_keywords->Release();\r
}\r
\r
-void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up)\r
+void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerErrorFunc efunc,void *ed)\r
{\r
+ _errfunc = efunc;\r
+ _errtarget = ed;\r
_sharedstate = ss;\r
_keywords = SQTable::Create(ss, 26);\r
ADD_KEYWORD(while, TK_WHILE);\r
ADD_KEYWORD(vargv,TK_VARGV);\r
ADD_KEYWORD(true,TK_TRUE);\r
ADD_KEYWORD(false,TK_FALSE);\r
+ ADD_KEYWORD(static,TK_STATIC);\r
\r
_readf = rg;\r
_up = up;\r
Next();\r
}\r
\r
+void SQLexer::Error(const SQChar *err)\r
+{\r
+ _errfunc(_errtarget,err);\r
+}\r
+\r
void SQLexer::Next()\r
{\r
SQInteger t = _readf(_up);\r
- if(t > MAX_CHAR) throw ParserException(_SC("Invalid character"));\r
+ if(t > MAX_CHAR) Error(_SC("Invalid character"));\r
if(t != 0) {\r
- _currdata = t;\r
+ _currdata = (LexChar)t;\r
return;\r
}\r
_currdata = SQUIRREL_EOB;\r
}\r
\r
-SQObjectPtr SQLexer::Tok2Str(int tok)\r
+const SQChar *SQLexer::Tok2Str(SQInteger tok)\r
{\r
SQObjectPtr itr, key, val;\r
- int nitr;\r
- while((nitr = _keywords->Next(itr, key, val)) != -1) {\r
+ SQInteger nitr;\r
+ while((nitr = _keywords->Next(false,itr, key, val)) != -1) {\r
itr = (SQInteger)nitr;\r
- if(((int)_integer(val)) == tok)\r
- return key;\r
+ if(((SQInteger)_integer(val)) == tok)\r
+ return _stringval(key);\r
}\r
- return SQObjectPtr();\r
+ return NULL;\r
}\r
\r
void SQLexer::LexBlockComment()\r
while(!done) {\r
switch(CUR_CHAR) {\r
case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;\r
- //case _SC('/'): { NEXT(); if(CUR_CHAR == _SC('*')) { nest++; NEXT(); }}; continue;\r
case _SC('\n'): _currentline++; NEXT(); continue;\r
- case SQUIRREL_EOB: throw ParserException(_SC("missing \"*/\" in comment"));\r
+ case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment"));\r
default: NEXT();\r
}\r
}\r
}\r
\r
-int SQLexer::Lex()\r
+SQInteger SQLexer::Lex()\r
{\r
_lasttokenline = _currentline;\r
while(CUR_CHAR != SQUIRREL_EOB) {\r
if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')}\r
else { NEXT(); RETURN_TOKEN(TK_NE); }\r
case _SC('@'): {\r
- int stype;\r
+ SQInteger stype;\r
NEXT(); \r
if(CUR_CHAR != _SC('"'))\r
- throw ParserException(_SC("string expected"));\r
+ Error(_SC("string expected"));\r
if((stype=ReadString('"',true))!=-1) {\r
RETURN_TOKEN(stype);\r
}\r
- throw ParserException(_SC("error parsing the string"));\r
+ Error(_SC("error parsing the string"));\r
}\r
case _SC('"'):\r
case _SC('\''): {\r
- int stype;\r
+ SQInteger stype;\r
if((stype=ReadString(CUR_CHAR,false))!=-1){\r
RETURN_TOKEN(stype);\r
}\r
- throw ParserException(_SC("error parsing the string"));\r
+ Error(_SC("error parsing the string"));\r
}\r
case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'):\r
case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'):\r
- {int ret = CUR_CHAR;\r
+ {SQInteger ret = CUR_CHAR;\r
NEXT(); RETURN_TOKEN(ret); }\r
case _SC('.'):\r
NEXT();\r
if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }\r
NEXT();\r
- if (CUR_CHAR != _SC('.')){ throw ParserException(_SC("invalid token '..'")); }\r
+ if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); }\r
NEXT();\r
RETURN_TOKEN(TK_VARPARAMS);\r
case _SC('&'):\r
return 0;\r
default:{\r
if (scisdigit(CUR_CHAR)) {\r
- int ret = ReadNumber();\r
+ SQInteger ret = ReadNumber();\r
RETURN_TOKEN(ret);\r
}\r
else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {\r
- int t = ReadID();\r
+ SQInteger t = ReadID();\r
RETURN_TOKEN(t);\r
}\r
else {\r
- int c = CUR_CHAR;\r
- if (sciscntrl(c)) throw ParserException(_SC("unexpected character(control)"));\r
+ SQInteger c = CUR_CHAR;\r
+ if (sciscntrl((int)c)) Error(_SC("unexpected character(control)"));\r
NEXT();\r
RETURN_TOKEN(c); \r
}\r
return 0; \r
}\r
\r
-int SQLexer::GetIDType(SQChar *s)\r
+SQInteger SQLexer::GetIDType(SQChar *s)\r
{\r
SQObjectPtr t;\r
if(_keywords->Get(SQString::Create(_sharedstate, s), t)) {\r
- return int(_integer(t));\r
+ return SQInteger(_integer(t));\r
}\r
return TK_IDENTIFIER;\r
}\r
\r
\r
-int SQLexer::ReadString(int ndelim,bool verbatim)\r
+SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim)\r
{\r
INIT_TEMP_STRING();\r
NEXT();\r
while(CUR_CHAR != ndelim) {\r
switch(CUR_CHAR) {\r
case SQUIRREL_EOB:\r
- throw ParserException(_SC("unfinished string"));\r
+ Error(_SC("unfinished string"));\r
return -1;\r
case _SC('\n'): \r
- if(!verbatim) throw ParserException(_SC("newline in a constant")); \r
+ if(!verbatim) Error(_SC("newline in a constant")); \r
APPEND_CHAR(CUR_CHAR); NEXT(); \r
+ _currentline++;\r
break;\r
case _SC('\\'):\r
if(verbatim) {\r
APPEND_CHAR('\\'); NEXT(); \r
}\r
else {\r
-\r
NEXT();\r
switch(CUR_CHAR) {\r
+ case _SC('x'): NEXT(); {\r
+ if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected")); \r
+ const SQInteger maxdigits = 4;\r
+ SQChar temp[maxdigits+1];\r
+ SQInteger n = 0;\r
+ while(isxdigit(CUR_CHAR) && n < maxdigits) {\r
+ temp[n] = CUR_CHAR;\r
+ n++;\r
+ NEXT();\r
+ }\r
+ temp[n] = 0;\r
+ SQChar *sTemp;\r
+ APPEND_CHAR((SQChar)scstrtoul(temp,&sTemp,16));\r
+ }\r
+ break;\r
case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break;\r
case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break;\r
case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break;\r
case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break;\r
case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;\r
default:\r
- throw ParserException(_SC("unrecognised escaper char"));\r
+ Error(_SC("unrecognised escaper char"));\r
break;\r
}\r
}\r
}\r
}\r
TERMINATE_BUFFER();\r
- int len = _longstr.size()-1;\r
+ SQInteger len = _longstr.size()-1;\r
if(ndelim == _SC('\'')) {\r
- if(len == 0) throw ParserException(_SC("empty constant"));\r
- if(len > 1) throw ParserException(_SC("constant too long"));\r
+ if(len == 0) Error(_SC("empty constant"));\r
+ if(len > 1) Error(_SC("constant too long"));\r
_nvalue = _longstr[0];\r
return TK_INTEGER;\r
}\r
return TK_STRING_LITERAL;\r
}\r
\r
-int isexponent(int c) { return c == 'e' || c=='E'; }\r
+void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res)\r
+{\r
+ *res = 0;\r
+ while(*s != 0)\r
+ {\r
+ if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0');\r
+ else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10);\r
+ else { assert(0); }\r
+ }\r
+}\r
+\r
+void LexInteger(const SQChar *s,SQUnsignedInteger *res)\r
+{\r
+ *res = 0;\r
+ while(*s != 0)\r
+ {\r
+ *res = (*res)*10+((*s++)-'0');\r
+ }\r
+}\r
\r
-int SQLexer::ReadNumber()\r
+SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; }\r
+#define MAX_HEX_DIGITS (sizeof(SQInteger)*2)\r
+SQInteger SQLexer::ReadNumber()\r
{\r
#define TINT 1\r
#define TFLOAT 2\r
#define THEX 3\r
#define TSCIENTIFIC 4\r
- int type = TINT, firstchar = CUR_CHAR;\r
- bool isfloat = false;\r
+ SQInteger type = TINT, firstchar = CUR_CHAR;\r
SQChar *sTemp;\r
INIT_TEMP_STRING();\r
NEXT();\r
APPEND_CHAR(CUR_CHAR);\r
NEXT();\r
}\r
- if(_longstr.size() > 8) throw ParserException(_SC("Hex number over 8 digits"));\r
+ if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number"));\r
}\r
else {\r
- APPEND_CHAR(firstchar);\r
+ APPEND_CHAR((int)firstchar);\r
while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {\r
if(CUR_CHAR == _SC('.')) type = TFLOAT;\r
if(isexponent(CUR_CHAR)) {\r
- if(type != TFLOAT) throw ParserException(_SC("invalid numeric format"));\r
+ if(type != TFLOAT) Error(_SC("invalid numeric format"));\r
type = TSCIENTIFIC;\r
APPEND_CHAR(CUR_CHAR);\r
NEXT();\r
APPEND_CHAR(CUR_CHAR);\r
NEXT();\r
}\r
- if(!scisdigit(CUR_CHAR)) throw ParserException(_SC("exponent expected"));\r
+ if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected"));\r
}\r
\r
APPEND_CHAR(CUR_CHAR);\r
_fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp);\r
return TK_FLOAT;\r
case TINT:\r
- _nvalue = (SQInteger)scatoi(&_longstr[0]);\r
+ LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue);\r
return TK_INTEGER;\r
case THEX:\r
- *((unsigned long *)&_nvalue) = scstrtoul(&_longstr[0],&sTemp,16);\r
+ LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);\r
return TK_INTEGER;\r
}\r
return 0;\r
}\r
\r
-int SQLexer::ReadID()\r
+SQInteger SQLexer::ReadID()\r
{\r
- int res, size = 0;\r
+ SQInteger res;\r
INIT_TEMP_STRING();\r
do {\r
APPEND_CHAR(CUR_CHAR);\r
} while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_'));\r
TERMINATE_BUFFER();\r
res = GetIDType(&_longstr[0]);\r
- if(res == TK_IDENTIFIER) {\r
+ if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) {\r
_svalue = &_longstr[0];\r
}\r
return res;\r