-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include <ctype.h>\r
-#include <stdlib.h>\r
-#include "sqtable.h"\r
-#include "sqstring.h"\r
-#include "sqcompiler.h"\r
-#include "sqlexer.h"\r
-\r
-#define CUR_CHAR (_currdata)\r
-#define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;}\r
-#define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB)\r
-#define NEXT() {Next();_currentcolumn++;}\r
-#define INIT_TEMP_STRING() { _longstr.resize(0);}\r
-#define APPEND_CHAR(c) { _longstr.push_back(c);}\r
-#define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));}\r
-#define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id))\r
-\r
-SQLexer::SQLexer(){}\r
-SQLexer::~SQLexer()\r
-{\r
- _keywords->Release();\r
-}\r
-\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(do, TK_DO);\r
- ADD_KEYWORD(if, TK_IF);\r
- ADD_KEYWORD(else, TK_ELSE);\r
- ADD_KEYWORD(break, TK_BREAK);\r
- ADD_KEYWORD(continue, TK_CONTINUE);\r
- ADD_KEYWORD(return, TK_RETURN);\r
- ADD_KEYWORD(null, TK_NULL);\r
- ADD_KEYWORD(function, TK_FUNCTION);\r
- ADD_KEYWORD(local, TK_LOCAL);\r
- ADD_KEYWORD(for, TK_FOR);\r
- ADD_KEYWORD(foreach, TK_FOREACH);\r
- ADD_KEYWORD(in, TK_IN);\r
- ADD_KEYWORD(typeof, TK_TYPEOF);\r
- ADD_KEYWORD(delegate, TK_DELEGATE);\r
- ADD_KEYWORD(delete, TK_DELETE);\r
- ADD_KEYWORD(try, TK_TRY);\r
- ADD_KEYWORD(catch, TK_CATCH);\r
- ADD_KEYWORD(throw, TK_THROW);\r
- ADD_KEYWORD(clone, TK_CLONE);\r
- ADD_KEYWORD(yield, TK_YIELD);\r
- ADD_KEYWORD(resume, TK_RESUME);\r
- ADD_KEYWORD(switch, TK_SWITCH);\r
- ADD_KEYWORD(case, TK_CASE);\r
- ADD_KEYWORD(default, TK_DEFAULT);\r
- ADD_KEYWORD(this, TK_THIS);\r
- ADD_KEYWORD(parent,TK_PARENT);\r
- ADD_KEYWORD(class,TK_CLASS);\r
- ADD_KEYWORD(extends,TK_EXTENDS);\r
- ADD_KEYWORD(constructor,TK_CONSTRUCTOR);\r
- ADD_KEYWORD(instanceof,TK_INSTANCEOF);\r
- ADD_KEYWORD(vargc,TK_VARGC);\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
- _lasttokenline = _currentline = 1;\r
- _currentcolumn = 0;\r
- _prevtoken = -1;\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) Error(_SC("Invalid character"));\r
- if(t != 0) {\r
- _currdata = (LexChar)t;\r
- return;\r
- }\r
- _currdata = SQUIRREL_EOB;\r
-}\r
-\r
-const SQChar *SQLexer::Tok2Str(SQInteger tok)\r
-{\r
- SQObjectPtr itr, key, val;\r
- SQInteger nitr;\r
- while((nitr = _keywords->Next(false,itr, key, val)) != -1) {\r
- itr = (SQInteger)nitr;\r
- if(((SQInteger)_integer(val)) == tok)\r
- return _stringval(key);\r
- }\r
- return NULL;\r
-}\r
-\r
-void SQLexer::LexBlockComment()\r
-{\r
- bool done = false;\r
- while(!done) {\r
- switch(CUR_CHAR) {\r
- case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;\r
- case _SC('\n'): _currentline++; NEXT(); continue;\r
- case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment"));\r
- default: NEXT();\r
- }\r
- }\r
-}\r
-\r
-SQInteger SQLexer::Lex()\r
-{\r
- _lasttokenline = _currentline;\r
- while(CUR_CHAR != SQUIRREL_EOB) {\r
- switch(CUR_CHAR){\r
- case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue;\r
- case _SC('\n'):\r
- _currentline++;\r
- _prevtoken=_curtoken;\r
- _curtoken=_SC('\n');\r
- NEXT();\r
- _currentcolumn=1;\r
- continue;\r
- case _SC('/'):\r
- NEXT();\r
- switch(CUR_CHAR){\r
- case _SC('*'):\r
- NEXT();\r
- LexBlockComment();\r
- continue; \r
- case _SC('/'):\r
- do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));\r
- continue;\r
- case _SC('='):\r
- NEXT();\r
- RETURN_TOKEN(TK_DIVEQ);\r
- continue;\r
- case _SC('>'):\r
- NEXT();\r
- RETURN_TOKEN(TK_ATTR_CLOSE);\r
- continue;\r
- default:\r
- RETURN_TOKEN('/');\r
- }\r
- case _SC('='):\r
- NEXT();\r
- if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') }\r
- else { NEXT(); RETURN_TOKEN(TK_EQ); }\r
- case _SC('<'):\r
- NEXT();\r
- if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) }\r
- else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); }\r
- else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); }\r
- else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); }\r
- //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); }\r
- else { RETURN_TOKEN('<') }\r
- case _SC('>'):\r
- NEXT();\r
- if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);}\r
- else if(CUR_CHAR == _SC('>')){ \r
- NEXT(); \r
- if(CUR_CHAR == _SC('>')){\r
- NEXT();\r
- RETURN_TOKEN(TK_USHIFTR);\r
- }\r
- RETURN_TOKEN(TK_SHIFTR);\r
- }\r
- else { RETURN_TOKEN('>') }\r
- case _SC('!'):\r
- NEXT();\r
- if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')}\r
- else { NEXT(); RETURN_TOKEN(TK_NE); }\r
- case _SC('@'): {\r
- SQInteger stype;\r
- NEXT(); \r
- if(CUR_CHAR != _SC('"'))\r
- Error(_SC("string expected"));\r
- if((stype=ReadString('"',true))!=-1) {\r
- RETURN_TOKEN(stype);\r
- }\r
- Error(_SC("error parsing the string"));\r
- }\r
- case _SC('"'):\r
- case _SC('\''): {\r
- SQInteger stype;\r
- if((stype=ReadString(CUR_CHAR,false))!=-1){\r
- RETURN_TOKEN(stype);\r
- }\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
- {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('.')){ Error(_SC("invalid token '..'")); }\r
- NEXT();\r
- RETURN_TOKEN(TK_VARPARAMS);\r
- case _SC('&'):\r
- NEXT();\r
- if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') }\r
- else { NEXT(); RETURN_TOKEN(TK_AND); }\r
- case _SC('|'):\r
- NEXT();\r
- if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') }\r
- else { NEXT(); RETURN_TOKEN(TK_OR); }\r
- case _SC(':'):\r
- NEXT();\r
- if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') }\r
- else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); }\r
- case _SC('*'):\r
- NEXT();\r
- if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);}\r
- else RETURN_TOKEN('*');\r
- case _SC('%'):\r
- NEXT();\r
- if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);}\r
- else RETURN_TOKEN('%');\r
- case _SC('-'):\r
- NEXT();\r
- if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);}\r
- else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);}\r
- else RETURN_TOKEN('-');\r
- case _SC('+'):\r
- NEXT();\r
- if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);}\r
- else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);}\r
- else RETURN_TOKEN('+');\r
- case SQUIRREL_EOB:\r
- return 0;\r
- default:{\r
- if (scisdigit(CUR_CHAR)) {\r
- SQInteger ret = ReadNumber();\r
- RETURN_TOKEN(ret);\r
- }\r
- else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {\r
- SQInteger t = ReadID();\r
- RETURN_TOKEN(t);\r
- }\r
- else {\r
- SQInteger c = CUR_CHAR;\r
- if (sciscntrl((int)c)) Error(_SC("unexpected character(control)"));\r
- NEXT();\r
- RETURN_TOKEN(c); \r
- }\r
- RETURN_TOKEN(0);\r
- }\r
- }\r
- }\r
- return 0; \r
-}\r
- \r
-SQInteger SQLexer::GetIDType(SQChar *s)\r
-{\r
- SQObjectPtr t;\r
- if(_keywords->Get(SQString::Create(_sharedstate, s), t)) {\r
- return SQInteger(_integer(t));\r
- }\r
- return TK_IDENTIFIER;\r
-}\r
-\r
-\r
-SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim)\r
-{\r
- INIT_TEMP_STRING();\r
- NEXT();\r
- if(IS_EOB()) return -1;\r
- for(;;) {\r
- while(CUR_CHAR != ndelim) {\r
- switch(CUR_CHAR) {\r
- case SQUIRREL_EOB:\r
- Error(_SC("unfinished string"));\r
- return -1;\r
- case _SC('\n'): \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
- 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('n'): APPEND_CHAR(_SC('\n')); NEXT(); break;\r
- case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break;\r
- case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break;\r
- case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break;\r
- case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break;\r
- case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break;\r
- case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break;\r
- case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;\r
- default:\r
- Error(_SC("unrecognised escaper char"));\r
- break;\r
- }\r
- }\r
- break;\r
- default:\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- }\r
- }\r
- NEXT();\r
- if(verbatim && CUR_CHAR == '"') { //double quotation\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- }\r
- else {\r
- break;\r
- }\r
- }\r
- TERMINATE_BUFFER();\r
- SQInteger len = _longstr.size()-1;\r
- if(ndelim == _SC('\'')) {\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
- _svalue = &_longstr[0];\r
- return TK_STRING_LITERAL;\r
-}\r
-\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
-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
- SQInteger type = TINT, firstchar = CUR_CHAR;\r
- SQChar *sTemp;\r
- INIT_TEMP_STRING();\r
- NEXT();\r
- if(firstchar == _SC('0') && toupper(CUR_CHAR) == _SC('X')) {\r
- NEXT();\r
- type = THEX;\r
- while(isxdigit(CUR_CHAR)) {\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- }\r
- if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number"));\r
- }\r
- else {\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) Error(_SC("invalid numeric format"));\r
- type = TSCIENTIFIC;\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- if(CUR_CHAR == '+' || CUR_CHAR == '-'){\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- }\r
- if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected"));\r
- }\r
- \r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- }\r
- }\r
- TERMINATE_BUFFER();\r
- switch(type) {\r
- case TSCIENTIFIC:\r
- case TFLOAT:\r
- _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp);\r
- return TK_FLOAT;\r
- case TINT:\r
- LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue);\r
- return TK_INTEGER;\r
- case THEX:\r
- LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);\r
- return TK_INTEGER;\r
- }\r
- return 0;\r
-}\r
-\r
-SQInteger SQLexer::ReadID()\r
-{\r
- SQInteger res;\r
- INIT_TEMP_STRING();\r
- do {\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_'));\r
- TERMINATE_BUFFER();\r
- res = GetIDType(&_longstr[0]);\r
- if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) {\r
- _svalue = &_longstr[0];\r
- }\r
- return res;\r
-}\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include "sqtable.h"
+#include "sqstring.h"
+#include "sqcompiler.h"
+#include "sqlexer.h"
+
+#define CUR_CHAR (_currdata)
+#define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;}
+#define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB)
+#define NEXT() {Next();_currentcolumn++;}
+#define INIT_TEMP_STRING() { _longstr.resize(0);}
+#define APPEND_CHAR(c) { _longstr.push_back(c);}
+#define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));}
+#define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id))
+
+SQLexer::SQLexer(){}
+SQLexer::~SQLexer()
+{
+ _keywords->Release();
+}
+
+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(do, TK_DO);
+ ADD_KEYWORD(if, TK_IF);
+ ADD_KEYWORD(else, TK_ELSE);
+ ADD_KEYWORD(break, TK_BREAK);
+ ADD_KEYWORD(continue, TK_CONTINUE);
+ ADD_KEYWORD(return, TK_RETURN);
+ ADD_KEYWORD(null, TK_NULL);
+ ADD_KEYWORD(function, TK_FUNCTION);
+ ADD_KEYWORD(local, TK_LOCAL);
+ ADD_KEYWORD(for, TK_FOR);
+ ADD_KEYWORD(foreach, TK_FOREACH);
+ ADD_KEYWORD(in, TK_IN);
+ ADD_KEYWORD(typeof, TK_TYPEOF);
+ ADD_KEYWORD(delegate, TK_DELEGATE);
+ ADD_KEYWORD(delete, TK_DELETE);
+ ADD_KEYWORD(try, TK_TRY);
+ ADD_KEYWORD(catch, TK_CATCH);
+ ADD_KEYWORD(throw, TK_THROW);
+ ADD_KEYWORD(clone, TK_CLONE);
+ ADD_KEYWORD(yield, TK_YIELD);
+ ADD_KEYWORD(resume, TK_RESUME);
+ ADD_KEYWORD(switch, TK_SWITCH);
+ ADD_KEYWORD(case, TK_CASE);
+ ADD_KEYWORD(default, TK_DEFAULT);
+ ADD_KEYWORD(this, TK_THIS);
+ ADD_KEYWORD(parent,TK_PARENT);
+ ADD_KEYWORD(class,TK_CLASS);
+ ADD_KEYWORD(extends,TK_EXTENDS);
+ ADD_KEYWORD(constructor,TK_CONSTRUCTOR);
+ ADD_KEYWORD(instanceof,TK_INSTANCEOF);
+ ADD_KEYWORD(vargc,TK_VARGC);
+ ADD_KEYWORD(vargv,TK_VARGV);
+ ADD_KEYWORD(true,TK_TRUE);
+ ADD_KEYWORD(false,TK_FALSE);
+ ADD_KEYWORD(static,TK_STATIC);
+
+ _readf = rg;
+ _up = up;
+ _lasttokenline = _currentline = 1;
+ _currentcolumn = 0;
+ _prevtoken = -1;
+ Next();
+}
+
+void SQLexer::Error(const SQChar *err)
+{
+ _errfunc(_errtarget,err);
+}
+
+void SQLexer::Next()
+{
+ SQInteger t = _readf(_up);
+ if(t > MAX_CHAR) Error(_SC("Invalid character"));
+ if(t != 0) {
+ _currdata = (LexChar)t;
+ return;
+ }
+ _currdata = SQUIRREL_EOB;
+}
+
+const SQChar *SQLexer::Tok2Str(SQInteger tok)
+{
+ SQObjectPtr itr, key, val;
+ SQInteger nitr;
+ while((nitr = _keywords->Next(false,itr, key, val)) != -1) {
+ itr = (SQInteger)nitr;
+ if(((SQInteger)_integer(val)) == tok)
+ return _stringval(key);
+ }
+ return NULL;
+}
+
+void SQLexer::LexBlockComment()
+{
+ bool done = false;
+ while(!done) {
+ switch(CUR_CHAR) {
+ case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;
+ case _SC('\n'): _currentline++; NEXT(); continue;
+ case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment"));
+ default: NEXT();
+ }
+ }
+}
+
+SQInteger SQLexer::Lex()
+{
+ _lasttokenline = _currentline;
+ while(CUR_CHAR != SQUIRREL_EOB) {
+ switch(CUR_CHAR){
+ case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue;
+ case _SC('\n'):
+ _currentline++;
+ _prevtoken=_curtoken;
+ _curtoken=_SC('\n');
+ NEXT();
+ _currentcolumn=1;
+ continue;
+ case _SC('/'):
+ NEXT();
+ switch(CUR_CHAR){
+ case _SC('*'):
+ NEXT();
+ LexBlockComment();
+ continue;
+ case _SC('/'):
+ do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));
+ continue;
+ case _SC('='):
+ NEXT();
+ RETURN_TOKEN(TK_DIVEQ);
+ continue;
+ case _SC('>'):
+ NEXT();
+ RETURN_TOKEN(TK_ATTR_CLOSE);
+ continue;
+ default:
+ RETURN_TOKEN('/');
+ }
+ case _SC('='):
+ NEXT();
+ if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') }
+ else { NEXT(); RETURN_TOKEN(TK_EQ); }
+ case _SC('<'):
+ NEXT();
+ if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) }
+ else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); }
+ else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); }
+ else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); }
+ //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); }
+ else { RETURN_TOKEN('<') }
+ case _SC('>'):
+ NEXT();
+ if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);}
+ else if(CUR_CHAR == _SC('>')){
+ NEXT();
+ if(CUR_CHAR == _SC('>')){
+ NEXT();
+ RETURN_TOKEN(TK_USHIFTR);
+ }
+ RETURN_TOKEN(TK_SHIFTR);
+ }
+ else { RETURN_TOKEN('>') }
+ case _SC('!'):
+ NEXT();
+ if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')}
+ else { NEXT(); RETURN_TOKEN(TK_NE); }
+ case _SC('@'): {
+ SQInteger stype;
+ NEXT();
+ if(CUR_CHAR != _SC('"'))
+ Error(_SC("string expected"));
+ if((stype=ReadString('"',true))!=-1) {
+ RETURN_TOKEN(stype);
+ }
+ Error(_SC("error parsing the string"));
+ }
+ case _SC('"'):
+ case _SC('\''): {
+ SQInteger stype;
+ if((stype=ReadString(CUR_CHAR,false))!=-1){
+ RETURN_TOKEN(stype);
+ }
+ 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('~'):
+ {SQInteger ret = CUR_CHAR;
+ NEXT(); RETURN_TOKEN(ret); }
+ case _SC('.'):
+ NEXT();
+ if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }
+ NEXT();
+ if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); }
+ NEXT();
+ RETURN_TOKEN(TK_VARPARAMS);
+ case _SC('&'):
+ NEXT();
+ if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') }
+ else { NEXT(); RETURN_TOKEN(TK_AND); }
+ case _SC('|'):
+ NEXT();
+ if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') }
+ else { NEXT(); RETURN_TOKEN(TK_OR); }
+ case _SC(':'):
+ NEXT();
+ if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') }
+ else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); }
+ case _SC('*'):
+ NEXT();
+ if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);}
+ else RETURN_TOKEN('*');
+ case _SC('%'):
+ NEXT();
+ if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);}
+ else RETURN_TOKEN('%');
+ case _SC('-'):
+ NEXT();
+ if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);}
+ else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);}
+ else RETURN_TOKEN('-');
+ case _SC('+'):
+ NEXT();
+ if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);}
+ else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);}
+ else RETURN_TOKEN('+');
+ case SQUIRREL_EOB:
+ return 0;
+ default:{
+ if (scisdigit(CUR_CHAR)) {
+ SQInteger ret = ReadNumber();
+ RETURN_TOKEN(ret);
+ }
+ else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {
+ SQInteger t = ReadID();
+ RETURN_TOKEN(t);
+ }
+ else {
+ SQInteger c = CUR_CHAR;
+ if (sciscntrl((int)c)) Error(_SC("unexpected character(control)"));
+ NEXT();
+ RETURN_TOKEN(c);
+ }
+ RETURN_TOKEN(0);
+ }
+ }
+ }
+ return 0;
+}
+
+SQInteger SQLexer::GetIDType(SQChar *s)
+{
+ SQObjectPtr t;
+ if(_keywords->Get(SQString::Create(_sharedstate, s), t)) {
+ return SQInteger(_integer(t));
+ }
+ return TK_IDENTIFIER;
+}
+
+
+SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim)
+{
+ INIT_TEMP_STRING();
+ NEXT();
+ if(IS_EOB()) return -1;
+ for(;;) {
+ while(CUR_CHAR != ndelim) {
+ switch(CUR_CHAR) {
+ case SQUIRREL_EOB:
+ Error(_SC("unfinished string"));
+ return -1;
+ 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();
+ }
+ 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('n'): APPEND_CHAR(_SC('\n')); NEXT(); break;
+ case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break;
+ case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break;
+ case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break;
+ case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break;
+ case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break;
+ case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break;
+ case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;
+ default:
+ Error(_SC("unrecognised escaper char"));
+ break;
+ }
+ }
+ break;
+ default:
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ }
+ NEXT();
+ if(verbatim && CUR_CHAR == '"') { //double quotation
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ else {
+ break;
+ }
+ }
+ TERMINATE_BUFFER();
+ SQInteger len = _longstr.size()-1;
+ if(ndelim == _SC('\'')) {
+ if(len == 0) Error(_SC("empty constant"));
+ if(len > 1) Error(_SC("constant too long"));
+ _nvalue = _longstr[0];
+ return TK_INTEGER;
+ }
+ _svalue = &_longstr[0];
+ return TK_STRING_LITERAL;
+}
+
+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); }
+ }
+}
+
+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
+ SQInteger type = TINT, firstchar = CUR_CHAR;
+ SQChar *sTemp;
+ INIT_TEMP_STRING();
+ NEXT();
+ if(firstchar == _SC('0') && toupper(CUR_CHAR) == _SC('X')) {
+ NEXT();
+ type = THEX;
+ while(isxdigit(CUR_CHAR)) {
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number"));
+ }
+ else {
+ 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) Error(_SC("invalid numeric format"));
+ type = TSCIENTIFIC;
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ if(CUR_CHAR == '+' || CUR_CHAR == '-'){
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected"));
+ }
+
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ }
+ TERMINATE_BUFFER();
+ switch(type) {
+ case TSCIENTIFIC:
+ case TFLOAT:
+ _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp);
+ return TK_FLOAT;
+ case TINT:
+ LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
+ return TK_INTEGER;
+ case THEX:
+ LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
+ return TK_INTEGER;
+ }
+ return 0;
+}
+
+SQInteger SQLexer::ReadID()
+{
+ SQInteger res;
+ INIT_TEMP_STRING();
+ do {
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_'));
+ TERMINATE_BUFFER();
+ res = GetIDType(&_longstr[0]);
+ if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) {
+ _svalue = &_longstr[0];
+ }
+ return res;
+}