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