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)
30 _keywords = SQTable::Create(ss, 26);
31 ADD_KEYWORD(while, TK_WHILE);
32 ADD_KEYWORD(do, TK_DO);
33 ADD_KEYWORD(if, TK_IF);
34 ADD_KEYWORD(else, TK_ELSE);
35 ADD_KEYWORD(break, TK_BREAK);
36 ADD_KEYWORD(continue, TK_CONTINUE);
37 ADD_KEYWORD(return, TK_RETURN);
38 ADD_KEYWORD(null, TK_NULL);
39 ADD_KEYWORD(function, TK_FUNCTION);
40 ADD_KEYWORD(local, TK_LOCAL);
41 ADD_KEYWORD(for, TK_FOR);
42 ADD_KEYWORD(foreach, TK_FOREACH);
43 ADD_KEYWORD(in, TK_IN);
44 ADD_KEYWORD(typeof, TK_TYPEOF);
45 ADD_KEYWORD(delegate, TK_DELEGATE);
46 ADD_KEYWORD(delete, TK_DELETE);
47 ADD_KEYWORD(try, TK_TRY);
48 ADD_KEYWORD(catch, TK_CATCH);
49 ADD_KEYWORD(throw, TK_THROW);
50 ADD_KEYWORD(clone, TK_CLONE);
51 ADD_KEYWORD(yield, TK_YIELD);
52 ADD_KEYWORD(resume, TK_RESUME);
53 ADD_KEYWORD(switch, TK_SWITCH);
54 ADD_KEYWORD(case, TK_CASE);
55 ADD_KEYWORD(default, TK_DEFAULT);
56 ADD_KEYWORD(this, TK_THIS);
57 ADD_KEYWORD(parent,TK_PARENT);
58 ADD_KEYWORD(class,TK_CLASS);
59 ADD_KEYWORD(extends,TK_EXTENDS);
60 ADD_KEYWORD(constructor,TK_CONSTRUCTOR);
61 ADD_KEYWORD(instanceof,TK_INSTANCEOF);
62 ADD_KEYWORD(vargc,TK_VARGC);
63 ADD_KEYWORD(vargv,TK_VARGV);
64 ADD_KEYWORD(true,TK_TRUE);
65 ADD_KEYWORD(false,TK_FALSE);
69 _lasttokenline = _currentline = 1;
77 SQInteger t = _readf(_up);
78 if(t > MAX_CHAR) throw ParserException(_SC("Invalid character"));
83 _currdata = SQUIRREL_EOB;
86 SQObjectPtr SQLexer::Tok2Str(int tok)
88 SQObjectPtr itr, key, val;
90 while((nitr = _keywords->Next(itr, key, val)) != -1) {
91 itr = (SQInteger)nitr;
92 if(((int)_integer(val)) == tok)
98 void SQLexer::LexBlockComment()
103 case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;
104 //case _SC('/'): { NEXT(); if(CUR_CHAR == _SC('*')) { nest++; NEXT(); }}; continue;
105 case _SC('\n'): _currentline++; NEXT(); continue;
106 case SQUIRREL_EOB: throw ParserException(_SC("missing \"*/\" in comment"));
114 _lasttokenline = _currentline;
115 while(CUR_CHAR != SQUIRREL_EOB) {
117 case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue;
120 _prevtoken=_curtoken;
133 do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));
137 RETURN_TOKEN(TK_DIVEQ);
141 RETURN_TOKEN(TK_ATTR_CLOSE);
148 if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') }
149 else { NEXT(); RETURN_TOKEN(TK_EQ); }
152 if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) }
153 else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); }
154 else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); }
155 else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); }
156 //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); }
157 else { RETURN_TOKEN('<') }
160 if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);}
161 else if(CUR_CHAR == _SC('>')){
163 if(CUR_CHAR == _SC('>')){
165 RETURN_TOKEN(TK_USHIFTR);
167 RETURN_TOKEN(TK_SHIFTR);
169 else { RETURN_TOKEN('>') }
172 if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')}
173 else { NEXT(); RETURN_TOKEN(TK_NE); }
177 if(CUR_CHAR != _SC('"'))
178 throw ParserException(_SC("string expected"));
179 if((stype=ReadString('"',true))!=-1) {
182 throw ParserException(_SC("error parsing the string"));
187 if((stype=ReadString(CUR_CHAR,false))!=-1){
190 throw ParserException(_SC("error parsing the string"));
192 case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'):
193 case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'):
195 NEXT(); RETURN_TOKEN(ret); }
198 if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }
200 if (CUR_CHAR != _SC('.')){ throw ParserException(_SC("invalid token '..'")); }
202 RETURN_TOKEN(TK_VARPARAMS);
205 if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') }
206 else { NEXT(); RETURN_TOKEN(TK_AND); }
209 if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') }
210 else { NEXT(); RETURN_TOKEN(TK_OR); }
213 if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') }
214 else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); }
217 if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);}
218 else RETURN_TOKEN('*');
221 if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);}
222 else RETURN_TOKEN('%');
225 if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);}
226 else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);}
227 else RETURN_TOKEN('-');
230 if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);}
231 else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);}
232 else RETURN_TOKEN('+');
236 if (scisdigit(CUR_CHAR)) {
237 int ret = ReadNumber();
240 else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {
246 if (sciscntrl(c)) throw ParserException(_SC("unexpected character(control)"));
257 int SQLexer::GetIDType(SQChar *s)
260 if(_keywords->Get(SQString::Create(_sharedstate, s), t)) {
261 return int(_integer(t));
263 return TK_IDENTIFIER;
267 int SQLexer::ReadString(int ndelim,bool verbatim)
271 if(IS_EOB()) return -1;
273 while(CUR_CHAR != ndelim) {
276 throw ParserException(_SC("unfinished string"));
279 if(!verbatim) throw ParserException(_SC("newline in a constant"));
280 APPEND_CHAR(CUR_CHAR); NEXT();
284 APPEND_CHAR('\\'); NEXT();
290 case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break;
291 case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break;
292 case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break;
293 case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break;
294 case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break;
295 case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break;
296 case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break;
297 case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break;
298 case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break;
299 case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break;
300 case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;
302 throw ParserException(_SC("unrecognised escaper char"));
308 APPEND_CHAR(CUR_CHAR);
313 if(verbatim && CUR_CHAR == '"') { //double quotation
314 APPEND_CHAR(CUR_CHAR);
322 int len = _longstr.size()-1;
323 if(ndelim == _SC('\'')) {
324 if(len == 0) throw ParserException(_SC("empty constant"));
325 if(len > 1) throw ParserException(_SC("constant too long"));
326 _nvalue = _longstr[0];
329 _svalue = &_longstr[0];
330 return TK_STRING_LITERAL;
333 int isexponent(int c) { return c == 'e' || c=='E'; }
335 int SQLexer::ReadNumber()
340 #define TSCIENTIFIC 4
341 int type = TINT, firstchar = CUR_CHAR;
342 //bool isfloat = false;
346 if(firstchar == _SC('0') && toupper(CUR_CHAR) == _SC('X')) {
349 while(isxdigit(CUR_CHAR)) {
350 APPEND_CHAR(CUR_CHAR);
353 if(_longstr.size() > 8) throw ParserException(_SC("Hex number over 8 digits"));
356 APPEND_CHAR(firstchar);
357 while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {
358 if(CUR_CHAR == _SC('.')) type = TFLOAT;
359 if(isexponent(CUR_CHAR)) {
360 if(type != TFLOAT) throw ParserException(_SC("invalid numeric format"));
362 APPEND_CHAR(CUR_CHAR);
364 if(CUR_CHAR == '+' || CUR_CHAR == '-'){
365 APPEND_CHAR(CUR_CHAR);
368 if(!scisdigit(CUR_CHAR)) throw ParserException(_SC("exponent expected"));
371 APPEND_CHAR(CUR_CHAR);
379 _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp);
382 _nvalue = (SQInteger)scatoi(&_longstr[0]);
385 *((unsigned long *)&_nvalue) = scstrtoul(&_longstr[0],&sTemp,16);
391 int SQLexer::ReadID()
397 APPEND_CHAR(CUR_CHAR);
399 } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_'));
401 res = GetIDType(&_longstr[0]);
402 if(res == TK_IDENTIFIER) {
403 _svalue = &_longstr[0];