The Squirrel interpreter. See http://www.squirrel-lang.org/
squirrel/sqlexer.cpp@3:7268a3ceaffc, 2014-12-16 (annotated)
- Committer:
- jhnwkmn
- Date:
- Tue Dec 16 11:39:42 2014 +0000
- Revision:
- 3:7268a3ceaffc
- Parent:
- 0:97a4f8cc534c
Accepts \r as line terminator as well.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jhnwkmn | 0:97a4f8cc534c | 1 | /* |
jhnwkmn | 0:97a4f8cc534c | 2 | see copyright notice in squirrel.h |
jhnwkmn | 0:97a4f8cc534c | 3 | */ |
jhnwkmn | 0:97a4f8cc534c | 4 | #include "sqpcheader.h" |
jhnwkmn | 0:97a4f8cc534c | 5 | #include <ctype.h> |
jhnwkmn | 0:97a4f8cc534c | 6 | #include <stdlib.h> |
jhnwkmn | 0:97a4f8cc534c | 7 | #include "sqtable.h" |
jhnwkmn | 0:97a4f8cc534c | 8 | #include "sqstring.h" |
jhnwkmn | 0:97a4f8cc534c | 9 | #include "sqcompiler.h" |
jhnwkmn | 0:97a4f8cc534c | 10 | #include "sqlexer.h" |
jhnwkmn | 0:97a4f8cc534c | 11 | |
jhnwkmn | 0:97a4f8cc534c | 12 | #define CUR_CHAR (_currdata) |
jhnwkmn | 0:97a4f8cc534c | 13 | #define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;} |
jhnwkmn | 0:97a4f8cc534c | 14 | #define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB) |
jhnwkmn | 0:97a4f8cc534c | 15 | #define NEXT() {Next();_currentcolumn++;} |
jhnwkmn | 0:97a4f8cc534c | 16 | #define INIT_TEMP_STRING() { _longstr.resize(0);} |
jhnwkmn | 0:97a4f8cc534c | 17 | #define APPEND_CHAR(c) { _longstr.push_back(c);} |
jhnwkmn | 0:97a4f8cc534c | 18 | #define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));} |
jhnwkmn | 0:97a4f8cc534c | 19 | #define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id)) |
jhnwkmn | 0:97a4f8cc534c | 20 | |
jhnwkmn | 0:97a4f8cc534c | 21 | SQLexer::SQLexer(){} |
jhnwkmn | 0:97a4f8cc534c | 22 | SQLexer::~SQLexer() |
jhnwkmn | 0:97a4f8cc534c | 23 | { |
jhnwkmn | 0:97a4f8cc534c | 24 | _keywords->Release(); |
jhnwkmn | 0:97a4f8cc534c | 25 | } |
jhnwkmn | 0:97a4f8cc534c | 26 | |
jhnwkmn | 0:97a4f8cc534c | 27 | void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerErrorFunc efunc,void *ed) |
jhnwkmn | 0:97a4f8cc534c | 28 | { |
jhnwkmn | 0:97a4f8cc534c | 29 | _errfunc = efunc; |
jhnwkmn | 0:97a4f8cc534c | 30 | _errtarget = ed; |
jhnwkmn | 0:97a4f8cc534c | 31 | _sharedstate = ss; |
jhnwkmn | 0:97a4f8cc534c | 32 | _keywords = SQTable::Create(ss, 26); |
jhnwkmn | 0:97a4f8cc534c | 33 | ADD_KEYWORD(while, TK_WHILE); |
jhnwkmn | 0:97a4f8cc534c | 34 | ADD_KEYWORD(do, TK_DO); |
jhnwkmn | 0:97a4f8cc534c | 35 | ADD_KEYWORD(if, TK_IF); |
jhnwkmn | 0:97a4f8cc534c | 36 | ADD_KEYWORD(else, TK_ELSE); |
jhnwkmn | 0:97a4f8cc534c | 37 | ADD_KEYWORD(break, TK_BREAK); |
jhnwkmn | 0:97a4f8cc534c | 38 | ADD_KEYWORD(continue, TK_CONTINUE); |
jhnwkmn | 0:97a4f8cc534c | 39 | ADD_KEYWORD(return, TK_RETURN); |
jhnwkmn | 0:97a4f8cc534c | 40 | ADD_KEYWORD(null, TK_NULL); |
jhnwkmn | 0:97a4f8cc534c | 41 | ADD_KEYWORD(function, TK_FUNCTION); |
jhnwkmn | 0:97a4f8cc534c | 42 | ADD_KEYWORD(local, TK_LOCAL); |
jhnwkmn | 0:97a4f8cc534c | 43 | ADD_KEYWORD(for, TK_FOR); |
jhnwkmn | 0:97a4f8cc534c | 44 | ADD_KEYWORD(foreach, TK_FOREACH); |
jhnwkmn | 0:97a4f8cc534c | 45 | ADD_KEYWORD(in, TK_IN); |
jhnwkmn | 0:97a4f8cc534c | 46 | ADD_KEYWORD(typeof, TK_TYPEOF); |
jhnwkmn | 0:97a4f8cc534c | 47 | ADD_KEYWORD(base, TK_BASE); |
jhnwkmn | 0:97a4f8cc534c | 48 | ADD_KEYWORD(delete, TK_DELETE); |
jhnwkmn | 0:97a4f8cc534c | 49 | ADD_KEYWORD(try, TK_TRY); |
jhnwkmn | 0:97a4f8cc534c | 50 | ADD_KEYWORD(catch, TK_CATCH); |
jhnwkmn | 0:97a4f8cc534c | 51 | ADD_KEYWORD(throw, TK_THROW); |
jhnwkmn | 0:97a4f8cc534c | 52 | ADD_KEYWORD(clone, TK_CLONE); |
jhnwkmn | 0:97a4f8cc534c | 53 | ADD_KEYWORD(yield, TK_YIELD); |
jhnwkmn | 0:97a4f8cc534c | 54 | ADD_KEYWORD(resume, TK_RESUME); |
jhnwkmn | 0:97a4f8cc534c | 55 | ADD_KEYWORD(switch, TK_SWITCH); |
jhnwkmn | 0:97a4f8cc534c | 56 | ADD_KEYWORD(case, TK_CASE); |
jhnwkmn | 0:97a4f8cc534c | 57 | ADD_KEYWORD(default, TK_DEFAULT); |
jhnwkmn | 0:97a4f8cc534c | 58 | ADD_KEYWORD(this, TK_THIS); |
jhnwkmn | 0:97a4f8cc534c | 59 | ADD_KEYWORD(class,TK_CLASS); |
jhnwkmn | 0:97a4f8cc534c | 60 | ADD_KEYWORD(extends,TK_EXTENDS); |
jhnwkmn | 0:97a4f8cc534c | 61 | ADD_KEYWORD(constructor,TK_CONSTRUCTOR); |
jhnwkmn | 0:97a4f8cc534c | 62 | ADD_KEYWORD(instanceof,TK_INSTANCEOF); |
jhnwkmn | 0:97a4f8cc534c | 63 | ADD_KEYWORD(true,TK_TRUE); |
jhnwkmn | 0:97a4f8cc534c | 64 | ADD_KEYWORD(false,TK_FALSE); |
jhnwkmn | 0:97a4f8cc534c | 65 | ADD_KEYWORD(static,TK_STATIC); |
jhnwkmn | 0:97a4f8cc534c | 66 | ADD_KEYWORD(enum,TK_ENUM); |
jhnwkmn | 0:97a4f8cc534c | 67 | ADD_KEYWORD(const,TK_CONST); |
jhnwkmn | 0:97a4f8cc534c | 68 | |
jhnwkmn | 0:97a4f8cc534c | 69 | _readf = rg; |
jhnwkmn | 0:97a4f8cc534c | 70 | _up = up; |
jhnwkmn | 0:97a4f8cc534c | 71 | _lasttokenline = _currentline = 1; |
jhnwkmn | 0:97a4f8cc534c | 72 | _currentcolumn = 0; |
jhnwkmn | 0:97a4f8cc534c | 73 | _prevtoken = -1; |
jhnwkmn | 0:97a4f8cc534c | 74 | _reached_eof = SQFalse; |
jhnwkmn | 0:97a4f8cc534c | 75 | Next(); |
jhnwkmn | 0:97a4f8cc534c | 76 | } |
jhnwkmn | 0:97a4f8cc534c | 77 | |
jhnwkmn | 0:97a4f8cc534c | 78 | void SQLexer::Error(const SQChar *err) |
jhnwkmn | 0:97a4f8cc534c | 79 | { |
jhnwkmn | 0:97a4f8cc534c | 80 | _errfunc(_errtarget,err); |
jhnwkmn | 0:97a4f8cc534c | 81 | } |
jhnwkmn | 0:97a4f8cc534c | 82 | |
jhnwkmn | 0:97a4f8cc534c | 83 | void SQLexer::Next() |
jhnwkmn | 0:97a4f8cc534c | 84 | { |
jhnwkmn | 0:97a4f8cc534c | 85 | SQInteger t = _readf(_up); |
jhnwkmn | 0:97a4f8cc534c | 86 | if(t > MAX_CHAR) Error(_SC("Invalid character")); |
jhnwkmn | 0:97a4f8cc534c | 87 | if(t != 0) { |
jhnwkmn | 0:97a4f8cc534c | 88 | _currdata = (LexChar)t; |
jhnwkmn | 0:97a4f8cc534c | 89 | return; |
jhnwkmn | 0:97a4f8cc534c | 90 | } |
jhnwkmn | 0:97a4f8cc534c | 91 | _currdata = SQUIRREL_EOB; |
jhnwkmn | 0:97a4f8cc534c | 92 | _reached_eof = SQTrue; |
jhnwkmn | 0:97a4f8cc534c | 93 | } |
jhnwkmn | 0:97a4f8cc534c | 94 | |
jhnwkmn | 0:97a4f8cc534c | 95 | const SQChar *SQLexer::Tok2Str(SQInteger tok) |
jhnwkmn | 0:97a4f8cc534c | 96 | { |
jhnwkmn | 0:97a4f8cc534c | 97 | SQObjectPtr itr, key, val; |
jhnwkmn | 0:97a4f8cc534c | 98 | SQInteger nitr; |
jhnwkmn | 0:97a4f8cc534c | 99 | while((nitr = _keywords->Next(false,itr, key, val)) != -1) { |
jhnwkmn | 0:97a4f8cc534c | 100 | itr = (SQInteger)nitr; |
jhnwkmn | 0:97a4f8cc534c | 101 | if(((SQInteger)_integer(val)) == tok) |
jhnwkmn | 0:97a4f8cc534c | 102 | return _stringval(key); |
jhnwkmn | 0:97a4f8cc534c | 103 | } |
jhnwkmn | 0:97a4f8cc534c | 104 | return NULL; |
jhnwkmn | 0:97a4f8cc534c | 105 | } |
jhnwkmn | 0:97a4f8cc534c | 106 | |
jhnwkmn | 0:97a4f8cc534c | 107 | void SQLexer::LexBlockComment() |
jhnwkmn | 0:97a4f8cc534c | 108 | { |
jhnwkmn | 0:97a4f8cc534c | 109 | bool done = false; |
jhnwkmn | 0:97a4f8cc534c | 110 | while(!done) { |
jhnwkmn | 0:97a4f8cc534c | 111 | switch(CUR_CHAR) { |
jhnwkmn | 0:97a4f8cc534c | 112 | case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue; |
jhnwkmn | 0:97a4f8cc534c | 113 | case _SC('\n'): _currentline++; NEXT(); continue; |
jhnwkmn | 0:97a4f8cc534c | 114 | case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment")); |
jhnwkmn | 0:97a4f8cc534c | 115 | default: NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 116 | } |
jhnwkmn | 0:97a4f8cc534c | 117 | } |
jhnwkmn | 0:97a4f8cc534c | 118 | } |
jhnwkmn | 0:97a4f8cc534c | 119 | void SQLexer::LexLineComment() |
jhnwkmn | 0:97a4f8cc534c | 120 | { |
jhnwkmn | 0:97a4f8cc534c | 121 | do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB())); |
jhnwkmn | 0:97a4f8cc534c | 122 | } |
jhnwkmn | 0:97a4f8cc534c | 123 | |
jhnwkmn | 0:97a4f8cc534c | 124 | SQInteger SQLexer::Lex() |
jhnwkmn | 0:97a4f8cc534c | 125 | { |
jhnwkmn | 0:97a4f8cc534c | 126 | _lasttokenline = _currentline; |
jhnwkmn | 0:97a4f8cc534c | 127 | while(CUR_CHAR != SQUIRREL_EOB) { |
jhnwkmn | 0:97a4f8cc534c | 128 | switch(CUR_CHAR){ |
jhnwkmn | 0:97a4f8cc534c | 129 | case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue; |
jhnwkmn | 0:97a4f8cc534c | 130 | case _SC('\n'): |
jhnwkmn | 0:97a4f8cc534c | 131 | _currentline++; |
jhnwkmn | 0:97a4f8cc534c | 132 | _prevtoken=_curtoken; |
jhnwkmn | 0:97a4f8cc534c | 133 | _curtoken=_SC('\n'); |
jhnwkmn | 0:97a4f8cc534c | 134 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 135 | _currentcolumn=1; |
jhnwkmn | 0:97a4f8cc534c | 136 | continue; |
jhnwkmn | 0:97a4f8cc534c | 137 | case _SC('#'): LexLineComment(); continue; |
jhnwkmn | 0:97a4f8cc534c | 138 | case _SC('/'): |
jhnwkmn | 0:97a4f8cc534c | 139 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 140 | switch(CUR_CHAR){ |
jhnwkmn | 0:97a4f8cc534c | 141 | case _SC('*'): |
jhnwkmn | 0:97a4f8cc534c | 142 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 143 | LexBlockComment(); |
jhnwkmn | 0:97a4f8cc534c | 144 | continue; |
jhnwkmn | 0:97a4f8cc534c | 145 | case _SC('/'): |
jhnwkmn | 0:97a4f8cc534c | 146 | LexLineComment(); |
jhnwkmn | 0:97a4f8cc534c | 147 | continue; |
jhnwkmn | 0:97a4f8cc534c | 148 | case _SC('='): |
jhnwkmn | 0:97a4f8cc534c | 149 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 150 | RETURN_TOKEN(TK_DIVEQ); |
jhnwkmn | 0:97a4f8cc534c | 151 | continue; |
jhnwkmn | 0:97a4f8cc534c | 152 | case _SC('>'): |
jhnwkmn | 0:97a4f8cc534c | 153 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 154 | RETURN_TOKEN(TK_ATTR_CLOSE); |
jhnwkmn | 0:97a4f8cc534c | 155 | continue; |
jhnwkmn | 0:97a4f8cc534c | 156 | default: |
jhnwkmn | 0:97a4f8cc534c | 157 | RETURN_TOKEN('/'); |
jhnwkmn | 0:97a4f8cc534c | 158 | } |
jhnwkmn | 0:97a4f8cc534c | 159 | case _SC('='): |
jhnwkmn | 0:97a4f8cc534c | 160 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 161 | if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') } |
jhnwkmn | 0:97a4f8cc534c | 162 | else { NEXT(); RETURN_TOKEN(TK_EQ); } |
jhnwkmn | 0:97a4f8cc534c | 163 | case _SC('<'): |
jhnwkmn | 0:97a4f8cc534c | 164 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 165 | switch(CUR_CHAR) { |
jhnwkmn | 0:97a4f8cc534c | 166 | case _SC('='): |
jhnwkmn | 0:97a4f8cc534c | 167 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 168 | if(CUR_CHAR == _SC('>')) { |
jhnwkmn | 0:97a4f8cc534c | 169 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 170 | RETURN_TOKEN(TK_3WAYSCMP); |
jhnwkmn | 0:97a4f8cc534c | 171 | } |
jhnwkmn | 0:97a4f8cc534c | 172 | RETURN_TOKEN(TK_LE) |
jhnwkmn | 0:97a4f8cc534c | 173 | break; |
jhnwkmn | 0:97a4f8cc534c | 174 | case _SC('-'): NEXT(); RETURN_TOKEN(TK_NEWSLOT); break; |
jhnwkmn | 0:97a4f8cc534c | 175 | case _SC('<'): NEXT(); RETURN_TOKEN(TK_SHIFTL); break; |
jhnwkmn | 0:97a4f8cc534c | 176 | case _SC('/'): NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); break; |
jhnwkmn | 0:97a4f8cc534c | 177 | } |
jhnwkmn | 0:97a4f8cc534c | 178 | RETURN_TOKEN('<'); |
jhnwkmn | 0:97a4f8cc534c | 179 | case _SC('>'): |
jhnwkmn | 0:97a4f8cc534c | 180 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 181 | if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);} |
jhnwkmn | 0:97a4f8cc534c | 182 | else if(CUR_CHAR == _SC('>')){ |
jhnwkmn | 0:97a4f8cc534c | 183 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 184 | if(CUR_CHAR == _SC('>')){ |
jhnwkmn | 0:97a4f8cc534c | 185 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 186 | RETURN_TOKEN(TK_USHIFTR); |
jhnwkmn | 0:97a4f8cc534c | 187 | } |
jhnwkmn | 0:97a4f8cc534c | 188 | RETURN_TOKEN(TK_SHIFTR); |
jhnwkmn | 0:97a4f8cc534c | 189 | } |
jhnwkmn | 0:97a4f8cc534c | 190 | else { RETURN_TOKEN('>') } |
jhnwkmn | 0:97a4f8cc534c | 191 | case _SC('!'): |
jhnwkmn | 0:97a4f8cc534c | 192 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 193 | if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')} |
jhnwkmn | 0:97a4f8cc534c | 194 | else { NEXT(); RETURN_TOKEN(TK_NE); } |
jhnwkmn | 0:97a4f8cc534c | 195 | case _SC('@'): { |
jhnwkmn | 0:97a4f8cc534c | 196 | SQInteger stype; |
jhnwkmn | 0:97a4f8cc534c | 197 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 198 | if(CUR_CHAR != _SC('"')) { |
jhnwkmn | 0:97a4f8cc534c | 199 | RETURN_TOKEN('@'); |
jhnwkmn | 0:97a4f8cc534c | 200 | } |
jhnwkmn | 0:97a4f8cc534c | 201 | if((stype=ReadString('"',true))!=-1) { |
jhnwkmn | 0:97a4f8cc534c | 202 | RETURN_TOKEN(stype); |
jhnwkmn | 0:97a4f8cc534c | 203 | } |
jhnwkmn | 0:97a4f8cc534c | 204 | Error(_SC("error parsing the string")); |
jhnwkmn | 0:97a4f8cc534c | 205 | } |
jhnwkmn | 0:97a4f8cc534c | 206 | case _SC('"'): |
jhnwkmn | 0:97a4f8cc534c | 207 | case _SC('\''): { |
jhnwkmn | 0:97a4f8cc534c | 208 | SQInteger stype; |
jhnwkmn | 0:97a4f8cc534c | 209 | if((stype=ReadString(CUR_CHAR,false))!=-1){ |
jhnwkmn | 0:97a4f8cc534c | 210 | RETURN_TOKEN(stype); |
jhnwkmn | 0:97a4f8cc534c | 211 | } |
jhnwkmn | 0:97a4f8cc534c | 212 | Error(_SC("error parsing the string")); |
jhnwkmn | 0:97a4f8cc534c | 213 | } |
jhnwkmn | 0:97a4f8cc534c | 214 | case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'): |
jhnwkmn | 0:97a4f8cc534c | 215 | case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'): |
jhnwkmn | 0:97a4f8cc534c | 216 | {SQInteger ret = CUR_CHAR; |
jhnwkmn | 0:97a4f8cc534c | 217 | NEXT(); RETURN_TOKEN(ret); } |
jhnwkmn | 0:97a4f8cc534c | 218 | case _SC('.'): |
jhnwkmn | 0:97a4f8cc534c | 219 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 220 | if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') } |
jhnwkmn | 0:97a4f8cc534c | 221 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 222 | if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); } |
jhnwkmn | 0:97a4f8cc534c | 223 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 224 | RETURN_TOKEN(TK_VARPARAMS); |
jhnwkmn | 0:97a4f8cc534c | 225 | case _SC('&'): |
jhnwkmn | 0:97a4f8cc534c | 226 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 227 | if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') } |
jhnwkmn | 0:97a4f8cc534c | 228 | else { NEXT(); RETURN_TOKEN(TK_AND); } |
jhnwkmn | 0:97a4f8cc534c | 229 | case _SC('|'): |
jhnwkmn | 0:97a4f8cc534c | 230 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 231 | if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') } |
jhnwkmn | 0:97a4f8cc534c | 232 | else { NEXT(); RETURN_TOKEN(TK_OR); } |
jhnwkmn | 0:97a4f8cc534c | 233 | case _SC(':'): |
jhnwkmn | 0:97a4f8cc534c | 234 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 235 | if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') } |
jhnwkmn | 0:97a4f8cc534c | 236 | else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); } |
jhnwkmn | 0:97a4f8cc534c | 237 | case _SC('*'): |
jhnwkmn | 0:97a4f8cc534c | 238 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 239 | if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);} |
jhnwkmn | 0:97a4f8cc534c | 240 | else RETURN_TOKEN('*'); |
jhnwkmn | 0:97a4f8cc534c | 241 | case _SC('%'): |
jhnwkmn | 0:97a4f8cc534c | 242 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 243 | if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);} |
jhnwkmn | 0:97a4f8cc534c | 244 | else RETURN_TOKEN('%'); |
jhnwkmn | 0:97a4f8cc534c | 245 | case _SC('-'): |
jhnwkmn | 0:97a4f8cc534c | 246 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 247 | if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);} |
jhnwkmn | 0:97a4f8cc534c | 248 | else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);} |
jhnwkmn | 0:97a4f8cc534c | 249 | else RETURN_TOKEN('-'); |
jhnwkmn | 0:97a4f8cc534c | 250 | case _SC('+'): |
jhnwkmn | 0:97a4f8cc534c | 251 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 252 | if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);} |
jhnwkmn | 0:97a4f8cc534c | 253 | else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);} |
jhnwkmn | 0:97a4f8cc534c | 254 | else RETURN_TOKEN('+'); |
jhnwkmn | 0:97a4f8cc534c | 255 | case SQUIRREL_EOB: |
jhnwkmn | 0:97a4f8cc534c | 256 | return 0; |
jhnwkmn | 0:97a4f8cc534c | 257 | default:{ |
jhnwkmn | 0:97a4f8cc534c | 258 | if (scisdigit(CUR_CHAR)) { |
jhnwkmn | 0:97a4f8cc534c | 259 | SQInteger ret = ReadNumber(); |
jhnwkmn | 0:97a4f8cc534c | 260 | RETURN_TOKEN(ret); |
jhnwkmn | 0:97a4f8cc534c | 261 | } |
jhnwkmn | 0:97a4f8cc534c | 262 | else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) { |
jhnwkmn | 0:97a4f8cc534c | 263 | SQInteger t = ReadID(); |
jhnwkmn | 0:97a4f8cc534c | 264 | RETURN_TOKEN(t); |
jhnwkmn | 0:97a4f8cc534c | 265 | } |
jhnwkmn | 0:97a4f8cc534c | 266 | else { |
jhnwkmn | 0:97a4f8cc534c | 267 | SQInteger c = CUR_CHAR; |
jhnwkmn | 0:97a4f8cc534c | 268 | if (sciscntrl((int)c)) Error(_SC("unexpected character(control)")); |
jhnwkmn | 0:97a4f8cc534c | 269 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 270 | RETURN_TOKEN(c); |
jhnwkmn | 0:97a4f8cc534c | 271 | } |
jhnwkmn | 0:97a4f8cc534c | 272 | RETURN_TOKEN(0); |
jhnwkmn | 0:97a4f8cc534c | 273 | } |
jhnwkmn | 0:97a4f8cc534c | 274 | } |
jhnwkmn | 0:97a4f8cc534c | 275 | } |
jhnwkmn | 0:97a4f8cc534c | 276 | return 0; |
jhnwkmn | 0:97a4f8cc534c | 277 | } |
jhnwkmn | 0:97a4f8cc534c | 278 | |
jhnwkmn | 0:97a4f8cc534c | 279 | SQInteger SQLexer::GetIDType(SQChar *s) |
jhnwkmn | 0:97a4f8cc534c | 280 | { |
jhnwkmn | 0:97a4f8cc534c | 281 | SQObjectPtr t; |
jhnwkmn | 0:97a4f8cc534c | 282 | if(_keywords->Get(SQString::Create(_sharedstate, s), t)) { |
jhnwkmn | 0:97a4f8cc534c | 283 | return SQInteger(_integer(t)); |
jhnwkmn | 0:97a4f8cc534c | 284 | } |
jhnwkmn | 0:97a4f8cc534c | 285 | return TK_IDENTIFIER; |
jhnwkmn | 0:97a4f8cc534c | 286 | } |
jhnwkmn | 0:97a4f8cc534c | 287 | |
jhnwkmn | 0:97a4f8cc534c | 288 | |
jhnwkmn | 0:97a4f8cc534c | 289 | SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim) |
jhnwkmn | 0:97a4f8cc534c | 290 | { |
jhnwkmn | 0:97a4f8cc534c | 291 | INIT_TEMP_STRING(); |
jhnwkmn | 0:97a4f8cc534c | 292 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 293 | if(IS_EOB()) return -1; |
jhnwkmn | 0:97a4f8cc534c | 294 | for(;;) { |
jhnwkmn | 0:97a4f8cc534c | 295 | while(CUR_CHAR != ndelim) { |
jhnwkmn | 0:97a4f8cc534c | 296 | switch(CUR_CHAR) { |
jhnwkmn | 0:97a4f8cc534c | 297 | case SQUIRREL_EOB: |
jhnwkmn | 0:97a4f8cc534c | 298 | Error(_SC("unfinished string")); |
jhnwkmn | 0:97a4f8cc534c | 299 | return -1; |
jhnwkmn | 0:97a4f8cc534c | 300 | case _SC('\n'): |
jhnwkmn | 0:97a4f8cc534c | 301 | if(!verbatim) Error(_SC("newline in a constant")); |
jhnwkmn | 0:97a4f8cc534c | 302 | APPEND_CHAR(CUR_CHAR); NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 303 | _currentline++; |
jhnwkmn | 0:97a4f8cc534c | 304 | break; |
jhnwkmn | 0:97a4f8cc534c | 305 | case _SC('\\'): |
jhnwkmn | 0:97a4f8cc534c | 306 | if(verbatim) { |
jhnwkmn | 0:97a4f8cc534c | 307 | APPEND_CHAR('\\'); NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 308 | } |
jhnwkmn | 0:97a4f8cc534c | 309 | else { |
jhnwkmn | 0:97a4f8cc534c | 310 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 311 | switch(CUR_CHAR) { |
jhnwkmn | 0:97a4f8cc534c | 312 | case _SC('x'): NEXT(); { |
jhnwkmn | 0:97a4f8cc534c | 313 | if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected")); |
jhnwkmn | 0:97a4f8cc534c | 314 | const SQInteger maxdigits = 4; |
jhnwkmn | 0:97a4f8cc534c | 315 | SQChar temp[maxdigits+1]; |
jhnwkmn | 0:97a4f8cc534c | 316 | SQInteger n = 0; |
jhnwkmn | 0:97a4f8cc534c | 317 | while(isxdigit(CUR_CHAR) && n < maxdigits) { |
jhnwkmn | 0:97a4f8cc534c | 318 | temp[n] = CUR_CHAR; |
jhnwkmn | 0:97a4f8cc534c | 319 | n++; |
jhnwkmn | 0:97a4f8cc534c | 320 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 321 | } |
jhnwkmn | 0:97a4f8cc534c | 322 | temp[n] = 0; |
jhnwkmn | 0:97a4f8cc534c | 323 | SQChar *sTemp; |
jhnwkmn | 0:97a4f8cc534c | 324 | APPEND_CHAR((SQChar)scstrtoul(temp,&sTemp,16)); |
jhnwkmn | 0:97a4f8cc534c | 325 | } |
jhnwkmn | 0:97a4f8cc534c | 326 | break; |
jhnwkmn | 0:97a4f8cc534c | 327 | case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break; |
jhnwkmn | 0:97a4f8cc534c | 328 | case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break; |
jhnwkmn | 0:97a4f8cc534c | 329 | case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break; |
jhnwkmn | 0:97a4f8cc534c | 330 | case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break; |
jhnwkmn | 0:97a4f8cc534c | 331 | case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break; |
jhnwkmn | 0:97a4f8cc534c | 332 | case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break; |
jhnwkmn | 0:97a4f8cc534c | 333 | case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break; |
jhnwkmn | 0:97a4f8cc534c | 334 | case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break; |
jhnwkmn | 0:97a4f8cc534c | 335 | case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break; |
jhnwkmn | 0:97a4f8cc534c | 336 | case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break; |
jhnwkmn | 0:97a4f8cc534c | 337 | case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break; |
jhnwkmn | 0:97a4f8cc534c | 338 | default: |
jhnwkmn | 0:97a4f8cc534c | 339 | Error(_SC("unrecognised escaper char")); |
jhnwkmn | 0:97a4f8cc534c | 340 | break; |
jhnwkmn | 0:97a4f8cc534c | 341 | } |
jhnwkmn | 0:97a4f8cc534c | 342 | } |
jhnwkmn | 0:97a4f8cc534c | 343 | break; |
jhnwkmn | 0:97a4f8cc534c | 344 | default: |
jhnwkmn | 0:97a4f8cc534c | 345 | APPEND_CHAR(CUR_CHAR); |
jhnwkmn | 0:97a4f8cc534c | 346 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 347 | } |
jhnwkmn | 0:97a4f8cc534c | 348 | } |
jhnwkmn | 0:97a4f8cc534c | 349 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 350 | if(verbatim && CUR_CHAR == '"') { //double quotation |
jhnwkmn | 0:97a4f8cc534c | 351 | APPEND_CHAR(CUR_CHAR); |
jhnwkmn | 0:97a4f8cc534c | 352 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 353 | } |
jhnwkmn | 0:97a4f8cc534c | 354 | else { |
jhnwkmn | 0:97a4f8cc534c | 355 | break; |
jhnwkmn | 0:97a4f8cc534c | 356 | } |
jhnwkmn | 0:97a4f8cc534c | 357 | } |
jhnwkmn | 0:97a4f8cc534c | 358 | TERMINATE_BUFFER(); |
jhnwkmn | 0:97a4f8cc534c | 359 | SQInteger len = _longstr.size()-1; |
jhnwkmn | 0:97a4f8cc534c | 360 | if(ndelim == _SC('\'')) { |
jhnwkmn | 0:97a4f8cc534c | 361 | if(len == 0) Error(_SC("empty constant")); |
jhnwkmn | 0:97a4f8cc534c | 362 | if(len > 1) Error(_SC("constant too long")); |
jhnwkmn | 0:97a4f8cc534c | 363 | _nvalue = _longstr[0]; |
jhnwkmn | 0:97a4f8cc534c | 364 | return TK_INTEGER; |
jhnwkmn | 0:97a4f8cc534c | 365 | } |
jhnwkmn | 0:97a4f8cc534c | 366 | _svalue = &_longstr[0]; |
jhnwkmn | 0:97a4f8cc534c | 367 | return TK_STRING_LITERAL; |
jhnwkmn | 0:97a4f8cc534c | 368 | } |
jhnwkmn | 0:97a4f8cc534c | 369 | |
jhnwkmn | 0:97a4f8cc534c | 370 | void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res) |
jhnwkmn | 0:97a4f8cc534c | 371 | { |
jhnwkmn | 0:97a4f8cc534c | 372 | *res = 0; |
jhnwkmn | 0:97a4f8cc534c | 373 | while(*s != 0) |
jhnwkmn | 0:97a4f8cc534c | 374 | { |
jhnwkmn | 0:97a4f8cc534c | 375 | if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0'); |
jhnwkmn | 0:97a4f8cc534c | 376 | else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10); |
jhnwkmn | 0:97a4f8cc534c | 377 | else { assert(0); } |
jhnwkmn | 0:97a4f8cc534c | 378 | } |
jhnwkmn | 0:97a4f8cc534c | 379 | } |
jhnwkmn | 0:97a4f8cc534c | 380 | |
jhnwkmn | 0:97a4f8cc534c | 381 | void LexInteger(const SQChar *s,SQUnsignedInteger *res) |
jhnwkmn | 0:97a4f8cc534c | 382 | { |
jhnwkmn | 0:97a4f8cc534c | 383 | *res = 0; |
jhnwkmn | 0:97a4f8cc534c | 384 | while(*s != 0) |
jhnwkmn | 0:97a4f8cc534c | 385 | { |
jhnwkmn | 0:97a4f8cc534c | 386 | *res = (*res)*10+((*s++)-'0'); |
jhnwkmn | 0:97a4f8cc534c | 387 | } |
jhnwkmn | 0:97a4f8cc534c | 388 | } |
jhnwkmn | 0:97a4f8cc534c | 389 | |
jhnwkmn | 0:97a4f8cc534c | 390 | SQInteger scisodigit(SQInteger c) { return c >= _SC('0') && c <= _SC('7'); } |
jhnwkmn | 0:97a4f8cc534c | 391 | |
jhnwkmn | 0:97a4f8cc534c | 392 | void LexOctal(const SQChar *s,SQUnsignedInteger *res) |
jhnwkmn | 0:97a4f8cc534c | 393 | { |
jhnwkmn | 0:97a4f8cc534c | 394 | *res = 0; |
jhnwkmn | 0:97a4f8cc534c | 395 | while(*s != 0) |
jhnwkmn | 0:97a4f8cc534c | 396 | { |
jhnwkmn | 0:97a4f8cc534c | 397 | if(scisodigit(*s)) *res = (*res)*8+((*s++)-'0'); |
jhnwkmn | 0:97a4f8cc534c | 398 | else { assert(0); } |
jhnwkmn | 0:97a4f8cc534c | 399 | } |
jhnwkmn | 0:97a4f8cc534c | 400 | } |
jhnwkmn | 0:97a4f8cc534c | 401 | |
jhnwkmn | 0:97a4f8cc534c | 402 | SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; } |
jhnwkmn | 0:97a4f8cc534c | 403 | |
jhnwkmn | 0:97a4f8cc534c | 404 | |
jhnwkmn | 0:97a4f8cc534c | 405 | #define MAX_HEX_DIGITS (sizeof(SQInteger)*2) |
jhnwkmn | 0:97a4f8cc534c | 406 | SQInteger SQLexer::ReadNumber() |
jhnwkmn | 0:97a4f8cc534c | 407 | { |
jhnwkmn | 0:97a4f8cc534c | 408 | #define TINT 1 |
jhnwkmn | 0:97a4f8cc534c | 409 | #define TFLOAT 2 |
jhnwkmn | 0:97a4f8cc534c | 410 | #define THEX 3 |
jhnwkmn | 0:97a4f8cc534c | 411 | #define TSCIENTIFIC 4 |
jhnwkmn | 0:97a4f8cc534c | 412 | #define TOCTAL 5 |
jhnwkmn | 0:97a4f8cc534c | 413 | SQInteger type = TINT, firstchar = CUR_CHAR; |
jhnwkmn | 0:97a4f8cc534c | 414 | SQChar *sTemp; |
jhnwkmn | 0:97a4f8cc534c | 415 | INIT_TEMP_STRING(); |
jhnwkmn | 0:97a4f8cc534c | 416 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 417 | if(firstchar == _SC('0') && (toupper(CUR_CHAR) == _SC('X') || scisodigit(CUR_CHAR)) ) { |
jhnwkmn | 0:97a4f8cc534c | 418 | if(scisodigit(CUR_CHAR)) { |
jhnwkmn | 0:97a4f8cc534c | 419 | type = TOCTAL; |
jhnwkmn | 0:97a4f8cc534c | 420 | while(scisodigit(CUR_CHAR)) { |
jhnwkmn | 0:97a4f8cc534c | 421 | APPEND_CHAR(CUR_CHAR); |
jhnwkmn | 0:97a4f8cc534c | 422 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 423 | } |
jhnwkmn | 0:97a4f8cc534c | 424 | if(scisdigit(CUR_CHAR)) Error(_SC("invalid octal number")); |
jhnwkmn | 0:97a4f8cc534c | 425 | } |
jhnwkmn | 0:97a4f8cc534c | 426 | else { |
jhnwkmn | 0:97a4f8cc534c | 427 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 428 | type = THEX; |
jhnwkmn | 0:97a4f8cc534c | 429 | while(isxdigit(CUR_CHAR)) { |
jhnwkmn | 0:97a4f8cc534c | 430 | APPEND_CHAR(CUR_CHAR); |
jhnwkmn | 0:97a4f8cc534c | 431 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 432 | } |
jhnwkmn | 0:97a4f8cc534c | 433 | if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number")); |
jhnwkmn | 0:97a4f8cc534c | 434 | } |
jhnwkmn | 0:97a4f8cc534c | 435 | } |
jhnwkmn | 0:97a4f8cc534c | 436 | else { |
jhnwkmn | 0:97a4f8cc534c | 437 | APPEND_CHAR((int)firstchar); |
jhnwkmn | 0:97a4f8cc534c | 438 | while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) { |
jhnwkmn | 0:97a4f8cc534c | 439 | if(CUR_CHAR == _SC('.') || isexponent(CUR_CHAR)) type = TFLOAT; |
jhnwkmn | 0:97a4f8cc534c | 440 | if(isexponent(CUR_CHAR)) { |
jhnwkmn | 0:97a4f8cc534c | 441 | if(type != TFLOAT) Error(_SC("invalid numeric format")); |
jhnwkmn | 0:97a4f8cc534c | 442 | type = TSCIENTIFIC; |
jhnwkmn | 0:97a4f8cc534c | 443 | APPEND_CHAR(CUR_CHAR); |
jhnwkmn | 0:97a4f8cc534c | 444 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 445 | if(CUR_CHAR == '+' || CUR_CHAR == '-'){ |
jhnwkmn | 0:97a4f8cc534c | 446 | APPEND_CHAR(CUR_CHAR); |
jhnwkmn | 0:97a4f8cc534c | 447 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 448 | } |
jhnwkmn | 0:97a4f8cc534c | 449 | if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected")); |
jhnwkmn | 0:97a4f8cc534c | 450 | } |
jhnwkmn | 0:97a4f8cc534c | 451 | |
jhnwkmn | 0:97a4f8cc534c | 452 | APPEND_CHAR(CUR_CHAR); |
jhnwkmn | 0:97a4f8cc534c | 453 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 454 | } |
jhnwkmn | 0:97a4f8cc534c | 455 | } |
jhnwkmn | 0:97a4f8cc534c | 456 | TERMINATE_BUFFER(); |
jhnwkmn | 0:97a4f8cc534c | 457 | switch(type) { |
jhnwkmn | 0:97a4f8cc534c | 458 | case TSCIENTIFIC: |
jhnwkmn | 0:97a4f8cc534c | 459 | case TFLOAT: |
jhnwkmn | 0:97a4f8cc534c | 460 | _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp); |
jhnwkmn | 0:97a4f8cc534c | 461 | return TK_FLOAT; |
jhnwkmn | 0:97a4f8cc534c | 462 | case TINT: |
jhnwkmn | 0:97a4f8cc534c | 463 | LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue); |
jhnwkmn | 0:97a4f8cc534c | 464 | return TK_INTEGER; |
jhnwkmn | 0:97a4f8cc534c | 465 | case THEX: |
jhnwkmn | 0:97a4f8cc534c | 466 | LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue); |
jhnwkmn | 0:97a4f8cc534c | 467 | return TK_INTEGER; |
jhnwkmn | 0:97a4f8cc534c | 468 | case TOCTAL: |
jhnwkmn | 0:97a4f8cc534c | 469 | LexOctal(&_longstr[0],(SQUnsignedInteger *)&_nvalue); |
jhnwkmn | 0:97a4f8cc534c | 470 | return TK_INTEGER; |
jhnwkmn | 0:97a4f8cc534c | 471 | } |
jhnwkmn | 0:97a4f8cc534c | 472 | return 0; |
jhnwkmn | 0:97a4f8cc534c | 473 | } |
jhnwkmn | 0:97a4f8cc534c | 474 | |
jhnwkmn | 0:97a4f8cc534c | 475 | SQInteger SQLexer::ReadID() |
jhnwkmn | 0:97a4f8cc534c | 476 | { |
jhnwkmn | 0:97a4f8cc534c | 477 | SQInteger res; |
jhnwkmn | 0:97a4f8cc534c | 478 | INIT_TEMP_STRING(); |
jhnwkmn | 0:97a4f8cc534c | 479 | do { |
jhnwkmn | 0:97a4f8cc534c | 480 | APPEND_CHAR(CUR_CHAR); |
jhnwkmn | 0:97a4f8cc534c | 481 | NEXT(); |
jhnwkmn | 0:97a4f8cc534c | 482 | } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_')); |
jhnwkmn | 0:97a4f8cc534c | 483 | TERMINATE_BUFFER(); |
jhnwkmn | 0:97a4f8cc534c | 484 | res = GetIDType(&_longstr[0]); |
jhnwkmn | 0:97a4f8cc534c | 485 | if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) { |
jhnwkmn | 0:97a4f8cc534c | 486 | _svalue = &_longstr[0]; |
jhnwkmn | 0:97a4f8cc534c | 487 | } |
jhnwkmn | 0:97a4f8cc534c | 488 | return res; |
jhnwkmn | 0:97a4f8cc534c | 489 | } |