diff options
Diffstat (limited to 'apps/plugins/lua/llex.c')
-rw-r--r-- | apps/plugins/lua/llex.c | 368 |
1 files changed, 218 insertions, 150 deletions
diff --git a/apps/plugins/lua/llex.c b/apps/plugins/lua/llex.c index 85ac516be3..8d410f620d 100644 --- a/apps/plugins/lua/llex.c +++ b/apps/plugins/lua/llex.c | |||
@@ -1,12 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ | 2 | ** $Id: llex.c,v 2.63.1.2 2013/08/30 15:49:41 roberto Exp $ |
3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
7 | 7 | ||
8 | #include <ctype.h> | ||
9 | /* #include <locale.h> */ | ||
10 | #include <string.h> | 8 | #include <string.h> |
11 | 9 | ||
12 | #define llex_c | 10 | #define llex_c |
@@ -14,6 +12,7 @@ | |||
14 | 12 | ||
15 | #include "lua.h" | 13 | #include "lua.h" |
16 | 14 | ||
15 | #include "lctype.h" | ||
17 | #include "ldo.h" | 16 | #include "ldo.h" |
18 | #include "llex.h" | 17 | #include "llex.h" |
19 | #include "lobject.h" | 18 | #include "lobject.h" |
@@ -29,35 +28,36 @@ | |||
29 | 28 | ||
30 | 29 | ||
31 | 30 | ||
32 | |||
33 | #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') | 31 | #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') |
34 | 32 | ||
35 | 33 | ||
36 | /* ORDER RESERVED */ | 34 | /* ORDER RESERVED */ |
37 | const char *const luaX_tokens [] = { | 35 | static const char *const luaX_tokens [] = { |
38 | "and", "break", "do", "else", "elseif", | 36 | "and", "break", "do", "else", "elseif", |
39 | "end", "false", "for", "function", "if", | 37 | "end", "false", "for", "function", "goto", "if", |
40 | "in", "local", "nil", "not", "or", "repeat", | 38 | "in", "local", "nil", "not", "or", "repeat", |
41 | "return", "then", "true", "until", "while", | 39 | "return", "then", "true", "until", "while", |
42 | "..", "...", "==", ">=", "<=", "~=", | 40 | "..", "...", "==", ">=", "<=", "~=", "::", "<eof>", |
43 | "<number>", "<name>", "<string>", "<eof>", | 41 | "<number>", "<name>", "<string>" |
44 | NULL | ||
45 | }; | 42 | }; |
46 | 43 | ||
47 | 44 | ||
48 | #define save_and_next(ls) (save(ls, ls->current), next(ls)) | 45 | #define save_and_next(ls) (save(ls, ls->current), next(ls)) |
49 | 46 | ||
50 | 47 | ||
48 | static l_noret lexerror (LexState *ls, const char *msg, int token); | ||
49 | |||
50 | |||
51 | static void save (LexState *ls, int c) { | 51 | static void save (LexState *ls, int c) { |
52 | Mbuffer *b = ls->buff; | 52 | Mbuffer *b = ls->buff; |
53 | if (b->n + 1 > b->buffsize) { | 53 | if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { |
54 | size_t newsize; | 54 | size_t newsize; |
55 | if (b->buffsize >= MAX_SIZET/2) | 55 | if (luaZ_sizebuffer(b) >= MAX_SIZET/2) |
56 | luaX_lexerror(ls, "lexical element too long", 0); | 56 | lexerror(ls, "lexical element too long", 0); |
57 | newsize = b->buffsize * 2; | 57 | newsize = luaZ_sizebuffer(b) * 2; |
58 | luaZ_resizebuffer(ls->L, b, newsize); | 58 | luaZ_resizebuffer(ls->L, b, newsize); |
59 | } | 59 | } |
60 | b->buffer[b->n++] = cast(char, c); | 60 | b->buffer[luaZ_bufflen(b)++] = cast(char, c); |
61 | } | 61 | } |
62 | 62 | ||
63 | 63 | ||
@@ -66,23 +66,24 @@ void luaX_init (lua_State *L) { | |||
66 | for (i=0; i<NUM_RESERVED; i++) { | 66 | for (i=0; i<NUM_RESERVED; i++) { |
67 | TString *ts = luaS_new(L, luaX_tokens[i]); | 67 | TString *ts = luaS_new(L, luaX_tokens[i]); |
68 | luaS_fix(ts); /* reserved words are never collected */ | 68 | luaS_fix(ts); /* reserved words are never collected */ |
69 | lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN); | 69 | ts->tsv.extra = cast_byte(i+1); /* reserved word */ |
70 | ts->tsv.reserved = cast_byte(i+1); /* reserved word */ | ||
71 | } | 70 | } |
72 | } | 71 | } |
73 | 72 | ||
74 | 73 | ||
75 | #define MAXSRC 80 | ||
76 | |||
77 | |||
78 | const char *luaX_token2str (LexState *ls, int token) { | 74 | const char *luaX_token2str (LexState *ls, int token) { |
79 | if (token < FIRST_RESERVED) { | 75 | if (token < FIRST_RESERVED) { /* single-byte symbols? */ |
80 | lua_assert(token == cast(unsigned char, token)); | 76 | lua_assert(token == cast(unsigned char, token)); |
81 | return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : | 77 | return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) : |
82 | luaO_pushfstring(ls->L, "%c", token); | 78 | luaO_pushfstring(ls->L, "char(%d)", token); |
79 | } | ||
80 | else { | ||
81 | const char *s = luaX_tokens[token - FIRST_RESERVED]; | ||
82 | if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ | ||
83 | return luaO_pushfstring(ls->L, LUA_QS, s); | ||
84 | else /* names, strings, and numerals */ | ||
85 | return s; | ||
83 | } | 86 | } |
84 | else | ||
85 | return luaX_tokens[token-FIRST_RESERVED]; | ||
86 | } | 87 | } |
87 | 88 | ||
88 | 89 | ||
@@ -92,38 +93,57 @@ static const char *txtToken (LexState *ls, int token) { | |||
92 | case TK_STRING: | 93 | case TK_STRING: |
93 | case TK_NUMBER: | 94 | case TK_NUMBER: |
94 | save(ls, '\0'); | 95 | save(ls, '\0'); |
95 | return luaZ_buffer(ls->buff); | 96 | return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff)); |
96 | default: | 97 | default: |
97 | return luaX_token2str(ls, token); | 98 | return luaX_token2str(ls, token); |
98 | } | 99 | } |
99 | } | 100 | } |
100 | 101 | ||
101 | 102 | ||
102 | void luaX_lexerror (LexState *ls, const char *msg, int token) { | 103 | static l_noret lexerror (LexState *ls, const char *msg, int token) { |
103 | char buff[MAXSRC]; | 104 | char buff[LUA_IDSIZE]; |
104 | luaO_chunkid(buff, getstr(ls->source), MAXSRC); | 105 | luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE); |
105 | msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); | 106 | msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); |
106 | if (token) | 107 | if (token) |
107 | luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); | 108 | luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); |
108 | luaD_throw(ls->L, LUA_ERRSYNTAX); | 109 | luaD_throw(ls->L, LUA_ERRSYNTAX); |
109 | } | 110 | } |
110 | 111 | ||
111 | 112 | ||
112 | void luaX_syntaxerror (LexState *ls, const char *msg) { | 113 | l_noret luaX_syntaxerror (LexState *ls, const char *msg) { |
113 | luaX_lexerror(ls, msg, ls->t.token); | 114 | lexerror(ls, msg, ls->t.token); |
114 | } | 115 | } |
115 | 116 | ||
116 | 117 | ||
118 | /* | ||
119 | ** creates a new string and anchors it in function's table so that | ||
120 | ** it will not be collected until the end of the function's compilation | ||
121 | ** (by that time it should be anchored in function's prototype) | ||
122 | */ | ||
117 | TString *luaX_newstring (LexState *ls, const char *str, size_t l) { | 123 | TString *luaX_newstring (LexState *ls, const char *str, size_t l) { |
118 | lua_State *L = ls->L; | 124 | lua_State *L = ls->L; |
119 | TString *ts = luaS_newlstr(L, str, l); | 125 | TValue *o; /* entry for `str' */ |
120 | TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ | 126 | TString *ts = luaS_newlstr(L, str, l); /* create new string */ |
121 | if (ttisnil(o)) | 127 | setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ |
122 | setbvalue(o, 1); /* make sure `str' will not be collected */ | 128 | o = luaH_set(L, ls->fs->h, L->top - 1); |
129 | if (ttisnil(o)) { /* not in use yet? (see 'addK') */ | ||
130 | /* boolean value does not need GC barrier; | ||
131 | table has no metatable, so it does not need to invalidate cache */ | ||
132 | setbvalue(o, 1); /* t[string] = true */ | ||
133 | luaC_checkGC(L); | ||
134 | } | ||
135 | else { /* string already present */ | ||
136 | ts = rawtsvalue(keyfromval(o)); /* re-use value previously stored */ | ||
137 | } | ||
138 | L->top--; /* remove string from stack */ | ||
123 | return ts; | 139 | return ts; |
124 | } | 140 | } |
125 | 141 | ||
126 | 142 | ||
143 | /* | ||
144 | ** increment line number and skips newline sequence (any of | ||
145 | ** \n, \r, \n\r, or \r\n) | ||
146 | */ | ||
127 | static void inclinenumber (LexState *ls) { | 147 | static void inclinenumber (LexState *ls) { |
128 | int old = ls->current; | 148 | int old = ls->current; |
129 | lua_assert(currIsNewline(ls)); | 149 | lua_assert(currIsNewline(ls)); |
@@ -135,17 +155,20 @@ static void inclinenumber (LexState *ls) { | |||
135 | } | 155 | } |
136 | 156 | ||
137 | 157 | ||
138 | void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { | 158 | void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, |
159 | int firstchar) { | ||
139 | ls->decpoint = '.'; | 160 | ls->decpoint = '.'; |
140 | ls->L = L; | 161 | ls->L = L; |
162 | ls->current = firstchar; | ||
141 | ls->lookahead.token = TK_EOS; /* no look-ahead token */ | 163 | ls->lookahead.token = TK_EOS; /* no look-ahead token */ |
142 | ls->z = z; | 164 | ls->z = z; |
143 | ls->fs = NULL; | 165 | ls->fs = NULL; |
144 | ls->linenumber = 1; | 166 | ls->linenumber = 1; |
145 | ls->lastline = 1; | 167 | ls->lastline = 1; |
146 | ls->source = source; | 168 | ls->source = source; |
169 | ls->envn = luaS_new(L, LUA_ENV); /* create env name */ | ||
170 | luaS_fix(ls->envn); /* never collect this name */ | ||
147 | luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ | 171 | luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ |
148 | next(ls); /* read first char */ | ||
149 | } | 172 | } |
150 | 173 | ||
151 | 174 | ||
@@ -159,13 +182,16 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { | |||
159 | 182 | ||
160 | 183 | ||
161 | static int check_next (LexState *ls, const char *set) { | 184 | static int check_next (LexState *ls, const char *set) { |
162 | if (!strchr(set, ls->current)) | 185 | if (ls->current == '\0' || !strchr(set, ls->current)) |
163 | return 0; | 186 | return 0; |
164 | save_and_next(ls); | 187 | save_and_next(ls); |
165 | return 1; | 188 | return 1; |
166 | } | 189 | } |
167 | 190 | ||
168 | 191 | ||
192 | /* | ||
193 | ** change all characters 'from' in buffer to 'to' | ||
194 | */ | ||
169 | static void buffreplace (LexState *ls, char from, char to) { | 195 | static void buffreplace (LexState *ls, char from, char to) { |
170 | size_t n = luaZ_bufflen(ls->buff); | 196 | size_t n = luaZ_bufflen(ls->buff); |
171 | char *p = luaZ_buffer(ls->buff); | 197 | char *p = luaZ_buffer(ls->buff); |
@@ -174,37 +200,59 @@ static void buffreplace (LexState *ls, char from, char to) { | |||
174 | } | 200 | } |
175 | 201 | ||
176 | 202 | ||
203 | #if !defined(getlocaledecpoint) | ||
204 | #define getlocaledecpoint() (localeconv()->decimal_point[0]) | ||
205 | #endif | ||
206 | |||
207 | |||
208 | #define buff2d(b,e) luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e) | ||
209 | |||
210 | /* | ||
211 | ** in case of format error, try to change decimal point separator to | ||
212 | ** the one defined in the current locale and check again | ||
213 | */ | ||
177 | static void trydecpoint (LexState *ls, SemInfo *seminfo) { | 214 | static void trydecpoint (LexState *ls, SemInfo *seminfo) { |
178 | /* format error: try to update decimal point separator */ | ||
179 | /* struct lconv *cv = localeconv(); */ | ||
180 | char old = ls->decpoint; | 215 | char old = ls->decpoint; |
181 | ls->decpoint = '.'; /* (cv ? cv->decimal_point[0] : '.'); */ | 216 | ls->decpoint = getlocaledecpoint(); |
182 | buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ | 217 | buffreplace(ls, old, ls->decpoint); /* try new decimal separator */ |
183 | if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { | 218 | if (!buff2d(ls->buff, &seminfo->r)) { |
184 | /* format error with correct decimal point: no more options */ | 219 | /* format error with correct decimal point: no more options */ |
185 | buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ | 220 | buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ |
186 | luaX_lexerror(ls, "malformed number", TK_NUMBER); | 221 | lexerror(ls, "malformed number", TK_NUMBER); |
187 | } | 222 | } |
188 | } | 223 | } |
189 | 224 | ||
190 | 225 | ||
191 | /* LUA_NUMBER */ | 226 | /* LUA_NUMBER */ |
227 | /* | ||
228 | ** this function is quite liberal in what it accepts, as 'luaO_str2d' | ||
229 | ** will reject ill-formed numerals. | ||
230 | */ | ||
192 | static void read_numeral (LexState *ls, SemInfo *seminfo) { | 231 | static void read_numeral (LexState *ls, SemInfo *seminfo) { |
193 | lua_assert(isdigit(ls->current)); | 232 | const char *expo = "Ee"; |
194 | do { | 233 | int first = ls->current; |
195 | save_and_next(ls); | 234 | lua_assert(lisdigit(ls->current)); |
196 | } while (isdigit(ls->current) || ls->current == '.'); | 235 | save_and_next(ls); |
197 | if (check_next(ls, "Ee")) /* `E'? */ | 236 | if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */ |
198 | check_next(ls, "+-"); /* optional exponent sign */ | 237 | expo = "Pp"; |
199 | while (isalnum(ls->current) || ls->current == '_') | 238 | for (;;) { |
200 | save_and_next(ls); | 239 | if (check_next(ls, expo)) /* exponent part? */ |
240 | check_next(ls, "+-"); /* optional exponent sign */ | ||
241 | if (lisxdigit(ls->current) || ls->current == '.') | ||
242 | save_and_next(ls); | ||
243 | else break; | ||
244 | } | ||
201 | save(ls, '\0'); | 245 | save(ls, '\0'); |
202 | buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ | 246 | buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ |
203 | if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ | 247 | if (!buff2d(ls->buff, &seminfo->r)) /* format error? */ |
204 | trydecpoint(ls, seminfo); /* try to update decimal point separator */ | 248 | trydecpoint(ls, seminfo); /* try to update decimal point separator */ |
205 | } | 249 | } |
206 | 250 | ||
207 | 251 | ||
252 | /* | ||
253 | ** skip a sequence '[=*[' or ']=*]' and return its number of '='s or | ||
254 | ** -1 if sequence is malformed | ||
255 | */ | ||
208 | static int skip_sep (LexState *ls) { | 256 | static int skip_sep (LexState *ls) { |
209 | int count = 0; | 257 | int count = 0; |
210 | int s = ls->current; | 258 | int s = ls->current; |
@@ -219,43 +267,23 @@ static int skip_sep (LexState *ls) { | |||
219 | 267 | ||
220 | 268 | ||
221 | static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { | 269 | static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { |
222 | int cont = 0; | ||
223 | (void)(cont); /* avoid warnings when `cont' is not used */ | ||
224 | save_and_next(ls); /* skip 2nd `[' */ | 270 | save_and_next(ls); /* skip 2nd `[' */ |
225 | if (currIsNewline(ls)) /* string starts with a newline? */ | 271 | if (currIsNewline(ls)) /* string starts with a newline? */ |
226 | inclinenumber(ls); /* skip it */ | 272 | inclinenumber(ls); /* skip it */ |
227 | for (;;) { | 273 | for (;;) { |
228 | switch (ls->current) { | 274 | switch (ls->current) { |
229 | case EOZ: | 275 | case EOZ: |
230 | luaX_lexerror(ls, (seminfo) ? "unfinished long string" : | 276 | lexerror(ls, (seminfo) ? "unfinished long string" : |
231 | "unfinished long comment", TK_EOS); | 277 | "unfinished long comment", TK_EOS); |
232 | break; /* to avoid warnings */ | 278 | break; /* to avoid warnings */ |
233 | #if defined(LUA_COMPAT_LSTR) | ||
234 | case '[': { | ||
235 | if (skip_sep(ls) == sep) { | ||
236 | save_and_next(ls); /* skip 2nd `[' */ | ||
237 | cont++; | ||
238 | #if LUA_COMPAT_LSTR == 1 | ||
239 | if (sep == 0) | ||
240 | luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); | ||
241 | #endif | ||
242 | } | ||
243 | break; | ||
244 | } | ||
245 | #endif | ||
246 | case ']': { | 279 | case ']': { |
247 | if (skip_sep(ls) == sep) { | 280 | if (skip_sep(ls) == sep) { |
248 | save_and_next(ls); /* skip 2nd `]' */ | 281 | save_and_next(ls); /* skip 2nd `]' */ |
249 | #if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 | ||
250 | cont--; | ||
251 | if (sep == 0 && cont >= 0) break; | ||
252 | #endif | ||
253 | goto endloop; | 282 | goto endloop; |
254 | } | 283 | } |
255 | break; | 284 | break; |
256 | } | 285 | } |
257 | case '\n': | 286 | case '\n': case '\r': { |
258 | case '\r': { | ||
259 | save(ls, '\n'); | 287 | save(ls, '\n'); |
260 | inclinenumber(ls); | 288 | inclinenumber(ls); |
261 | if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ | 289 | if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ |
@@ -273,51 +301,91 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { | |||
273 | } | 301 | } |
274 | 302 | ||
275 | 303 | ||
304 | static void escerror (LexState *ls, int *c, int n, const char *msg) { | ||
305 | int i; | ||
306 | luaZ_resetbuffer(ls->buff); /* prepare error message */ | ||
307 | save(ls, '\\'); | ||
308 | for (i = 0; i < n && c[i] != EOZ; i++) | ||
309 | save(ls, c[i]); | ||
310 | lexerror(ls, msg, TK_STRING); | ||
311 | } | ||
312 | |||
313 | |||
314 | static int readhexaesc (LexState *ls) { | ||
315 | int c[3], i; /* keep input for error message */ | ||
316 | int r = 0; /* result accumulator */ | ||
317 | c[0] = 'x'; /* for error message */ | ||
318 | for (i = 1; i < 3; i++) { /* read two hexadecimal digits */ | ||
319 | c[i] = next(ls); | ||
320 | if (!lisxdigit(c[i])) | ||
321 | escerror(ls, c, i + 1, "hexadecimal digit expected"); | ||
322 | r = (r << 4) + luaO_hexavalue(c[i]); | ||
323 | } | ||
324 | return r; | ||
325 | } | ||
326 | |||
327 | |||
328 | static int readdecesc (LexState *ls) { | ||
329 | int c[3], i; | ||
330 | int r = 0; /* result accumulator */ | ||
331 | for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ | ||
332 | c[i] = ls->current; | ||
333 | r = 10*r + c[i] - '0'; | ||
334 | next(ls); | ||
335 | } | ||
336 | if (r > UCHAR_MAX) | ||
337 | escerror(ls, c, i, "decimal escape too large"); | ||
338 | return r; | ||
339 | } | ||
340 | |||
341 | |||
276 | static void read_string (LexState *ls, int del, SemInfo *seminfo) { | 342 | static void read_string (LexState *ls, int del, SemInfo *seminfo) { |
277 | save_and_next(ls); | 343 | save_and_next(ls); /* keep delimiter (for error messages) */ |
278 | while (ls->current != del) { | 344 | while (ls->current != del) { |
279 | switch (ls->current) { | 345 | switch (ls->current) { |
280 | case EOZ: | 346 | case EOZ: |
281 | luaX_lexerror(ls, "unfinished string", TK_EOS); | 347 | lexerror(ls, "unfinished string", TK_EOS); |
282 | continue; /* to avoid warnings */ | 348 | break; /* to avoid warnings */ |
283 | case '\n': | 349 | case '\n': |
284 | case '\r': | 350 | case '\r': |
285 | luaX_lexerror(ls, "unfinished string", TK_STRING); | 351 | lexerror(ls, "unfinished string", TK_STRING); |
286 | continue; /* to avoid warnings */ | 352 | break; /* to avoid warnings */ |
287 | case '\\': { | 353 | case '\\': { /* escape sequences */ |
288 | int c; | 354 | int c; /* final character to be saved */ |
289 | next(ls); /* do not save the `\' */ | 355 | next(ls); /* do not save the `\' */ |
290 | switch (ls->current) { | 356 | switch (ls->current) { |
291 | case 'a': c = '\a'; break; | 357 | case 'a': c = '\a'; goto read_save; |
292 | case 'b': c = '\b'; break; | 358 | case 'b': c = '\b'; goto read_save; |
293 | case 'f': c = '\f'; break; | 359 | case 'f': c = '\f'; goto read_save; |
294 | case 'n': c = '\n'; break; | 360 | case 'n': c = '\n'; goto read_save; |
295 | case 'r': c = '\r'; break; | 361 | case 'r': c = '\r'; goto read_save; |
296 | case 't': c = '\t'; break; | 362 | case 't': c = '\t'; goto read_save; |
297 | case 'v': c = '\v'; break; | 363 | case 'v': c = '\v'; goto read_save; |
298 | case '\n': /* go through */ | 364 | case 'x': c = readhexaesc(ls); goto read_save; |
299 | case '\r': save(ls, '\n'); inclinenumber(ls); continue; | 365 | case '\n': case '\r': |
300 | case EOZ: continue; /* will raise an error next loop */ | 366 | inclinenumber(ls); c = '\n'; goto only_save; |
301 | default: { | 367 | case '\\': case '\"': case '\'': |
302 | if (!isdigit(ls->current)) | 368 | c = ls->current; goto read_save; |
303 | save_and_next(ls); /* handles \\, \", \', and \? */ | 369 | case EOZ: goto no_save; /* will raise an error next loop */ |
304 | else { /* \xxx */ | 370 | case 'z': { /* zap following span of spaces */ |
305 | int i = 0; | 371 | next(ls); /* skip the 'z' */ |
306 | c = 0; | 372 | while (lisspace(ls->current)) { |
307 | do { | 373 | if (currIsNewline(ls)) inclinenumber(ls); |
308 | c = 10*c + (ls->current-'0'); | 374 | else next(ls); |
309 | next(ls); | ||
310 | } while (++i<3 && isdigit(ls->current)); | ||
311 | if (c > UCHAR_MAX) | ||
312 | luaX_lexerror(ls, "escape sequence too large", TK_STRING); | ||
313 | save(ls, c); | ||
314 | } | 375 | } |
315 | continue; | 376 | goto no_save; |
377 | } | ||
378 | default: { | ||
379 | if (!lisdigit(ls->current)) | ||
380 | escerror(ls, &ls->current, 1, "invalid escape sequence"); | ||
381 | /* digital escape \ddd */ | ||
382 | c = readdecesc(ls); | ||
383 | goto only_save; | ||
316 | } | 384 | } |
317 | } | 385 | } |
318 | save(ls, c); | 386 | read_save: next(ls); /* read next character */ |
319 | next(ls); | 387 | only_save: save(ls, c); /* save 'c' */ |
320 | continue; | 388 | no_save: break; |
321 | } | 389 | } |
322 | default: | 390 | default: |
323 | save_and_next(ls); | 391 | save_and_next(ls); |
@@ -333,38 +401,41 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
333 | luaZ_resetbuffer(ls->buff); | 401 | luaZ_resetbuffer(ls->buff); |
334 | for (;;) { | 402 | for (;;) { |
335 | switch (ls->current) { | 403 | switch (ls->current) { |
336 | case '\n': | 404 | case '\n': case '\r': { /* line breaks */ |
337 | case '\r': { | ||
338 | inclinenumber(ls); | 405 | inclinenumber(ls); |
339 | continue; | 406 | break; |
340 | } | 407 | } |
341 | case '-': { | 408 | case ' ': case '\f': case '\t': case '\v': { /* spaces */ |
409 | next(ls); | ||
410 | break; | ||
411 | } | ||
412 | case '-': { /* '-' or '--' (comment) */ | ||
342 | next(ls); | 413 | next(ls); |
343 | if (ls->current != '-') return '-'; | 414 | if (ls->current != '-') return '-'; |
344 | /* else is a comment */ | 415 | /* else is a comment */ |
345 | next(ls); | 416 | next(ls); |
346 | if (ls->current == '[') { | 417 | if (ls->current == '[') { /* long comment? */ |
347 | int sep = skip_sep(ls); | 418 | int sep = skip_sep(ls); |
348 | luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ | 419 | luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ |
349 | if (sep >= 0) { | 420 | if (sep >= 0) { |
350 | read_long_string(ls, NULL, sep); /* long comment */ | 421 | read_long_string(ls, NULL, sep); /* skip long comment */ |
351 | luaZ_resetbuffer(ls->buff); | 422 | luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ |
352 | continue; | 423 | break; |
353 | } | 424 | } |
354 | } | 425 | } |
355 | /* else short comment */ | 426 | /* else short comment */ |
356 | while (!currIsNewline(ls) && ls->current != EOZ) | 427 | while (!currIsNewline(ls) && ls->current != EOZ) |
357 | next(ls); | 428 | next(ls); /* skip until end of line (or end of file) */ |
358 | continue; | 429 | break; |
359 | } | 430 | } |
360 | case '[': { | 431 | case '[': { /* long string or simply '[' */ |
361 | int sep = skip_sep(ls); | 432 | int sep = skip_sep(ls); |
362 | if (sep >= 0) { | 433 | if (sep >= 0) { |
363 | read_long_string(ls, seminfo, sep); | 434 | read_long_string(ls, seminfo, sep); |
364 | return TK_STRING; | 435 | return TK_STRING; |
365 | } | 436 | } |
366 | else if (sep == -1) return '['; | 437 | else if (sep == -1) return '['; |
367 | else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); | 438 | else lexerror(ls, "invalid long string delimiter", TK_STRING); |
368 | } | 439 | } |
369 | case '=': { | 440 | case '=': { |
370 | next(ls); | 441 | next(ls); |
@@ -386,56 +457,52 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
386 | if (ls->current != '=') return '~'; | 457 | if (ls->current != '=') return '~'; |
387 | else { next(ls); return TK_NE; } | 458 | else { next(ls); return TK_NE; } |
388 | } | 459 | } |
389 | case '"': | 460 | case ':': { |
390 | case '\'': { | 461 | next(ls); |
462 | if (ls->current != ':') return ':'; | ||
463 | else { next(ls); return TK_DBCOLON; } | ||
464 | } | ||
465 | case '"': case '\'': { /* short literal strings */ | ||
391 | read_string(ls, ls->current, seminfo); | 466 | read_string(ls, ls->current, seminfo); |
392 | return TK_STRING; | 467 | return TK_STRING; |
393 | } | 468 | } |
394 | case '.': { | 469 | case '.': { /* '.', '..', '...', or number */ |
395 | save_and_next(ls); | 470 | save_and_next(ls); |
396 | if (check_next(ls, ".")) { | 471 | if (check_next(ls, ".")) { |
397 | if (check_next(ls, ".")) | 472 | if (check_next(ls, ".")) |
398 | return TK_DOTS; /* ... */ | 473 | return TK_DOTS; /* '...' */ |
399 | else return TK_CONCAT; /* .. */ | 474 | else return TK_CONCAT; /* '..' */ |
400 | } | ||
401 | else if (!isdigit(ls->current)) return '.'; | ||
402 | else { | ||
403 | read_numeral(ls, seminfo); | ||
404 | return TK_NUMBER; | ||
405 | } | 475 | } |
476 | else if (!lisdigit(ls->current)) return '.'; | ||
477 | /* else go through */ | ||
478 | } | ||
479 | case '0': case '1': case '2': case '3': case '4': | ||
480 | case '5': case '6': case '7': case '8': case '9': { | ||
481 | read_numeral(ls, seminfo); | ||
482 | return TK_NUMBER; | ||
406 | } | 483 | } |
407 | case EOZ: { | 484 | case EOZ: { |
408 | return TK_EOS; | 485 | return TK_EOS; |
409 | } | 486 | } |
410 | default: { | 487 | default: { |
411 | if (isspace(ls->current)) { | 488 | if (lislalpha(ls->current)) { /* identifier or reserved word? */ |
412 | lua_assert(!currIsNewline(ls)); | ||
413 | next(ls); | ||
414 | continue; | ||
415 | } | ||
416 | else if (isdigit(ls->current)) { | ||
417 | read_numeral(ls, seminfo); | ||
418 | return TK_NUMBER; | ||
419 | } | ||
420 | else if (isalpha(ls->current) || ls->current == '_') { | ||
421 | /* identifier or reserved word */ | ||
422 | TString *ts; | 489 | TString *ts; |
423 | do { | 490 | do { |
424 | save_and_next(ls); | 491 | save_and_next(ls); |
425 | } while (isalnum(ls->current) || ls->current == '_'); | 492 | } while (lislalnum(ls->current)); |
426 | ts = luaX_newstring(ls, luaZ_buffer(ls->buff), | 493 | ts = luaX_newstring(ls, luaZ_buffer(ls->buff), |
427 | luaZ_bufflen(ls->buff)); | 494 | luaZ_bufflen(ls->buff)); |
428 | if (ts->tsv.reserved > 0) /* reserved word? */ | 495 | seminfo->ts = ts; |
429 | return ts->tsv.reserved - 1 + FIRST_RESERVED; | 496 | if (isreserved(ts)) /* reserved word? */ |
497 | return ts->tsv.extra - 1 + FIRST_RESERVED; | ||
430 | else { | 498 | else { |
431 | seminfo->ts = ts; | ||
432 | return TK_NAME; | 499 | return TK_NAME; |
433 | } | 500 | } |
434 | } | 501 | } |
435 | else { | 502 | else { /* single-char tokens (+ - / ...) */ |
436 | int c = ls->current; | 503 | int c = ls->current; |
437 | next(ls); | 504 | next(ls); |
438 | return c; /* single-char tokens (+ - / ...) */ | 505 | return c; |
439 | } | 506 | } |
440 | } | 507 | } |
441 | } | 508 | } |
@@ -454,8 +521,9 @@ void luaX_next (LexState *ls) { | |||
454 | } | 521 | } |
455 | 522 | ||
456 | 523 | ||
457 | void luaX_lookahead (LexState *ls) { | 524 | int luaX_lookahead (LexState *ls) { |
458 | lua_assert(ls->lookahead.token == TK_EOS); | 525 | lua_assert(ls->lookahead.token == TK_EOS); |
459 | ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); | 526 | ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); |
527 | return ls->lookahead.token; | ||
460 | } | 528 | } |
461 | 529 | ||