2 see copyright notice in squirrel.h
4 #include "sqpcheader.h"
9 #include "sqcompiler.h"
12 #define CUR_CHAR (_currdata)
13 #define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;}
14 #define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB)
15 #define NEXT() {Next();_currentcolumn++;}
16 #define INIT_TEMP_STRING() { _longstr.resize(0);}
17 #define APPEND_CHAR(c) { _longstr.push_back(c);}
18 #define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));}
19 #define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id))
27 void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerErrorFunc efunc,void *ed)
32 _keywords = SQTable::Create(ss, 26);
33 ADD_KEYWORD(while, TK_WHILE);
34 ADD_KEYWORD(do, TK_DO);
35 ADD_KEYWORD(if, TK_IF);
36 ADD_KEYWORD(else, TK_ELSE);
37 ADD_KEYWORD(break, TK_BREAK);
38 ADD_KEYWORD(continue, TK_CONTINUE);
39 ADD_KEYWORD(return, TK_RETURN);
40 ADD_KEYWORD(null, TK_NULL);
41 ADD_KEYWORD(function, TK_FUNCTION);
42 ADD_KEYWORD(local, TK_LOCAL);
43 ADD_KEYWORD(for, TK_FOR);
44 ADD_KEYWORD(foreach, TK_FOREACH);
45 ADD_KEYWORD(in, TK_IN);
46 ADD_KEYWORD(typeof, TK_TYPEOF);
47 ADD_KEYWORD(delegate, TK_DELEGATE);
48 ADD_KEYWORD(delete, TK_DELETE);
49 ADD_KEYWORD(try, TK_TRY);
50 ADD_KEYWORD(catch, TK_CATCH);
51 ADD_KEYWORD(throw, TK_THROW);
52 ADD_KEYWORD(clone, TK_CLONE);
53 ADD_KEYWORD(yield, TK_YIELD);
54 ADD_KEYWORD(resume, TK_RESUME);
55 ADD_KEYWORD(switch, TK_SWITCH);
56 ADD_KEYWORD(case, TK_CASE);
57 ADD_KEYWORD(default, TK_DEFAULT);
58 ADD_KEYWORD(this, TK_THIS);
59 ADD_KEYWORD(parent,TK_PARENT);
60 ADD_KEYWORD(class,TK_CLASS);
61 ADD_KEYWORD(extends,TK_EXTENDS);
62 ADD_KEYWORD(constructor,TK_CONSTRUCTOR);
63 ADD_KEYWORD(instanceof,TK_INSTANCEOF);
64 ADD_KEYWORD(vargc,TK_VARGC);
65 ADD_KEYWORD(vargv,TK_VARGV);
66 ADD_KEYWORD(true,TK_TRUE);
67 ADD_KEYWORD(false,TK_FALSE);
68 ADD_KEYWORD(static,TK_STATIC);
69 ADD_KEYWORD(enum,TK_ENUM);
70 ADD_KEYWORD(const,TK_CONST);
74 _lasttokenline = _currentline = 1;
80 void SQLexer::Error(const SQChar *err)
82 _errfunc(_errtarget,err);
87 SQInteger t = _readf(_up);
88 if(t > MAX_CHAR) Error(_SC("Invalid character"));
90 _currdata = (LexChar)t;
93 _currdata = SQUIRREL_EOB;
96 const SQChar *SQLexer::Tok2Str(SQInteger tok)
98 SQObjectPtr itr, key, val;
100 while((nitr = _keywords->Next(false,itr, key, val)) != -1) {
101 itr = (SQInteger)nitr;
102 if(((SQInteger)_integer(val)) == tok)
103 return _stringval(key);
108 void SQLexer::LexBlockComment()
113 case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;
114 case _SC('\n'): _currentline++; NEXT(); continue;
115 case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment"));
121 SQInteger SQLexer::Lex()
123 _lasttokenline = _currentline;
124 while(CUR_CHAR != SQUIRREL_EOB) {
126 case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue;
129 _prevtoken=_curtoken;
142 do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));
146 RETURN_TOKEN(TK_DIVEQ);
150 RETURN_TOKEN(TK_ATTR_CLOSE);
157 if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') }
158 else { NEXT(); RETURN_TOKEN(TK_EQ); }
161 if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) }
162 else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); }
163 else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); }
164 else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); }
165 //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); }
166 else { RETURN_TOKEN('<') }
169 if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);}
170 else if(CUR_CHAR == _SC('>')){
172 if(CUR_CHAR == _SC('>')){
174 RETURN_TOKEN(TK_USHIFTR);
176 RETURN_TOKEN(TK_SHIFTR);
178 else { RETURN_TOKEN('>') }
181 if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')}
182 else { NEXT(); RETURN_TOKEN(TK_NE); }
186 if(CUR_CHAR != _SC('"'))
187 Error(_SC("string expected"));
188 if((stype=ReadString('"',true))!=-1) {
191 Error(_SC("error parsing the string"));
196 if((stype=ReadString(CUR_CHAR,false))!=-1){
199 Error(_SC("error parsing the string"));
201 case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'):
202 case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'):
203 {SQInteger ret = CUR_CHAR;
204 NEXT(); RETURN_TOKEN(ret); }
207 if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }
209 if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); }
211 RETURN_TOKEN(TK_VARPARAMS);
214 if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') }
215 else { NEXT(); RETURN_TOKEN(TK_AND); }
218 if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') }
219 else { NEXT(); RETURN_TOKEN(TK_OR); }
222 if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') }
223 else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); }
226 if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);}
227 else RETURN_TOKEN('*');
230 if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);}
231 else RETURN_TOKEN('%');
234 if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);}
235 else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);}
236 else RETURN_TOKEN('-');
239 if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);}
240 else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);}
241 else RETURN_TOKEN('+');
245 if (scisdigit(CUR_CHAR)) {
246 SQInteger ret = ReadNumber();
249 else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {
250 SQInteger t = ReadID();
254 SQInteger c = CUR_CHAR;
255 if (sciscntrl((int)c)) Error(_SC("unexpected character(control)"));
266 SQInteger SQLexer::GetIDType(SQChar *s)
269 if(_keywords->Get(SQString::Create(_sharedstate, s), t)) {
270 return SQInteger(_integer(t));
272 return TK_IDENTIFIER;
276 SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim)
280 if(IS_EOB()) return -1;
282 while(CUR_CHAR != ndelim) {
285 Error(_SC("unfinished string"));
288 if(!verbatim) Error(_SC("newline in a constant"));
289 APPEND_CHAR(CUR_CHAR); NEXT();
294 APPEND_CHAR('\\'); NEXT();
299 case _SC('x'): NEXT(); {
300 if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected"));
301 const SQInteger maxdigits = 4;
302 SQChar temp[maxdigits+1];
304 while(isxdigit(CUR_CHAR) && n < maxdigits) {
311 APPEND_CHAR((SQChar)scstrtoul(temp,&sTemp,16));
314 case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break;
315 case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break;
316 case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break;
317 case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break;
318 case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break;
319 case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break;
320 case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break;
321 case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break;
322 case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break;
323 case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break;
324 case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;
326 Error(_SC("unrecognised escaper char"));
332 APPEND_CHAR(CUR_CHAR);
337 if(verbatim && CUR_CHAR == '"') { //double quotation
338 APPEND_CHAR(CUR_CHAR);
346 SQInteger len = _longstr.size()-1;
347 if(ndelim == _SC('\'')) {
348 if(len == 0) Error(_SC("empty constant"));
349 if(len > 1) Error(_SC("constant too long"));
350 _nvalue = _longstr[0];
353 _svalue = &_longstr[0];
354 return TK_STRING_LITERAL;
357 void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res)
362 if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0');
363 else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10);
368 void LexInteger(const SQChar *s,SQUnsignedInteger *res)
373 *res = (*res)*10+((*s++)-'0');
377 SQInteger scisodigit(SQInteger c) { return c >= _SC('0') && c <= _SC('7'); }
379 void LexOctal(const SQChar *s,SQUnsignedInteger *res)
384 if(scisodigit(*s)) *res = (*res)*8+((*s++)-'0');
389 SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; }
392 #define MAX_HEX_DIGITS (sizeof(SQInteger)*2)
393 SQInteger SQLexer::ReadNumber()
398 #define TSCIENTIFIC 4
400 SQInteger type = TINT, firstchar = CUR_CHAR;
404 if(firstchar == _SC('0') && (toupper(CUR_CHAR) == _SC('X') || scisodigit(CUR_CHAR)) ) {
405 if(scisodigit(CUR_CHAR)) {
407 while(scisodigit(CUR_CHAR)) {
408 APPEND_CHAR(CUR_CHAR);
411 if(scisdigit(CUR_CHAR)) Error(_SC("invalid octal number"));
416 while(isxdigit(CUR_CHAR)) {
417 APPEND_CHAR(CUR_CHAR);
420 if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number"));
424 APPEND_CHAR((int)firstchar);
425 while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {
426 if(CUR_CHAR == _SC('.')) type = TFLOAT;
427 if(isexponent(CUR_CHAR)) {
428 if(type != TFLOAT) Error(_SC("invalid numeric format"));
430 APPEND_CHAR(CUR_CHAR);
432 if(CUR_CHAR == '+' || CUR_CHAR == '-'){
433 APPEND_CHAR(CUR_CHAR);
436 if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected"));
439 APPEND_CHAR(CUR_CHAR);
447 _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp);
450 LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
453 LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
456 LexOctal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
462 SQInteger SQLexer::ReadID()
467 APPEND_CHAR(CUR_CHAR);
469 } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_'));
471 res = GetIDType(&_longstr[0]);
472 if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) {
473 _svalue = &_longstr[0];