diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-05-27 10:08:34 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-05-27 10:08:34 -0300 |
commit | 7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6 (patch) | |
tree | 1834168cd16e821a017e3d8408978f89e6c2ddaf | |
parent | abc6eac404da8181ad945ac6950f61a65ba7dfa5 (diff) | |
download | lua-7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6.tar.gz lua-7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6.tar.bz2 lua-7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6.zip |
NEW LL(1) PARSER
-rw-r--r-- | llex.c | 138 | ||||
-rw-r--r-- | llex.h | 31 | ||||
-rw-r--r-- | lparser.c | 1332 | ||||
-rw-r--r-- | lstate.h | 4 | ||||
-rw-r--r-- | lua.stx | 940 | ||||
-rw-r--r-- | makefile | 22 |
6 files changed, 1442 insertions, 1025 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llex.c,v 1.17 1998/03/09 17:22:49 roberto Exp roberto $ | 2 | ** $Id: llex.c,v 1.18 1998/03/20 14:18:18 roberto Exp roberto $ |
3 | ** Lexical Analizer | 3 | ** Lexical Analizer |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -15,7 +15,6 @@ | |||
15 | #include "lparser.h" | 15 | #include "lparser.h" |
16 | #include "lstate.h" | 16 | #include "lstate.h" |
17 | #include "lstring.h" | 17 | #include "lstring.h" |
18 | #include "lstx.h" | ||
19 | #include "luadebug.h" | 18 | #include "luadebug.h" |
20 | #include "lzio.h" | 19 | #include "lzio.h" |
21 | 20 | ||
@@ -27,23 +26,53 @@ int lua_debug=0; | |||
27 | #define next(LS) (LS->current = zgetc(LS->lex_z)) | 26 | #define next(LS) (LS->current = zgetc(LS->lex_z)) |
28 | 27 | ||
29 | 28 | ||
30 | static struct { | 29 | #define save(c) luaL_addchar(c) |
31 | char *name; | 30 | #define save_and_next(LS) (save(LS->current), next(LS)) |
32 | int token; | 31 | |
33 | } reserved [] = { | 32 | |
34 | {"and", AND}, {"do", DO}, {"else", ELSE}, {"elseif", ELSEIF}, | 33 | char *reserved [] = {"and", "do", "else", "elseif", "end", "function", |
35 | {"end", END}, {"function", FUNCTION}, {"if", IF}, {"local", LOCAL}, | 34 | "if", "local", "nil", "not", "or", "repeat", "return", "then", |
36 | {"nil", NIL}, {"not", NOT}, {"or", OR}, {"repeat", REPEAT}, | 35 | "until", "while"}; |
37 | {"return", RETURN}, {"then", THEN}, {"until", UNTIL}, {"while", WHILE} | 36 | |
38 | }; | ||
39 | 37 | ||
40 | void luaX_init (void) | 38 | void luaX_init (void) |
41 | { | 39 | { |
42 | int i; | 40 | int i; |
43 | for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) { | 41 | for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) { |
44 | TaggedString *ts = luaS_new(reserved[i].name); | 42 | TaggedString *ts = luaS_new(reserved[i]); |
45 | ts->head.marked = reserved[i].token; /* reserved word (always > 255) */ | 43 | ts->head.marked = FIRST_RESERVED+i; /* reserved word (always > 255) */ |
44 | } | ||
45 | } | ||
46 | |||
47 | |||
48 | void luaX_syntaxerror (LexState *ls, char *s, char *token) { | ||
49 | if (token[0] == 0) | ||
50 | token = "<eof>"; | ||
51 | luaL_verror("%.100s;\n last token read: `%.50s' at line %d in file %.50s", | ||
52 | s, token, ls->linenumber, zname(ls->lex_z)); | ||
53 | } | ||
54 | |||
55 | |||
56 | void luaX_error (LexState *ls, char *s) { | ||
57 | save(0); | ||
58 | luaX_syntaxerror(ls, s, luaL_buffer()); | ||
59 | } | ||
60 | |||
61 | |||
62 | void luaX_token2str (LexState *ls, int token, char *s) { | ||
63 | if (token < 255) { | ||
64 | s[0] = token; | ||
65 | s[1] = 0; | ||
46 | } | 66 | } |
67 | else | ||
68 | strcpy(s, reserved[token-FIRST_RESERVED]); | ||
69 | } | ||
70 | |||
71 | |||
72 | static void luaX_invalidchar (LexState *ls, int c) { | ||
73 | char buff[10]; | ||
74 | sprintf(buff, "0x%X", c); | ||
75 | luaX_syntaxerror(ls, "invalid control char", buff); | ||
47 | } | 76 | } |
48 | 77 | ||
49 | 78 | ||
@@ -56,16 +85,15 @@ static void firstline (LexState *LS) | |||
56 | } | 85 | } |
57 | 86 | ||
58 | 87 | ||
59 | void luaX_setinput (ZIO *z) | 88 | void luaX_setinput (LexState *LS, ZIO *z) |
60 | { | 89 | { |
61 | LexState *LS = L->lexstate; | ||
62 | LS->current = '\n'; | 90 | LS->current = '\n'; |
63 | LS->linelasttoken = 0; | ||
64 | LS->linenumber = 0; | 91 | LS->linenumber = 0; |
65 | LS->iflevel = 0; | 92 | LS->iflevel = 0; |
66 | LS->ifstate[0].skip = 0; | 93 | LS->ifstate[0].skip = 0; |
67 | LS->ifstate[0].elsepart = 1; /* to avoid a free $else */ | 94 | LS->ifstate[0].elsepart = 1; /* to avoid a free $else */ |
68 | LS->lex_z = z; | 95 | LS->lex_z = z; |
96 | LS->fs = NULL; | ||
69 | firstline(LS); | 97 | firstline(LS); |
70 | luaL_resetbuffer(); | 98 | luaL_resetbuffer(); |
71 | } | 99 | } |
@@ -87,7 +115,7 @@ static void skipspace (LexState *LS) | |||
87 | } | 115 | } |
88 | 116 | ||
89 | 117 | ||
90 | static int checkcond (char *buff) | 118 | static int checkcond (LexState *LS, char *buff) |
91 | { | 119 | { |
92 | static char *opts[] = {"nil", "1", NULL}; | 120 | static char *opts[] = {"nil", "1", NULL}; |
93 | int i = luaO_findstring(buff, opts); | 121 | int i = luaO_findstring(buff, opts); |
@@ -95,7 +123,7 @@ static int checkcond (char *buff) | |||
95 | else if (isalpha((unsigned char)buff[0]) || buff[0] == '_') | 123 | else if (isalpha((unsigned char)buff[0]) || buff[0] == '_') |
96 | return luaS_globaldefined(buff); | 124 | return luaS_globaldefined(buff); |
97 | else { | 125 | else { |
98 | luaY_syntaxerror("invalid $if condition", buff); | 126 | luaX_syntaxerror(LS, "invalid $if condition", buff); |
99 | return 0; /* to avoid warnings */ | 127 | return 0; /* to avoid warnings */ |
100 | } | 128 | } |
101 | } | 129 | } |
@@ -108,7 +136,7 @@ static void readname (LexState *LS, char *buff) | |||
108 | while (isalnum(LS->current) || LS->current == '_') { | 136 | while (isalnum(LS->current) || LS->current == '_') { |
109 | if (i >= PRAGMASIZE) { | 137 | if (i >= PRAGMASIZE) { |
110 | buff[PRAGMASIZE] = 0; | 138 | buff[PRAGMASIZE] = 0; |
111 | luaY_syntaxerror("pragma too long", buff); | 139 | luaX_syntaxerror(LS, "pragma too long", buff); |
112 | } | 140 | } |
113 | buff[i++] = LS->current; | 141 | buff[i++] = LS->current; |
114 | next(LS); | 142 | next(LS); |
@@ -126,7 +154,7 @@ static void ifskip (LexState *LS) | |||
126 | if (LS->current == '\n') | 154 | if (LS->current == '\n') |
127 | inclinenumber(LS); | 155 | inclinenumber(LS); |
128 | else if (LS->current == EOZ) | 156 | else if (LS->current == EOZ) |
129 | luaY_error("input ends inside a $if"); | 157 | luaX_error(LS, "input ends inside a $if"); |
130 | else next(LS); | 158 | else next(LS); |
131 | } | 159 | } |
132 | } | 160 | } |
@@ -159,35 +187,35 @@ static void inclinenumber (LexState *LS) | |||
159 | break; | 187 | break; |
160 | case 3: /* end */ | 188 | case 3: /* end */ |
161 | if (LS->iflevel-- == 0) | 189 | if (LS->iflevel-- == 0) |
162 | luaY_syntaxerror("unmatched $end", "$end"); | 190 | luaX_syntaxerror(LS, "unmatched $end", "$end"); |
163 | break; | 191 | break; |
164 | case 4: /* ifnot */ | 192 | case 4: /* ifnot */ |
165 | ifnot = 1; | 193 | ifnot = 1; |
166 | /* go through */ | 194 | /* go through */ |
167 | case 5: /* if */ | 195 | case 5: /* if */ |
168 | if (LS->iflevel == MAX_IFS-1) | 196 | if (LS->iflevel == MAX_IFS-1) |
169 | luaY_syntaxerror("too many nested $ifs", "$if"); | 197 | luaX_syntaxerror(LS, "too many nested $ifs", "$if"); |
170 | readname(LS, buff); | 198 | readname(LS, buff); |
171 | LS->iflevel++; | 199 | LS->iflevel++; |
172 | LS->ifstate[LS->iflevel].elsepart = 0; | 200 | LS->ifstate[LS->iflevel].elsepart = 0; |
173 | LS->ifstate[LS->iflevel].condition = checkcond(buff) ? !ifnot : ifnot; | 201 | LS->ifstate[LS->iflevel].condition = checkcond(LS, buff) ? !ifnot : ifnot; |
174 | LS->ifstate[LS->iflevel].skip = skip || !LS->ifstate[LS->iflevel].condition; | 202 | LS->ifstate[LS->iflevel].skip = skip || !LS->ifstate[LS->iflevel].condition; |
175 | break; | 203 | break; |
176 | case 6: /* else */ | 204 | case 6: /* else */ |
177 | if (LS->ifstate[LS->iflevel].elsepart) | 205 | if (LS->ifstate[LS->iflevel].elsepart) |
178 | luaY_syntaxerror("unmatched $else", "$else"); | 206 | luaX_syntaxerror(LS, "unmatched $else", "$else"); |
179 | LS->ifstate[LS->iflevel].elsepart = 1; | 207 | LS->ifstate[LS->iflevel].elsepart = 1; |
180 | LS->ifstate[LS->iflevel].skip = LS->ifstate[LS->iflevel-1].skip || | 208 | LS->ifstate[LS->iflevel].skip = LS->ifstate[LS->iflevel-1].skip || |
181 | LS->ifstate[LS->iflevel].condition; | 209 | LS->ifstate[LS->iflevel].condition; |
182 | break; | 210 | break; |
183 | default: | 211 | default: |
184 | luaY_syntaxerror("unknown pragma", buff); | 212 | luaX_syntaxerror(LS, "unknown pragma", buff); |
185 | } | 213 | } |
186 | skipspace(LS); | 214 | skipspace(LS); |
187 | if (LS->current == '\n') /* pragma must end with a '\n' ... */ | 215 | if (LS->current == '\n') /* pragma must end with a '\n' ... */ |
188 | inclinenumber(LS); | 216 | inclinenumber(LS); |
189 | else if (LS->current != EOZ) /* or eof */ | 217 | else if (LS->current != EOZ) /* or eof */ |
190 | luaY_syntaxerror("invalid pragma format", buff); | 218 | luaX_syntaxerror(LS, "invalid pragma format", buff); |
191 | ifskip(LS); | 219 | ifskip(LS); |
192 | } | 220 | } |
193 | } | 221 | } |
@@ -201,25 +229,16 @@ static void inclinenumber (LexState *LS) | |||
201 | 229 | ||
202 | 230 | ||
203 | 231 | ||
204 | #define save(c) luaL_addchar(c) | ||
205 | #define save_and_next(LS) (save(LS->current), next(LS)) | ||
206 | |||
207 | |||
208 | char *luaX_lasttoken (void) | ||
209 | { | ||
210 | save(0); | ||
211 | return luaL_buffer(); | ||
212 | } | ||
213 | 232 | ||
214 | 233 | ||
215 | static int read_long_string (LexState *LS, YYSTYPE *l) | 234 | static int read_long_string (LexState *LS) |
216 | { | 235 | { |
217 | int cont = 0; | 236 | int cont = 0; |
218 | while (1) { | 237 | while (1) { |
219 | switch (LS->current) { | 238 | switch (LS->current) { |
220 | case EOZ: | 239 | case EOZ: |
221 | luaY_error("unfinished long string"); | 240 | luaX_error(LS, "unfinished long string"); |
222 | return 0; /* to avoid warnings */ | 241 | return EOS; /* to avoid warnings */ |
223 | case '[': | 242 | case '[': |
224 | save_and_next(LS); | 243 | save_and_next(LS); |
225 | if (LS->current == '[') { | 244 | if (LS->current == '[') { |
@@ -244,25 +263,15 @@ static int read_long_string (LexState *LS, YYSTYPE *l) | |||
244 | } | 263 | } |
245 | } endloop: | 264 | } endloop: |
246 | save_and_next(LS); /* pass the second ']' */ | 265 | save_and_next(LS); /* pass the second ']' */ |
247 | l->pTStr = luaS_newlstr(L->Mbuffbase+2, | 266 | LS->seminfo.ts = luaS_newlstr(L->Mbuffbase+2, |
248 | L->Mbuffnext-(L->Mbuffbase-L->Mbuffer)-4); | 267 | L->Mbuffnext-(L->Mbuffbase-L->Mbuffer)-4); |
249 | return STRING; | 268 | return STRING; |
250 | } | 269 | } |
251 | 270 | ||
252 | 271 | ||
253 | /* to avoid warnings; this declaration cannot be public since YYSTYPE | 272 | int luaX_lex (LexState *LS) { |
254 | ** cannot be visible in llex.h (otherwise there is an error, since | ||
255 | ** the parser body redefines it!) | ||
256 | */ | ||
257 | int luaY_lex (YYSTYPE *l); | ||
258 | int luaY_lex (YYSTYPE *l) | ||
259 | { | ||
260 | LexState *LS = L->lexstate; | ||
261 | double a; | 273 | double a; |
262 | luaL_resetbuffer(); | 274 | luaL_resetbuffer(); |
263 | if (lua_debug) | ||
264 | luaY_codedebugline(LS->linelasttoken); | ||
265 | LS->linelasttoken = LS->linenumber; | ||
266 | while (1) { | 275 | while (1) { |
267 | switch (LS->current) { | 276 | switch (LS->current) { |
268 | 277 | ||
@@ -272,7 +281,6 @@ int luaY_lex (YYSTYPE *l) | |||
272 | 281 | ||
273 | case '\n': | 282 | case '\n': |
274 | inclinenumber(LS); | 283 | inclinenumber(LS); |
275 | LS->linelasttoken = LS->linenumber; | ||
276 | continue; | 284 | continue; |
277 | 285 | ||
278 | case '-': | 286 | case '-': |
@@ -287,7 +295,7 @@ int luaY_lex (YYSTYPE *l) | |||
287 | if (LS->current != '[') return '['; | 295 | if (LS->current != '[') return '['; |
288 | else { | 296 | else { |
289 | save_and_next(LS); /* pass the second '[' */ | 297 | save_and_next(LS); /* pass the second '[' */ |
290 | return read_long_string(LS, l); | 298 | return read_long_string(LS); |
291 | } | 299 | } |
292 | 300 | ||
293 | case '=': | 301 | case '=': |
@@ -318,8 +326,8 @@ int luaY_lex (YYSTYPE *l) | |||
318 | switch (LS->current) { | 326 | switch (LS->current) { |
319 | case EOZ: | 327 | case EOZ: |
320 | case '\n': | 328 | case '\n': |
321 | luaY_error("unfinished string"); | 329 | luaX_error(LS, "unfinished string"); |
322 | return 0; /* to avoid warnings */ | 330 | return EOS; /* to avoid warnings */ |
323 | case '\\': | 331 | case '\\': |
324 | next(LS); /* do not save the '\' */ | 332 | next(LS); /* do not save the '\' */ |
325 | switch (LS->current) { | 333 | switch (LS->current) { |
@@ -345,13 +353,13 @@ int luaY_lex (YYSTYPE *l) | |||
345 | next(LS); | 353 | next(LS); |
346 | } while (++i<3 && isdigit(LS->current)); | 354 | } while (++i<3 && isdigit(LS->current)); |
347 | if (c >= 256) | 355 | if (c >= 256) |
348 | luaY_error("escape sequence too large"); | 356 | luaX_error(LS, "escape sequence too large"); |
349 | save(c); | 357 | save(c); |
350 | } | 358 | } |
351 | else { | 359 | else { |
352 | save('\\'); | 360 | save('\\'); |
353 | save(LS->current); | 361 | save(LS->current); |
354 | luaY_error("invalid escape sequence"); | 362 | luaX_error(LS, "invalid escape sequence"); |
355 | } | 363 | } |
356 | break; | 364 | break; |
357 | } | 365 | } |
@@ -362,7 +370,7 @@ int luaY_lex (YYSTYPE *l) | |||
362 | } | 370 | } |
363 | } | 371 | } |
364 | save_and_next(LS); /* skip delimiter */ | 372 | save_and_next(LS); /* skip delimiter */ |
365 | l->pTStr = luaS_newlstr(L->Mbuffbase+1, | 373 | LS->seminfo.ts = luaS_newlstr(L->Mbuffbase+1, |
366 | L->Mbuffnext-(L->Mbuffbase-L->Mbuffer)-2); | 374 | L->Mbuffnext-(L->Mbuffbase-L->Mbuffer)-2); |
367 | return STRING; | 375 | return STRING; |
368 | } | 376 | } |
@@ -395,7 +403,7 @@ int luaY_lex (YYSTYPE *l) | |||
395 | save_and_next(LS); | 403 | save_and_next(LS); |
396 | if (LS->current == '.') { | 404 | if (LS->current == '.') { |
397 | save('.'); | 405 | save('.'); |
398 | luaY_error( | 406 | luaX_error(LS, |
399 | "ambiguous syntax (decimal point x string concatenation)"); | 407 | "ambiguous syntax (decimal point x string concatenation)"); |
400 | } | 408 | } |
401 | } | 409 | } |
@@ -415,7 +423,7 @@ int luaY_lex (YYSTYPE *l) | |||
415 | neg = (LS->current=='-'); | 423 | neg = (LS->current=='-'); |
416 | if (LS->current == '+' || LS->current == '-') save_and_next(LS); | 424 | if (LS->current == '+' || LS->current == '-') save_and_next(LS); |
417 | if (!isdigit(LS->current)) | 425 | if (!isdigit(LS->current)) |
418 | luaY_error("invalid numeral format"); | 426 | luaX_error(LS, "invalid numeral format"); |
419 | do { | 427 | do { |
420 | e = 10.0*e + (LS->current-'0'); | 428 | e = 10.0*e + (LS->current-'0'); |
421 | save_and_next(LS); | 429 | save_and_next(LS); |
@@ -426,18 +434,20 @@ int luaY_lex (YYSTYPE *l) | |||
426 | ea *= ea; | 434 | ea *= ea; |
427 | } | 435 | } |
428 | } | 436 | } |
429 | l->vReal = a; | 437 | LS->seminfo.r = a; |
430 | return NUMBER; | 438 | return NUMBER; |
431 | } | 439 | } |
432 | 440 | ||
433 | case EOZ: | 441 | case EOZ: |
434 | if (LS->iflevel > 0) | 442 | if (LS->iflevel > 0) |
435 | luaY_error("input ends inside a $if"); | 443 | luaX_error(LS, "input ends inside a $if"); |
436 | return 0; | 444 | return EOS; |
437 | 445 | ||
438 | default: | 446 | default: |
439 | if (LS->current != '_' && !isalpha(LS->current)) { | 447 | if (LS->current != '_' && !isalpha(LS->current)) { |
440 | int c = LS->current; | 448 | int c = LS->current; |
449 | if (iscntrl(c)) | ||
450 | luaX_invalidchar(LS, c); | ||
441 | save_and_next(LS); | 451 | save_and_next(LS); |
442 | return c; | 452 | return c; |
443 | } | 453 | } |
@@ -448,9 +458,9 @@ int luaY_lex (YYSTYPE *l) | |||
448 | } while (isalnum(LS->current) || LS->current == '_'); | 458 | } while (isalnum(LS->current) || LS->current == '_'); |
449 | save(0); | 459 | save(0); |
450 | ts = luaS_new(L->Mbuffbase); | 460 | ts = luaS_new(L->Mbuffbase); |
451 | if (ts->head.marked > 255) | 461 | if (ts->head.marked >= 'A') |
452 | return ts->head.marked; /* reserved word */ | 462 | return ts->head.marked; /* reserved word */ |
453 | l->pTStr = ts; | 463 | LS->seminfo.ts = ts; |
454 | return NAME; | 464 | return NAME; |
455 | } | 465 | } |
456 | } | 466 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llex.h,v 1.6 1997/12/17 20:48:58 roberto Exp roberto $ | 2 | ** $Id: llex.h,v 1.7 1998/01/09 14:57:43 roberto Exp $ |
3 | ** Lexical Analizer | 3 | ** Lexical Analizer |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -11,6 +11,20 @@ | |||
11 | #include "lzio.h" | 11 | #include "lzio.h" |
12 | 12 | ||
13 | 13 | ||
14 | #define FIRST_RESERVED 260 | ||
15 | |||
16 | /* maximum length of a reserved word (+1 for terminal 0) */ | ||
17 | #define TOKEN_LEN 15 | ||
18 | |||
19 | enum RESERVED { | ||
20 | /* terminal symbols denoted by reserved words */ | ||
21 | AND = FIRST_RESERVED, | ||
22 | DO, ELSE, ELSEIF, END, FUNCTION, IF, LOCAL, NIL, NOT, OR, | ||
23 | REPEAT, RETURN, THEN, UNTIL, WHILE, | ||
24 | /* other terminal symbols */ | ||
25 | NAME, CONC, DOTS, EQ, GE, LE, NE, NUMBER, STRING, EOS}; | ||
26 | |||
27 | |||
14 | #define MAX_IFS 5 | 28 | #define MAX_IFS 5 |
15 | 29 | ||
16 | /* "ifstate" keeps the state of each nested $if the lexical is dealing with. */ | 30 | /* "ifstate" keeps the state of each nested $if the lexical is dealing with. */ |
@@ -24,18 +38,25 @@ struct ifState { | |||
24 | 38 | ||
25 | typedef struct LexState { | 39 | typedef struct LexState { |
26 | int current; /* look ahead character */ | 40 | int current; /* look ahead character */ |
41 | int token; /* look ahead token */ | ||
42 | struct FuncState *fs; /* 'FuncState' is private for the parser */ | ||
43 | union { | ||
44 | real r; | ||
45 | TaggedString *ts; | ||
46 | } seminfo; /* semantics information */ | ||
27 | struct zio *lex_z; /* input stream */ | 47 | struct zio *lex_z; /* input stream */ |
28 | int linenumber; /* input line counter */ | 48 | int linenumber; /* input line counter */ |
29 | int linelasttoken; /* line where last token was read */ | ||
30 | int lastline; /* last line wherein a SETLINE was generated */ | ||
31 | int iflevel; /* level of nested $if's (for lexical analysis) */ | 49 | int iflevel; /* level of nested $if's (for lexical analysis) */ |
32 | struct ifState ifstate[MAX_IFS]; | 50 | struct ifState ifstate[MAX_IFS]; |
33 | } LexState; | 51 | } LexState; |
34 | 52 | ||
35 | 53 | ||
36 | void luaX_init (void); | 54 | void luaX_init (void); |
37 | void luaX_setinput (ZIO *z); | 55 | void luaX_setinput (LexState *LS, ZIO *z); |
38 | char *luaX_lasttoken (void); | 56 | int luaX_lex (LexState *LS); |
57 | void luaX_syntaxerror (LexState *ls, char *s, char *token); | ||
58 | void luaX_error (LexState *ls, char *s); | ||
59 | void luaX_token2str (LexState *ls, int token, char *s); | ||
39 | 60 | ||
40 | 61 | ||
41 | #endif | 62 | #endif |
diff --git a/lparser.c b/lparser.c new file mode 100644 index 00000000..0eefb204 --- /dev/null +++ b/lparser.c | |||
@@ -0,0 +1,1332 @@ | |||
1 | /* | ||
2 | ** $Id: $ | ||
3 | ** LL(1) Parser and code generator for Lua | ||
4 | ** See Copyright Notice in lua.h | ||
5 | */ | ||
6 | |||
7 | |||
8 | #include <stdio.h> | ||
9 | |||
10 | #include "lauxlib.h" | ||
11 | #include "ldo.h" | ||
12 | #include "lfunc.h" | ||
13 | #include "llex.h" | ||
14 | #include "lmem.h" | ||
15 | #include "lopcodes.h" | ||
16 | #include "lparser.h" | ||
17 | #include "lstate.h" | ||
18 | #include "lstring.h" | ||
19 | #include "lua.h" | ||
20 | #include "luadebug.h" | ||
21 | #include "lzio.h" | ||
22 | |||
23 | |||
24 | /* for limit numbers in error messages */ | ||
25 | #define MES_LIM(x) "(limit=" x ")" | ||
26 | |||
27 | |||
28 | /* size of a "normal" jump instruction: OpCode + 1 byte */ | ||
29 | #define JMPSIZE 2 | ||
30 | |||
31 | /* maximum number of local variables */ | ||
32 | #define MAXLOCALS 32 | ||
33 | #define SMAXLOCALS "32" | ||
34 | |||
35 | |||
36 | /* maximum number of upvalues */ | ||
37 | #define MAXUPVALUES 16 | ||
38 | #define SMAXUPVALUES "16" | ||
39 | |||
40 | |||
41 | /* | ||
42 | ** Variable descriptor: | ||
43 | ** must include a "exp" option because LL(1) cannot distinguish | ||
44 | ** between variables, upvalues and function calls on first sight. | ||
45 | ** VGLOBAL: info is constant index of global name | ||
46 | ** VLOCAL: info is stack index | ||
47 | ** VDOT: info is constant index of index name | ||
48 | ** VEXP: info is pc index of "nparam" of function call (or 0 if exp is closed) | ||
49 | */ | ||
50 | typedef enum {VGLOBAL, VLOCAL, VDOT, VINDEXED, VEXP} varkind; | ||
51 | |||
52 | typedef struct { | ||
53 | varkind k; | ||
54 | int info; | ||
55 | } vardesc; | ||
56 | |||
57 | |||
58 | /* | ||
59 | ** Expression List descriptor: | ||
60 | ** tells number of expressions in the list, | ||
61 | ** and, if last expression is open (a function call), | ||
62 | ** where is its pc index of "nparam" | ||
63 | */ | ||
64 | typedef struct { | ||
65 | int n; | ||
66 | int pc; /* 0 if last expression is closed */ | ||
67 | } listdesc; | ||
68 | |||
69 | |||
70 | /* | ||
71 | ** Constructors descriptor: | ||
72 | ** "n" indicates number of elements, and "k" signals whether | ||
73 | ** it is a list constructor (k = 0) or a record constructor (k = 1) | ||
74 | ** or empty (k = ';' or '}') | ||
75 | */ | ||
76 | typedef struct { | ||
77 | int n; | ||
78 | int k; | ||
79 | } constdesc; | ||
80 | |||
81 | |||
82 | /* state needed to generate code for a given function */ | ||
83 | typedef struct FuncState { | ||
84 | TProtoFunc *f; /* current function header */ | ||
85 | struct FuncState *prev; /* enclosuring function */ | ||
86 | int pc; /* next position to code */ | ||
87 | int stacksize; /* number of values on activation register */ | ||
88 | int maxstacksize; /* maximum number of values on activation register */ | ||
89 | int nlocalvar; /* number of active local variables */ | ||
90 | int nupvalues; /* number of upvalues */ | ||
91 | int nvars; /* number of entries in f->locvars */ | ||
92 | int maxcode; /* size of f->code */ | ||
93 | int maxvars; /* size of f->locvars (-1 if no debug information) */ | ||
94 | int maxconsts; /* size of f->consts */ | ||
95 | int lastsetline; /* line where last SETLINE was issued */ | ||
96 | vardesc upvalues[MAXUPVALUES]; /* upvalues */ | ||
97 | TaggedString *localvar[MAXLOCALS]; /* store local variable names */ | ||
98 | } FuncState; | ||
99 | |||
100 | |||
101 | static int assignment (LexState *ls, vardesc *v, int nvars); | ||
102 | static int cond (LexState *ls); | ||
103 | static int funcname (LexState *ls, vardesc *v); | ||
104 | static int funcparams (LexState *ls, int slf); | ||
105 | static int listfields (LexState *ls); | ||
106 | static int localnamelist (LexState *ls); | ||
107 | static int optional (LexState *ls, int c); | ||
108 | static int recfields (LexState *ls); | ||
109 | static int stat (LexState *ls); | ||
110 | static void block (LexState *ls); | ||
111 | static void body (LexState *ls, int needself, int line); | ||
112 | static void chunk (LexState *ls); | ||
113 | static void constructor (LexState *ls); | ||
114 | static void decinit (LexState *ls, listdesc *d); | ||
115 | static void exp (LexState *ls, vardesc *v); | ||
116 | static void exp1 (LexState *ls); | ||
117 | static void exp2 (LexState *ls, vardesc *v); | ||
118 | static void explist (LexState *ls, listdesc *e); | ||
119 | static void explist1 (LexState *ls, listdesc *e); | ||
120 | static void ifpart (LexState *ls); | ||
121 | static void parlist (LexState *ls); | ||
122 | static void part (LexState *ls, constdesc *cd); | ||
123 | static void recfield (LexState *ls); | ||
124 | static void ret (LexState *ls); | ||
125 | static void simpleexp (LexState *ls, vardesc *v); | ||
126 | static void statlist (LexState *ls); | ||
127 | static void var_or_func (LexState *ls, vardesc *v); | ||
128 | static void var_or_func_tail (LexState *ls, vardesc *v); | ||
129 | |||
130 | |||
131 | |||
132 | static void check_pc (FuncState *fs, int n) { | ||
133 | if (fs->pc+n > fs->maxcode) | ||
134 | fs->maxcode = luaM_growvector(&fs->f->code, fs->maxcode, | ||
135 | Byte, codeEM, MAX_INT); | ||
136 | } | ||
137 | |||
138 | |||
139 | static void code_byte (FuncState *fs, Byte c) { | ||
140 | check_pc(fs, 1); | ||
141 | fs->f->code[fs->pc++] = c; | ||
142 | } | ||
143 | |||
144 | |||
145 | static void deltastack (LexState *ls, int delta) { | ||
146 | FuncState *fs = ls->fs; | ||
147 | fs->stacksize += delta; | ||
148 | if (fs->stacksize > fs->maxstacksize) { | ||
149 | if (fs->stacksize > 255) | ||
150 | luaX_error(ls, "function/expression too complex"); | ||
151 | fs->maxstacksize = fs->stacksize; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | |||
156 | static int code_oparg_at (LexState *ls, int pc, OpCode op, int builtin, | ||
157 | int arg, int delta) { | ||
158 | Byte *code = ls->fs->f->code; | ||
159 | deltastack(ls, delta); | ||
160 | if (arg < builtin) { | ||
161 | code[pc] = op+1+arg; | ||
162 | return 1; | ||
163 | } | ||
164 | else if (arg <= 255) { | ||
165 | code[pc] = op; | ||
166 | code[pc+1] = arg; | ||
167 | return 2; | ||
168 | } | ||
169 | else if (arg <= MAX_WORD) { | ||
170 | code[pc] = op+1+builtin; | ||
171 | code[pc+1] = arg>>8; | ||
172 | code[pc+2] = arg&0xFF; | ||
173 | return 3; | ||
174 | } | ||
175 | else luaX_error(ls, "code too long " MES_LIM("64K")); | ||
176 | return 0; /* to avoid warnings */ | ||
177 | } | ||
178 | |||
179 | |||
180 | static int fix_opcode (LexState *ls, int pc, OpCode op, int builtin, int arg) { | ||
181 | FuncState *fs = ls->fs; | ||
182 | TProtoFunc *f = fs->f; | ||
183 | if (arg < builtin) { /* close space */ | ||
184 | luaO_memdown(f->code+pc+1, f->code+pc+2, fs->pc-(pc+2)); | ||
185 | fs->pc--; | ||
186 | } | ||
187 | else if (arg > 255) { /* open space */ | ||
188 | check_pc(fs, 1); | ||
189 | luaO_memup(f->code+pc+1, f->code+pc, fs->pc-pc); | ||
190 | fs->pc++; | ||
191 | } | ||
192 | return code_oparg_at(ls, pc, op, builtin, arg, 0) - 2; | ||
193 | } | ||
194 | |||
195 | static void code_oparg (LexState *ls, OpCode op, int builtin, int arg, | ||
196 | int delta) { | ||
197 | check_pc(ls->fs, 3); /* maximum code size */ | ||
198 | ls->fs->pc += code_oparg_at(ls, ls->fs->pc, op, builtin, arg, delta); | ||
199 | } | ||
200 | |||
201 | |||
202 | static void code_opcode (LexState *ls, OpCode op, int delta) { | ||
203 | deltastack(ls, delta); | ||
204 | code_byte(ls->fs, op); | ||
205 | } | ||
206 | |||
207 | |||
208 | static void code_constant (LexState *ls, int c) { | ||
209 | code_oparg(ls, PUSHCONSTANT, 8, c, 1); | ||
210 | } | ||
211 | |||
212 | |||
213 | static int next_constant (FuncState *fs) { | ||
214 | TProtoFunc *f = fs->f; | ||
215 | if (f->nconsts >= fs->maxconsts) { | ||
216 | fs->maxconsts = luaM_growvector(&f->consts, fs->maxconsts, TObject, | ||
217 | constantEM, MAX_WORD); | ||
218 | } | ||
219 | return f->nconsts++; | ||
220 | } | ||
221 | |||
222 | |||
223 | static int string_constant (FuncState *fs, TaggedString *s) { | ||
224 | TProtoFunc *f = fs->f; | ||
225 | int c = s->constindex; | ||
226 | if (!(c < f->nconsts && | ||
227 | ttype(&f->consts[c]) == LUA_T_STRING && tsvalue(&f->consts[c]) == s)) { | ||
228 | c = next_constant(fs); | ||
229 | ttype(&f->consts[c]) = LUA_T_STRING; | ||
230 | tsvalue(&f->consts[c]) = s; | ||
231 | s->constindex = c; /* hint for next time */ | ||
232 | } | ||
233 | return c; | ||
234 | } | ||
235 | |||
236 | |||
237 | static void code_string (LexState *ls, TaggedString *s) { | ||
238 | code_constant(ls, string_constant(ls->fs, s)); | ||
239 | } | ||
240 | |||
241 | |||
242 | #define LIM 20 | ||
243 | static int real_constant (FuncState *fs, real r) { | ||
244 | /* check whether 'r' has appeared within the last LIM entries */ | ||
245 | TObject *cnt = fs->f->consts; | ||
246 | int c = fs->f->nconsts; | ||
247 | int lim = c < LIM ? 0 : c-LIM; | ||
248 | while (--c >= lim) { | ||
249 | if (ttype(&cnt[c]) == LUA_T_NUMBER && nvalue(&cnt[c]) == r) | ||
250 | return c; | ||
251 | } | ||
252 | /* not found; create a luaM_new entry */ | ||
253 | c = next_constant(fs); | ||
254 | cnt = fs->f->consts; /* 'next_constant' may reallocate this vector */ | ||
255 | ttype(&cnt[c]) = LUA_T_NUMBER; | ||
256 | nvalue(&cnt[c]) = r; | ||
257 | return c; | ||
258 | } | ||
259 | |||
260 | |||
261 | static void code_number (LexState *ls, real f) { | ||
262 | int i; | ||
263 | if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(int)f) == f) | ||
264 | code_oparg(ls, PUSHNUMBER, 3, i, 1); /* f has a short integer value */ | ||
265 | else | ||
266 | code_constant(ls, real_constant(ls->fs, f)); | ||
267 | } | ||
268 | |||
269 | |||
270 | static void flush_record (LexState *ls, int n) { | ||
271 | if (n > 0) | ||
272 | code_oparg(ls, SETMAP, 1, n-1, -2*n); | ||
273 | } | ||
274 | |||
275 | |||
276 | static void flush_list (LexState *ls, int m, int n) { | ||
277 | if (n == 0) return; | ||
278 | code_oparg(ls, SETLIST, 1, m, -n); | ||
279 | code_byte(ls->fs, n); | ||
280 | } | ||
281 | |||
282 | |||
283 | static void luaI_registerlocalvar (FuncState *fs, TaggedString *varname, | ||
284 | int line) { | ||
285 | if (fs->maxvars != -1) { /* debug information? */ | ||
286 | TProtoFunc *f = fs->f; | ||
287 | if (fs->nvars >= fs->maxvars) | ||
288 | fs->maxvars = luaM_growvector(&f->locvars, fs->maxvars, | ||
289 | LocVar, "", MAX_WORD); | ||
290 | f->locvars[fs->nvars].varname = varname; | ||
291 | f->locvars[fs->nvars].line = line; | ||
292 | fs->nvars++; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | |||
297 | static void luaI_unregisterlocalvar (FuncState *fs, int line) { | ||
298 | luaI_registerlocalvar(fs, NULL, line); | ||
299 | } | ||
300 | |||
301 | |||
302 | static void store_localvar (LexState *ls, TaggedString *name, int n) { | ||
303 | FuncState *fs = ls->fs; | ||
304 | if (fs->nlocalvar+n < MAXLOCALS) | ||
305 | fs->localvar[fs->nlocalvar+n] = name; | ||
306 | else | ||
307 | luaX_error(ls, "too many local variables " MES_LIM(SMAXLOCALS)); | ||
308 | luaI_registerlocalvar(fs, name, ls->linenumber); | ||
309 | } | ||
310 | |||
311 | |||
312 | static void add_localvar (LexState *ls, TaggedString *name) { | ||
313 | store_localvar(ls, name, 0); | ||
314 | ls->fs->nlocalvar++; | ||
315 | } | ||
316 | |||
317 | |||
318 | static int aux_localname (FuncState *fs, TaggedString *n) { | ||
319 | int i; | ||
320 | for (i=fs->nlocalvar-1; i >= 0; i--) | ||
321 | if (n == fs->localvar[i]) return i; /* local var index */ | ||
322 | return -1; /* not found */ | ||
323 | } | ||
324 | |||
325 | |||
326 | static void singlevar (LexState *ls, TaggedString *n, vardesc *var, int prev) { | ||
327 | FuncState *fs = prev ? ls->fs->prev : ls->fs; | ||
328 | int i = aux_localname(fs, n); | ||
329 | if (i >= 0) { /* local value */ | ||
330 | var->k = VLOCAL; | ||
331 | var->info = i; | ||
332 | } | ||
333 | else { /* check shadowing */ | ||
334 | FuncState *level = fs; | ||
335 | while ((level = level->prev) != NULL) | ||
336 | if (aux_localname(level, n) >= 0) | ||
337 | luaX_syntaxerror(ls, "cannot access a variable in outer scope", n->str); | ||
338 | var->k = VGLOBAL; | ||
339 | var->info = string_constant(fs, n); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | |||
344 | static int indexupvalue (LexState *ls, TaggedString *n) { | ||
345 | FuncState *fs = ls->fs; | ||
346 | vardesc v; | ||
347 | int i; | ||
348 | singlevar(ls, n, &v, 1); | ||
349 | for (i=0; i<fs->nupvalues; i++) { | ||
350 | if (fs->upvalues[i].k == v.k && fs->upvalues[i].info == v.info) | ||
351 | return i; | ||
352 | } | ||
353 | /* new one */ | ||
354 | if (++(fs->nupvalues) > MAXUPVALUES) | ||
355 | luaX_error(ls, "too many upvalues in a single function " | ||
356 | MES_LIM(SMAXUPVALUES)); | ||
357 | fs->upvalues[i] = v; /* i = fs->nupvalues - 1 */ | ||
358 | return i; | ||
359 | } | ||
360 | |||
361 | |||
362 | static void pushupvalue (LexState *ls, TaggedString *n) { | ||
363 | int i; | ||
364 | if (ls->fs->prev == NULL) | ||
365 | luaX_syntaxerror(ls, "cannot access upvalue in main", n->str); | ||
366 | if (aux_localname(ls->fs, n) >= 0) | ||
367 | luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str); | ||
368 | i = indexupvalue(ls, n); | ||
369 | code_oparg(ls, PUSHUPVALUE, 2, i, 1); | ||
370 | } | ||
371 | |||
372 | |||
373 | |||
374 | static void check_debugline (LexState *ls) { | ||
375 | if (lua_debug && ls->linenumber != ls->fs->lastsetline) { | ||
376 | code_oparg(ls, SETLINE, 0, ls->linenumber, 0); | ||
377 | ls->fs->lastsetline = ls->linenumber; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | |||
382 | static void adjuststack (LexState *ls, int n) { | ||
383 | if (n > 0) | ||
384 | code_oparg(ls, POP, 2, n-1, -n); | ||
385 | else if (n < 0) | ||
386 | code_oparg(ls, PUSHNIL, 1, (-n)-1, -n); | ||
387 | } | ||
388 | |||
389 | |||
390 | static void close_exp (LexState *ls, int pc, int nresults) { | ||
391 | if (pc > 0) { /* expression is an open function call */ | ||
392 | Byte *code = ls->fs->f->code; | ||
393 | int nparams = code[pc]; /* save nparams */ | ||
394 | pc += fix_opcode(ls, pc-2, CALLFUNC, 2, nresults); | ||
395 | code[pc] = nparams; /* restore nparams */ | ||
396 | if (nresults != MULT_RET) | ||
397 | deltastack(ls, nresults); /* "push" results */ | ||
398 | deltastack(ls, -(nparams+1)); /* "pop" params and function */ | ||
399 | } | ||
400 | } | ||
401 | |||
402 | |||
403 | static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) { | ||
404 | int diff = d->n - nvars; | ||
405 | if (d->pc == 0) { /* list is closed */ | ||
406 | /* push or pop eventual difference between list lengths */ | ||
407 | adjuststack(ls, diff); | ||
408 | } | ||
409 | else { /* must correct function call */ | ||
410 | diff--; /* do not count function call itself */ | ||
411 | if (diff < 0) { /* more variables than values */ | ||
412 | /* function call must provide extra values */ | ||
413 | close_exp(ls, d->pc, -diff); | ||
414 | } | ||
415 | else { /* more values than variables */ | ||
416 | close_exp(ls, d->pc, 0); /* call should provide no value */ | ||
417 | adjuststack(ls, diff); /* pop eventual extra values */ | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | |||
422 | |||
423 | static void code_args (LexState *ls, int nparams, int dots) { | ||
424 | FuncState *fs = ls->fs; | ||
425 | fs->nlocalvar += nparams; /* "self" may already be there */ | ||
426 | nparams = fs->nlocalvar; | ||
427 | if (!dots) { | ||
428 | fs->f->code[1] = nparams; /* fill-in arg information */ | ||
429 | deltastack(ls, nparams); | ||
430 | } | ||
431 | else { | ||
432 | fs->f->code[1] = nparams+ZEROVARARG; | ||
433 | deltastack(ls, nparams+1); | ||
434 | add_localvar(ls, luaS_new("arg")); | ||
435 | } | ||
436 | } | ||
437 | |||
438 | |||
439 | static void lua_pushvar (LexState *ls, vardesc *var) { | ||
440 | switch (var->k) { | ||
441 | case VLOCAL: | ||
442 | code_oparg(ls, PUSHLOCAL, 8, var->info, 1); | ||
443 | break; | ||
444 | case VGLOBAL: | ||
445 | code_oparg(ls, GETGLOBAL, 8, var->info, 1); | ||
446 | break; | ||
447 | case VDOT: | ||
448 | code_oparg(ls, GETDOTTED, 8, var->info, 0); | ||
449 | break; | ||
450 | case VINDEXED: | ||
451 | code_opcode(ls, GETTABLE, -1); | ||
452 | break; | ||
453 | case VEXP: | ||
454 | close_exp(ls, var->info, 1); /* function must return 1 value */ | ||
455 | break; | ||
456 | } | ||
457 | var->k = VEXP; | ||
458 | var->info = 0; /* now this is a closed expression */ | ||
459 | } | ||
460 | |||
461 | |||
462 | static void storevar (LexState *ls, vardesc *var) { | ||
463 | switch (var->k) { | ||
464 | case VLOCAL: | ||
465 | code_oparg(ls, SETLOCAL, 8, var->info, -1); | ||
466 | break; | ||
467 | case VGLOBAL: | ||
468 | code_oparg(ls, SETGLOBAL, 8, var->info, -1); | ||
469 | break; | ||
470 | case VINDEXED: | ||
471 | code_opcode(ls, SETTABLE0, -3); | ||
472 | break; | ||
473 | default: | ||
474 | LUA_INTERNALERROR("invalid var kind to store"); | ||
475 | } | ||
476 | } | ||
477 | |||
478 | |||
479 | static int fix_jump (LexState *ls, int pc, OpCode op, int n) { | ||
480 | /* jump is relative to position following jump instruction */ | ||
481 | return fix_opcode(ls, pc, op, 0, n-(pc+JMPSIZE)); | ||
482 | } | ||
483 | |||
484 | |||
485 | static void fix_upjmp (LexState *ls, OpCode op, int pos) { | ||
486 | int delta = ls->fs->pc+JMPSIZE - pos; /* jump is relative */ | ||
487 | if (delta > 255) delta++; | ||
488 | code_oparg(ls, op, 0, delta, 0); | ||
489 | } | ||
490 | |||
491 | |||
492 | static void codeIf (LexState *ls, int thenAdd, int elseAdd) { | ||
493 | FuncState *fs = ls->fs; | ||
494 | int elseinit = elseAdd+JMPSIZE; | ||
495 | if (fs->pc == elseinit) { /* no else part */ | ||
496 | fs->pc -= JMPSIZE; | ||
497 | elseinit = fs->pc; | ||
498 | } | ||
499 | else | ||
500 | elseinit += fix_jump(ls, elseAdd, JMP, fs->pc); | ||
501 | fix_jump(ls, thenAdd, IFFJMP, elseinit); | ||
502 | } | ||
503 | |||
504 | |||
505 | static void func_onstack (LexState *ls, FuncState *func) { | ||
506 | FuncState *fs = ls->fs; | ||
507 | int i; | ||
508 | int c = next_constant(fs); | ||
509 | ttype(&fs->f->consts[c]) = LUA_T_PROTO; | ||
510 | fs->f->consts[c].value.tf = func->f; | ||
511 | if (func->nupvalues == 0) | ||
512 | code_constant(ls, c); | ||
513 | else { | ||
514 | for (i=0; i<func->nupvalues; i++) | ||
515 | lua_pushvar(ls, &func->upvalues[i]); | ||
516 | code_oparg(ls, CLOSURE, 0, c, -func->nupvalues+1); | ||
517 | code_byte(fs, func->nupvalues); | ||
518 | } | ||
519 | } | ||
520 | |||
521 | |||
522 | static void init_state (LexState *ls, FuncState *fs, TaggedString *filename) { | ||
523 | TProtoFunc *f = luaF_newproto(); | ||
524 | fs->prev = ls->fs; /* linked list of funcstates */ | ||
525 | ls->fs = fs; | ||
526 | fs->stacksize = 0; | ||
527 | fs->maxstacksize = 0; | ||
528 | fs->nlocalvar = 0; | ||
529 | fs->nupvalues = 0; | ||
530 | fs->lastsetline = 0; | ||
531 | fs->f = f; | ||
532 | f->fileName = filename; | ||
533 | fs->pc = 0; | ||
534 | fs->maxcode = 0; | ||
535 | f->code = NULL; | ||
536 | fs->maxconsts = 0; | ||
537 | if (lua_debug) | ||
538 | fs->nvars = fs->maxvars = 0; | ||
539 | else | ||
540 | fs->maxvars = -1; /* flag no debug information */ | ||
541 | code_byte(fs, 0); /* to be filled with stacksize */ | ||
542 | code_byte(fs, 0); /* to be filled with arg information */ | ||
543 | } | ||
544 | |||
545 | |||
546 | static void close_func (LexState *ls) { | ||
547 | FuncState *fs = ls->fs; | ||
548 | TProtoFunc *f = fs->f; | ||
549 | code_opcode(ls, ENDCODE, 0); | ||
550 | f->code[0] = fs->maxstacksize; | ||
551 | f->code = luaM_reallocvector(f->code, fs->pc, Byte); | ||
552 | f->consts = luaM_reallocvector(f->consts, f->nconsts, TObject); | ||
553 | if (fs->maxvars != -1) { /* debug information? */ | ||
554 | luaI_registerlocalvar(fs, NULL, -1); /* flag end of vector */ | ||
555 | f->locvars = luaM_reallocvector(f->locvars, fs->nvars, LocVar); | ||
556 | } | ||
557 | ls->fs = fs->prev; | ||
558 | } | ||
559 | |||
560 | |||
561 | |||
562 | static int expfollow [] = {ELSE, ELSEIF, THEN, IF, WHILE, REPEAT, DO, NAME, | ||
563 | LOCAL, FUNCTION, END, UNTIL, RETURN, ')', ']', '}', ';', EOS, ',', 0}; | ||
564 | |||
565 | static int is_in (int tok, int *toks) { | ||
566 | int *t = toks; | ||
567 | while (*t) { | ||
568 | if (*t == tok) | ||
569 | return t-toks; | ||
570 | t++; | ||
571 | } | ||
572 | return -1; | ||
573 | } | ||
574 | |||
575 | |||
576 | static void next (LexState *ls) { | ||
577 | ls->token = luaX_lex(ls); | ||
578 | } | ||
579 | |||
580 | |||
581 | static void error_expected (LexState *ls, int token) { | ||
582 | char buff[100], t[TOKEN_LEN]; | ||
583 | luaX_token2str(ls, token, t); | ||
584 | sprintf(buff, "`%s' expected", t); | ||
585 | luaX_error(ls, buff); | ||
586 | } | ||
587 | |||
588 | static void error_unmatched (LexState *ls, int what, int who, int where) { | ||
589 | if (where == ls->linenumber) | ||
590 | error_expected(ls, what); | ||
591 | else { | ||
592 | char buff[100]; | ||
593 | char t_what[TOKEN_LEN], t_who[TOKEN_LEN]; | ||
594 | luaX_token2str(ls, what, t_what); | ||
595 | luaX_token2str(ls, who, t_who); | ||
596 | sprintf(buff, "`%s' expected (to close `%s' at line %d)", | ||
597 | t_what, t_who, where); | ||
598 | luaX_error(ls, buff); | ||
599 | } | ||
600 | } | ||
601 | |||
602 | static void check (LexState *ls, int c) { | ||
603 | if (ls->token != c) | ||
604 | error_expected(ls, c); | ||
605 | next(ls); | ||
606 | } | ||
607 | |||
608 | static void check_match (LexState *ls, int what, int who, int where) { | ||
609 | if (ls->token != what) | ||
610 | error_unmatched(ls, what, who, where); | ||
611 | check_debugline(ls); /* to 'mark' the 'what' */ | ||
612 | next(ls); | ||
613 | } | ||
614 | |||
615 | static TaggedString *checkname (LexState *ls) { | ||
616 | TaggedString *ts; | ||
617 | if (ls->token != NAME) | ||
618 | luaX_error(ls, "`NAME' expected"); | ||
619 | ts = ls->seminfo.ts; | ||
620 | next(ls); | ||
621 | return ts; | ||
622 | } | ||
623 | |||
624 | |||
625 | static int optional (LexState *ls, int c) { | ||
626 | if (ls->token == c) { | ||
627 | next(ls); | ||
628 | return 1; | ||
629 | } | ||
630 | else return 0; | ||
631 | } | ||
632 | |||
633 | |||
634 | TProtoFunc *luaY_parser (ZIO *z) { | ||
635 | struct LexState lexstate; | ||
636 | struct FuncState funcstate; | ||
637 | luaX_setinput(&lexstate, z); | ||
638 | init_state(&lexstate, &funcstate, luaS_new(zname(z))); | ||
639 | next(&lexstate); /* read first token */ | ||
640 | chunk(&lexstate); | ||
641 | if (lexstate.token != EOS) | ||
642 | luaX_error(&lexstate, "<eof> expected"); | ||
643 | close_func(&lexstate); | ||
644 | return funcstate.f; | ||
645 | } | ||
646 | |||
647 | |||
648 | |||
649 | /*============================================================*/ | ||
650 | /* GRAMAR RULES */ | ||
651 | /*============================================================*/ | ||
652 | |||
653 | static void chunk (LexState *ls) { | ||
654 | /* chunk -> statlist ret */ | ||
655 | statlist(ls); | ||
656 | ret(ls); | ||
657 | } | ||
658 | |||
659 | static void statlist (LexState *ls) { | ||
660 | /* statlist -> { stat [;] } */ | ||
661 | while (stat(ls)) { | ||
662 | LUA_ASSERT(ls->fs->stacksize == ls->fs->nlocalvar, | ||
663 | "stack size != # local vars"); | ||
664 | optional(ls, ';'); | ||
665 | } | ||
666 | } | ||
667 | |||
668 | static int stat (LexState *ls) { | ||
669 | int line = ls->linenumber; /* may be needed for error messages */ | ||
670 | FuncState *fs = ls->fs; | ||
671 | switch (ls->token) { | ||
672 | case IF: { /* stat -> IF ifpart END */ | ||
673 | next(ls); | ||
674 | ifpart(ls); | ||
675 | check_match(ls, END, IF, line); | ||
676 | return 1; | ||
677 | } | ||
678 | |||
679 | case WHILE: { /* stat -> WHILE cond DO block END */ | ||
680 | TProtoFunc *f = fs->f; | ||
681 | int while_init = fs->pc; | ||
682 | int cond_end, cond_size; | ||
683 | next(ls); | ||
684 | cond_end = cond(ls); | ||
685 | check(ls, DO); | ||
686 | block(ls); | ||
687 | check_match(ls, END, WHILE, line); | ||
688 | cond_size = cond_end-while_init; | ||
689 | check_pc(fs, cond_size); | ||
690 | memcpy(f->code+fs->pc, f->code+while_init, cond_size); | ||
691 | luaO_memdown(f->code+while_init, f->code+cond_end, fs->pc-while_init); | ||
692 | while_init += JMPSIZE + fix_jump(ls, while_init, JMP, fs->pc-cond_size); | ||
693 | fix_upjmp(ls, IFTUPJMP, while_init); | ||
694 | return 1; | ||
695 | } | ||
696 | |||
697 | case DO: { /* stat -> DO block END */ | ||
698 | next(ls); | ||
699 | block(ls); | ||
700 | check_match(ls, END, DO, line); | ||
701 | return 1; | ||
702 | } | ||
703 | |||
704 | case REPEAT: { /* stat -> REPEAT block UNTIL exp1 */ | ||
705 | int repeat_init = fs->pc; | ||
706 | next(ls); | ||
707 | block(ls); | ||
708 | check_match(ls, UNTIL, REPEAT, line); | ||
709 | exp1(ls); | ||
710 | fix_upjmp(ls, IFFUPJMP, repeat_init); | ||
711 | deltastack(ls, -1); /* pops condition */ | ||
712 | return 1; | ||
713 | } | ||
714 | |||
715 | case FUNCTION: { /* stat -> FUNCTION funcname body */ | ||
716 | int needself; | ||
717 | vardesc v; | ||
718 | if (ls->fs->prev) /* inside other function? */ | ||
719 | return 0; | ||
720 | check_debugline(ls); | ||
721 | next(ls); | ||
722 | needself = funcname(ls, &v); | ||
723 | body(ls, needself, line); | ||
724 | storevar(ls, &v); | ||
725 | return 1; | ||
726 | } | ||
727 | |||
728 | case LOCAL: { /* stat -> LOCAL localnamelist decinit */ | ||
729 | listdesc d; | ||
730 | int nvars; | ||
731 | check_debugline(ls); | ||
732 | next(ls); | ||
733 | nvars = localnamelist(ls); | ||
734 | decinit(ls, &d); | ||
735 | ls->fs->nlocalvar += nvars; | ||
736 | adjust_mult_assign(ls, nvars, &d); | ||
737 | return 1; | ||
738 | } | ||
739 | |||
740 | case NAME: case '%': { /* stat -> func | ['%'] NAME assignment */ | ||
741 | vardesc v; | ||
742 | check_debugline(ls); | ||
743 | var_or_func(ls, &v); | ||
744 | if (v.k == VEXP) { /* stat -> func */ | ||
745 | if (v.info == 0) /* is just an upper value? */ | ||
746 | luaX_error(ls, "syntax error"); | ||
747 | close_exp(ls, v.info, 0); | ||
748 | } | ||
749 | else { | ||
750 | int left = assignment(ls, &v, 1); /* stat -> ['%'] NAME assignment */ | ||
751 | adjuststack(ls, left); /* remove eventual 'garbage' left on stack */ | ||
752 | } | ||
753 | return 1; | ||
754 | } | ||
755 | |||
756 | case RETURN: case ';': case ELSE: case ELSEIF: | ||
757 | case END: case UNTIL: case EOS: /* 'stat' follow */ | ||
758 | return 0; | ||
759 | |||
760 | default: | ||
761 | luaX_error(ls, "<statement> expected"); | ||
762 | return 0; /* to avoid warnings */ | ||
763 | } | ||
764 | } | ||
765 | |||
766 | static int SaveWord (LexState *ls) { | ||
767 | int res = ls->fs->pc; | ||
768 | check_pc(ls->fs, JMPSIZE); | ||
769 | ls->fs->pc += JMPSIZE; /* open space */ | ||
770 | return res; | ||
771 | } | ||
772 | |||
773 | static int SaveWordPop (LexState *ls) { | ||
774 | deltastack(ls, -1); /* pop condition */ | ||
775 | return SaveWord(ls); | ||
776 | } | ||
777 | |||
778 | static int cond (LexState *ls) { | ||
779 | /* cond -> exp1 */ | ||
780 | exp1(ls); | ||
781 | return SaveWordPop(ls); | ||
782 | } | ||
783 | |||
784 | static void block (LexState *ls) { | ||
785 | /* block -> chunk */ | ||
786 | FuncState *fs = ls->fs; | ||
787 | int nlocalvar = fs->nlocalvar; | ||
788 | chunk(ls); | ||
789 | adjuststack(ls, fs->nlocalvar - nlocalvar); | ||
790 | for (; fs->nlocalvar > nlocalvar; fs->nlocalvar--) | ||
791 | luaI_unregisterlocalvar(fs, ls->linenumber); | ||
792 | } | ||
793 | |||
794 | static int funcname (LexState *ls, vardesc *v) { | ||
795 | /* funcname -> NAME [':' NAME | '.' NAME] */ | ||
796 | int needself = 0; | ||
797 | singlevar(ls, checkname(ls), v, 0); | ||
798 | if (ls->token == ':' || ls->token == '.') { | ||
799 | needself = (ls->token == ':'); | ||
800 | next(ls); | ||
801 | lua_pushvar(ls, v); | ||
802 | code_string(ls, checkname(ls)); | ||
803 | v->k = VINDEXED; | ||
804 | } | ||
805 | return needself; | ||
806 | } | ||
807 | |||
808 | static void body (LexState *ls, int needself, int line) { | ||
809 | /* body -> '(' parlist ')' chunk END */ | ||
810 | FuncState newfs; | ||
811 | init_state(ls, &newfs, ls->fs->f->fileName); | ||
812 | newfs.f->lineDefined = line; | ||
813 | check(ls, '('); | ||
814 | if (needself) | ||
815 | add_localvar(ls, luaS_new("self")); | ||
816 | parlist(ls); | ||
817 | check(ls, ')'); | ||
818 | chunk(ls); | ||
819 | check_match(ls, END, FUNCTION, line); | ||
820 | close_func(ls); | ||
821 | func_onstack(ls, &newfs); | ||
822 | } | ||
823 | |||
824 | static void ifpart (LexState *ls) { | ||
825 | /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */ | ||
826 | int c = cond(ls); | ||
827 | int e; | ||
828 | check(ls, THEN); | ||
829 | block(ls); | ||
830 | e = SaveWord(ls); | ||
831 | switch (ls->token) { | ||
832 | case ELSE: | ||
833 | next(ls); | ||
834 | block(ls); | ||
835 | break; | ||
836 | |||
837 | case ELSEIF: | ||
838 | next(ls); | ||
839 | ifpart(ls); | ||
840 | break; | ||
841 | } | ||
842 | codeIf(ls, c, e); | ||
843 | } | ||
844 | |||
845 | static void ret (LexState *ls) { | ||
846 | /* ret -> [RETURN explist sc] */ | ||
847 | if (ls->token == RETURN) { | ||
848 | listdesc e; | ||
849 | check_debugline(ls); | ||
850 | next(ls); | ||
851 | explist(ls, &e); | ||
852 | close_exp(ls, e.pc, MULT_RET); | ||
853 | code_oparg(ls, RETCODE, 0, ls->fs->nlocalvar, 0); | ||
854 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ | ||
855 | optional(ls, ';'); | ||
856 | } | ||
857 | } | ||
858 | |||
859 | |||
860 | /* | ||
861 | ** For parsing expressions, we use a classic stack with priorities. | ||
862 | ** Each binary operator is represented by its index in "binop" + FIRSTBIN | ||
863 | ** (EQ=2, NE=3, ... '^'=13). The unary NOT is 0 and UNMINUS is 1. | ||
864 | */ | ||
865 | |||
866 | /* code of first binary operator */ | ||
867 | #define FIRSTBIN 2 | ||
868 | |||
869 | /* code for power operator (last operator) | ||
870 | ** '^' needs special treatment because it is right associative | ||
871 | */ | ||
872 | #define POW 13 | ||
873 | |||
874 | static int binop [] = {EQ, NE, '>', '<', LE, GE, CONC, | ||
875 | '+', '-', '*', '/', '^', 0}; | ||
876 | |||
877 | static int priority [POW+1] = {5, 5, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 6}; | ||
878 | |||
879 | static OpCode opcodes [POW+1] = {NOTOP, MINUSOP, EQOP, NEQOP, GTOP, LTOP, | ||
880 | LEOP, GEOP, CONCOP, ADDOP, SUBOP, MULTOP, DIVOP, POWOP}; | ||
881 | |||
882 | #define MAXOPS 20 | ||
883 | |||
884 | typedef struct { | ||
885 | int ops[MAXOPS]; | ||
886 | int top; | ||
887 | } stack_op; | ||
888 | |||
889 | |||
890 | static void exp1 (LexState *ls) { | ||
891 | vardesc v; | ||
892 | exp(ls, &v); | ||
893 | lua_pushvar(ls, &v); | ||
894 | if (is_in(ls->token, expfollow) < 0) | ||
895 | luaX_error(ls, "ill formed expression"); | ||
896 | } | ||
897 | |||
898 | |||
899 | static void exp (LexState *ls, vardesc *v) { | ||
900 | exp2(ls, v); | ||
901 | while (ls->token == AND || ls->token == OR) { | ||
902 | int is_and = (ls->token == AND); | ||
903 | int pc; | ||
904 | lua_pushvar(ls, v); | ||
905 | next(ls); | ||
906 | pc = SaveWordPop(ls); | ||
907 | exp2(ls, v); | ||
908 | lua_pushvar(ls, v); | ||
909 | fix_jump(ls, pc, (is_and?ONFJMP:ONTJMP), ls->fs->pc); | ||
910 | } | ||
911 | } | ||
912 | |||
913 | |||
914 | static void push (LexState *ls, stack_op *s, int op) { | ||
915 | if (s->top == MAXOPS) | ||
916 | luaX_error(ls, "expression too complex"); | ||
917 | s->ops[s->top++] = op; | ||
918 | } | ||
919 | |||
920 | |||
921 | static void prefix (LexState *ls, stack_op *s) { | ||
922 | while (ls->token == NOT || ls->token == '-') { | ||
923 | push(ls, s, ls->token==NOT?0:1); | ||
924 | next(ls); | ||
925 | } | ||
926 | } | ||
927 | |||
928 | static void pop_to (LexState *ls, stack_op *s, int prio) { | ||
929 | int op; | ||
930 | while (s->top > 0 && priority[(op=s->ops[s->top-1])] >= prio) { | ||
931 | code_opcode(ls, opcodes[op], op<FIRSTBIN?0:-1); | ||
932 | s->top--; | ||
933 | } | ||
934 | } | ||
935 | |||
936 | static void exp2 (LexState *ls, vardesc *v) { | ||
937 | stack_op s; | ||
938 | int op; | ||
939 | s.top = 0; | ||
940 | prefix(ls, &s); | ||
941 | simpleexp(ls, v); | ||
942 | while ((op = is_in(ls->token, binop)) >= 0) { | ||
943 | op += FIRSTBIN; | ||
944 | lua_pushvar(ls, v); | ||
945 | /* '^' is right associative, so must 'simulate' a higher priority */ | ||
946 | pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]); | ||
947 | push(ls, &s, op); | ||
948 | next(ls); | ||
949 | prefix(ls, &s); | ||
950 | simpleexp(ls, v); | ||
951 | lua_pushvar(ls, v); | ||
952 | } | ||
953 | if (s.top > 0) { | ||
954 | lua_pushvar(ls, v); | ||
955 | pop_to(ls, &s, 0); | ||
956 | } | ||
957 | } | ||
958 | |||
959 | |||
960 | static void simpleexp (LexState *ls, vardesc *v) { | ||
961 | check_debugline(ls); | ||
962 | switch (ls->token) { | ||
963 | case '(': /* simpleexp -> '(' exp ')' */ | ||
964 | next(ls); | ||
965 | exp(ls, v); | ||
966 | check(ls, ')'); | ||
967 | break; | ||
968 | |||
969 | case NUMBER: /* simpleexp -> NUMBER */ | ||
970 | code_number(ls, ls->seminfo.r); | ||
971 | next(ls); | ||
972 | v->k = VEXP; v->info = 0; | ||
973 | break; | ||
974 | |||
975 | case STRING: /* simpleexp -> STRING */ | ||
976 | code_string(ls, ls->seminfo.ts); | ||
977 | next(ls); | ||
978 | v->k = VEXP; v->info = 0; | ||
979 | break; | ||
980 | |||
981 | case NIL: /* simpleexp -> NIL */ | ||
982 | adjuststack(ls, -1); | ||
983 | next(ls); | ||
984 | v->k = VEXP; v->info = 0; | ||
985 | break; | ||
986 | |||
987 | case '{': /* simpleexp -> constructor */ | ||
988 | constructor(ls); | ||
989 | v->k = VEXP; v->info = 0; | ||
990 | break; | ||
991 | |||
992 | case FUNCTION: { /* simpleexp -> FUNCTION body */ | ||
993 | int line = ls->linenumber; | ||
994 | next(ls); | ||
995 | body(ls, 0, line); | ||
996 | v->k = VEXP; v->info = 0; | ||
997 | break; | ||
998 | } | ||
999 | |||
1000 | case NAME: case '%': | ||
1001 | var_or_func(ls, v); | ||
1002 | break; | ||
1003 | |||
1004 | default: | ||
1005 | luaX_error(ls, "<expression> expected"); | ||
1006 | break; | ||
1007 | } | ||
1008 | } | ||
1009 | |||
1010 | static void var_or_func (LexState *ls, vardesc *v) { | ||
1011 | /* var_or_func -> ['%'] NAME var_or_func_tail */ | ||
1012 | if (optional(ls, '%')) { /* upvalue? */ | ||
1013 | pushupvalue(ls, checkname(ls)); | ||
1014 | v->k = VEXP; | ||
1015 | v->info = 0; /* closed expression */ | ||
1016 | } | ||
1017 | else /* variable name */ | ||
1018 | singlevar(ls, checkname(ls), v, 0); | ||
1019 | var_or_func_tail(ls, v); | ||
1020 | } | ||
1021 | |||
1022 | static void var_or_func_tail (LexState *ls, vardesc *v) { | ||
1023 | for (;;) { | ||
1024 | switch (ls->token) { | ||
1025 | case '.': /* var_or_func_tail -> '.' NAME */ | ||
1026 | next(ls); | ||
1027 | lua_pushvar(ls, v); /* 'v' must be on stack */ | ||
1028 | v->k = VDOT; | ||
1029 | v->info = string_constant(ls->fs, checkname(ls)); | ||
1030 | break; | ||
1031 | |||
1032 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ | ||
1033 | next(ls); | ||
1034 | lua_pushvar(ls, v); /* 'v' must be on stack */ | ||
1035 | exp1(ls); | ||
1036 | check(ls, ']'); | ||
1037 | v->k = VINDEXED; | ||
1038 | break; | ||
1039 | |||
1040 | case ':': /* var_or_func_tail -> ':' NAME funcparams */ | ||
1041 | next(ls); | ||
1042 | lua_pushvar(ls, v); /* 'v' must be on stack */ | ||
1043 | code_oparg(ls, PUSHSELF, 8, string_constant(ls->fs, checkname(ls)), 1); | ||
1044 | v->k = VEXP; | ||
1045 | v->info = funcparams(ls, 1); | ||
1046 | break; | ||
1047 | |||
1048 | case '(': case STRING: case '{': /* var_or_func_tail -> funcparams */ | ||
1049 | lua_pushvar(ls, v); /* 'v' must be on stack */ | ||
1050 | v->k = VEXP; | ||
1051 | v->info = funcparams(ls, 0); | ||
1052 | break; | ||
1053 | |||
1054 | default: return; /* should be follow... */ | ||
1055 | } | ||
1056 | } | ||
1057 | } | ||
1058 | |||
1059 | static int funcparams (LexState *ls, int slf) { | ||
1060 | FuncState *fs = ls->fs; | ||
1061 | int nparams = 1; /* default value */ | ||
1062 | switch (ls->token) { | ||
1063 | case '(': { /* funcparams -> '(' explist ')' */ | ||
1064 | listdesc e; | ||
1065 | next(ls); | ||
1066 | explist(ls, &e); | ||
1067 | check(ls, ')'); | ||
1068 | close_exp(ls, e.pc, 1); | ||
1069 | nparams = e.n; | ||
1070 | break; | ||
1071 | } | ||
1072 | |||
1073 | case '{': /* funcparams -> constructor */ | ||
1074 | constructor(ls); | ||
1075 | break; | ||
1076 | |||
1077 | case STRING: /* funcparams -> STRING */ | ||
1078 | next(ls); | ||
1079 | break; | ||
1080 | |||
1081 | default: | ||
1082 | luaX_error(ls, "function arguments expected"); | ||
1083 | break; | ||
1084 | } | ||
1085 | code_byte(fs, 0); /* save space for opcode */ | ||
1086 | code_byte(fs, 0); /* and nresult */ | ||
1087 | code_byte(fs, nparams+slf); | ||
1088 | return fs->pc-1; | ||
1089 | } | ||
1090 | |||
1091 | static void explist (LexState *ls, listdesc *d) { | ||
1092 | switch (ls->token) { | ||
1093 | case ELSE: case ELSEIF: case END: case UNTIL: | ||
1094 | case EOS: case ';': case ')': | ||
1095 | d->pc = 0; | ||
1096 | d->n = 0; | ||
1097 | break; | ||
1098 | |||
1099 | default: | ||
1100 | explist1(ls, d); | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1104 | static void explist1 (LexState *ls, listdesc *d) { | ||
1105 | vardesc v; | ||
1106 | exp(ls, &v); | ||
1107 | d->n = 1; | ||
1108 | while (ls->token == ',') { | ||
1109 | d->n++; | ||
1110 | lua_pushvar(ls, &v); | ||
1111 | next(ls); | ||
1112 | exp(ls, &v); | ||
1113 | } | ||
1114 | if (v.k == VEXP) | ||
1115 | d->pc = v.info; | ||
1116 | else { | ||
1117 | lua_pushvar(ls, &v); | ||
1118 | d->pc = 0; | ||
1119 | } | ||
1120 | } | ||
1121 | |||
1122 | static void parlist (LexState *ls) { | ||
1123 | int nparams = 0; | ||
1124 | int dots = 0; | ||
1125 | switch (ls->token) { | ||
1126 | case DOTS: /* parlist -> DOTS */ | ||
1127 | next(ls); | ||
1128 | dots = 1; | ||
1129 | break; | ||
1130 | |||
1131 | case NAME: /* parlist, tailparlist -> NAME [',' tailparlist] */ | ||
1132 | init: | ||
1133 | store_localvar(ls, checkname(ls), nparams++); | ||
1134 | if (ls->token == ',') { | ||
1135 | next(ls); | ||
1136 | switch (ls->token) { | ||
1137 | case DOTS: /* tailparlist -> DOTS */ | ||
1138 | next(ls); | ||
1139 | dots = 1; | ||
1140 | break; | ||
1141 | |||
1142 | case NAME: /* tailparlist -> NAME [',' tailparlist] */ | ||
1143 | goto init; | ||
1144 | |||
1145 | default: luaX_error(ls, "NAME or `...' expected"); | ||
1146 | } | ||
1147 | } | ||
1148 | break; | ||
1149 | |||
1150 | case ')': break; /* parlist -> empty */ | ||
1151 | |||
1152 | default: luaX_error(ls, "NAME or `...' expected"); | ||
1153 | } | ||
1154 | code_args(ls, nparams, dots); | ||
1155 | } | ||
1156 | |||
1157 | static int localnamelist (LexState *ls) { | ||
1158 | /* localnamelist -> NAME {',' NAME} */ | ||
1159 | int i = 1; | ||
1160 | store_localvar(ls, checkname(ls), 0); | ||
1161 | while (ls->token == ',') { | ||
1162 | next(ls); | ||
1163 | store_localvar(ls, checkname(ls), i++); | ||
1164 | } | ||
1165 | return i; | ||
1166 | } | ||
1167 | |||
1168 | static void decinit (LexState *ls, listdesc *d) { | ||
1169 | /* decinit -> ['=' explist1] */ | ||
1170 | if (ls->token == '=') { | ||
1171 | next(ls); | ||
1172 | explist1(ls, d); | ||
1173 | } | ||
1174 | else { | ||
1175 | d->n = 0; | ||
1176 | d->pc = 0; | ||
1177 | } | ||
1178 | } | ||
1179 | |||
1180 | static int assignment (LexState *ls, vardesc *v, int nvars) { | ||
1181 | int left = 0; | ||
1182 | /* dotted variables <a.x> must be stored like regular indexed vars <a["x"]> */ | ||
1183 | if (v->k == VDOT) { | ||
1184 | code_constant(ls, v->info); | ||
1185 | v->k = VINDEXED; | ||
1186 | } | ||
1187 | if (ls->token == ',') { /* assignment -> ',' NAME assignment */ | ||
1188 | vardesc nv; | ||
1189 | next(ls); | ||
1190 | var_or_func(ls, &nv); | ||
1191 | if (nv.k == VEXP) | ||
1192 | luaX_error(ls, "syntax error"); | ||
1193 | left = assignment(ls, &nv, nvars+1); | ||
1194 | } | ||
1195 | else { /* assignment -> '=' explist1 */ | ||
1196 | listdesc d; | ||
1197 | check(ls, '='); | ||
1198 | explist1(ls, &d); | ||
1199 | adjust_mult_assign(ls, nvars, &d); | ||
1200 | } | ||
1201 | if (v->k != VINDEXED || left+(nvars-1) == 0) { | ||
1202 | /* global/local var or indexed var without values in between */ | ||
1203 | storevar(ls, v); | ||
1204 | } | ||
1205 | else { /* indexed var with values in between*/ | ||
1206 | code_oparg(ls, SETTABLE, 0, left+(nvars-1), -1); | ||
1207 | left += 2; /* table/index are not popped, because they aren't on top */ | ||
1208 | } | ||
1209 | return left; | ||
1210 | } | ||
1211 | |||
1212 | static void constructor (LexState *ls) { | ||
1213 | /* constructor -> '{' part [';' part] '}' */ | ||
1214 | int line = ls->linenumber; | ||
1215 | int pc = SaveWord(ls); | ||
1216 | int nelems; | ||
1217 | constdesc cd; | ||
1218 | deltastack(ls, 1); | ||
1219 | check(ls, '{'); | ||
1220 | part(ls, &cd); | ||
1221 | nelems = cd.n; | ||
1222 | if (ls->token == ';') { | ||
1223 | constdesc other_cd; | ||
1224 | next(ls); | ||
1225 | part(ls, &other_cd); | ||
1226 | if (cd.k == other_cd.k) /* repeated parts? */ | ||
1227 | luaX_error(ls, "invalid constructor syntax"); | ||
1228 | nelems += other_cd.n; | ||
1229 | } | ||
1230 | check_match(ls, '}', '{', line); | ||
1231 | fix_opcode(ls, pc, CREATEARRAY, 2, nelems); | ||
1232 | } | ||
1233 | |||
1234 | static void part (LexState *ls, constdesc *cd) { | ||
1235 | switch (ls->token) { | ||
1236 | case ';': case '}': /* part -> empty */ | ||
1237 | cd->n = 0; | ||
1238 | cd->k = ls->token; | ||
1239 | return; | ||
1240 | |||
1241 | case NAME: { | ||
1242 | vardesc v; | ||
1243 | exp(ls, &v); | ||
1244 | if (ls->token == '=') { | ||
1245 | switch (v.k) { | ||
1246 | case VGLOBAL: | ||
1247 | code_constant(ls, v.info); | ||
1248 | break; | ||
1249 | case VLOCAL: | ||
1250 | code_string(ls, ls->fs->localvar[v.info]); | ||
1251 | break; | ||
1252 | default: | ||
1253 | luaX_error(ls, "`=' unexpected"); | ||
1254 | } | ||
1255 | next(ls); | ||
1256 | exp1(ls); | ||
1257 | cd->n = recfields(ls); | ||
1258 | cd->k = 1; /* record */ | ||
1259 | } | ||
1260 | else { | ||
1261 | lua_pushvar(ls, &v); | ||
1262 | cd->n = listfields(ls); | ||
1263 | cd->k = 0; /* list */ | ||
1264 | } | ||
1265 | break; | ||
1266 | } | ||
1267 | |||
1268 | case '[': /* part -> recfield recfields */ | ||
1269 | recfield(ls); | ||
1270 | cd->n = recfields(ls); | ||
1271 | cd->k = 1; /* record */ | ||
1272 | break; | ||
1273 | |||
1274 | default: /* part -> exp1 listfields */ | ||
1275 | exp1(ls); | ||
1276 | cd->n = listfields(ls); | ||
1277 | cd->k = 0; /* list */ | ||
1278 | break; | ||
1279 | } | ||
1280 | } | ||
1281 | |||
1282 | static int recfields (LexState *ls) { | ||
1283 | /* recfields -> { ',' recfield } [','] */ | ||
1284 | int n = 1; /* one has been read before */ | ||
1285 | while (ls->token == ',') { | ||
1286 | next(ls); | ||
1287 | if (ls->token == ';' || ls->token == '}') | ||
1288 | break; | ||
1289 | recfield(ls); | ||
1290 | n++; | ||
1291 | if (n%RFIELDS_PER_FLUSH == 0) | ||
1292 | flush_record(ls, RFIELDS_PER_FLUSH); | ||
1293 | } | ||
1294 | flush_record(ls, n%RFIELDS_PER_FLUSH); | ||
1295 | return n; | ||
1296 | } | ||
1297 | |||
1298 | static int listfields (LexState *ls) { | ||
1299 | /* listfields -> { ',' exp1 } [','] */ | ||
1300 | int n = 1; /* one has been read before */ | ||
1301 | while (ls->token == ',') { | ||
1302 | next(ls); | ||
1303 | if (ls->token == ';' || ls->token == '}') | ||
1304 | break; | ||
1305 | exp1(ls); | ||
1306 | n++; | ||
1307 | if (n%LFIELDS_PER_FLUSH == 0) | ||
1308 | flush_list(ls, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); | ||
1309 | } | ||
1310 | flush_list(ls, n/LFIELDS_PER_FLUSH, n%LFIELDS_PER_FLUSH); | ||
1311 | return n; | ||
1312 | } | ||
1313 | |||
1314 | static void recfield (LexState *ls) { | ||
1315 | /* recfield -> (NAME | '['exp1']') = exp1 */ | ||
1316 | switch (ls->token) { | ||
1317 | case NAME: | ||
1318 | code_string(ls, checkname(ls)); | ||
1319 | break; | ||
1320 | |||
1321 | case '[': | ||
1322 | next(ls); | ||
1323 | exp1(ls); | ||
1324 | check(ls, ']'); | ||
1325 | break; | ||
1326 | |||
1327 | default: luaX_error(ls, "NAME or `[' expected"); | ||
1328 | } | ||
1329 | check(ls, '='); | ||
1330 | exp1(ls); | ||
1331 | } | ||
1332 | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 1.6 1997/12/17 20:48:58 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 1.7 1998/01/09 14:57:43 roberto Exp $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -57,8 +57,6 @@ typedef struct LState { | |||
57 | struct IM *IMtable; /* table for tag methods */ | 57 | struct IM *IMtable; /* table for tag methods */ |
58 | int IMtable_size; /* size of IMtable */ | 58 | int IMtable_size; /* size of IMtable */ |
59 | int last_tag; /* last used tag in IMtable */ | 59 | int last_tag; /* last used tag in IMtable */ |
60 | struct FuncState *mainState, *currState; /* point to local structs in yacc */ | ||
61 | struct LexState *lexstate; /* point to local struct in yacc */ | ||
62 | struct ref *refArray; /* locked objects */ | 60 | struct ref *refArray; /* locked objects */ |
63 | int refSize; /* size of refArray */ | 61 | int refSize; /* size of refArray */ |
64 | unsigned long GCthreshold; | 62 | unsigned long GCthreshold; |
diff --git a/lua.stx b/lua.stx deleted file mode 100644 index 41aff108..00000000 --- a/lua.stx +++ /dev/null | |||
@@ -1,940 +0,0 @@ | |||
1 | %{ | ||
2 | /* | ||
3 | ** $Id: lua.stx,v 1.36 1998/03/25 18:52:29 roberto Exp roberto $ | ||
4 | ** Syntax analizer and code generator | ||
5 | ** See Copyright Notice in lua.h | ||
6 | */ | ||
7 | |||
8 | |||
9 | #include <stdlib.h> | ||
10 | #include <string.h> | ||
11 | |||
12 | #include "lauxlib.h" | ||
13 | #include "ldo.h" | ||
14 | #include "lfunc.h" | ||
15 | #include "llex.h" | ||
16 | #include "lmem.h" | ||
17 | #include "lopcodes.h" | ||
18 | #include "lparser.h" | ||
19 | #include "lstate.h" | ||
20 | #include "lstring.h" | ||
21 | #include "lua.h" | ||
22 | #include "luadebug.h" | ||
23 | #include "lzio.h" | ||
24 | |||
25 | |||
26 | int luaY_parse (void); | ||
27 | |||
28 | |||
29 | #define MES_LIM(x) "(limit=" x ")" | ||
30 | |||
31 | |||
32 | /* size of a "normal" jump instruction: OpCode + 1 byte */ | ||
33 | #define JMPSIZE 2 | ||
34 | |||
35 | /* maximum number of local variables */ | ||
36 | #define MAXLOCALS 32 | ||
37 | #define SMAXLOCALS "32" | ||
38 | |||
39 | #define MINGLOBAL (MAXLOCALS+1) | ||
40 | |||
41 | /* maximum number of variables in a multiple assignment */ | ||
42 | #define MAXVAR 32 | ||
43 | #define SMAXVAR "32" | ||
44 | |||
45 | /* maximum number of nested functions */ | ||
46 | #define MAXSTATES 6 | ||
47 | #define SMAXSTATES "6" | ||
48 | |||
49 | /* maximum number of upvalues */ | ||
50 | #define MAXUPVALUES 16 | ||
51 | #define SMAXUPVALUES "16" | ||
52 | |||
53 | |||
54 | |||
55 | /* | ||
56 | ** Variable descriptor: | ||
57 | ** if 0<n<MINGLOBAL, represents local variable indexed by (n-1); | ||
58 | ** if MINGLOBAL<=n, represents global variable at position (n-MINGLOBAL); | ||
59 | ** if n<0, indexed variable with index (-n)-1 (table on top of stack); | ||
60 | ** if n==0, an indexed variable (table and index on top of stack) | ||
61 | ** Must be long to store negative Word values. | ||
62 | */ | ||
63 | typedef long vardesc; | ||
64 | |||
65 | #define isglobal(v) (MINGLOBAL<=(v)) | ||
66 | #define globalindex(v) ((v)-MINGLOBAL) | ||
67 | #define islocal(v) (0<(v) && (v)<MINGLOBAL) | ||
68 | #define localindex(v) ((v)-1) | ||
69 | #define isdot(v) (v<0) | ||
70 | #define dotindex(v) ((-(v))-1) | ||
71 | |||
72 | /* state needed to generate code for a given function */ | ||
73 | typedef struct FuncState { | ||
74 | TProtoFunc *f; /* current function header */ | ||
75 | int pc; /* next position to code */ | ||
76 | TaggedString *localvar[MAXLOCALS]; /* store local variable names */ | ||
77 | int stacksize; /* number of values on activation register */ | ||
78 | int maxstacksize; /* maximum number of values on activation register */ | ||
79 | int nlocalvar; /* number of active local variables */ | ||
80 | int nupvalues; /* number of upvalues */ | ||
81 | int nvars; /* number of entries in f->locvars */ | ||
82 | int maxcode; /* size of f->code */ | ||
83 | int maxvars; /* size of f->locvars (-1 if no debug information) */ | ||
84 | int maxconsts; /* size of f->consts */ | ||
85 | vardesc varbuffer[MAXVAR]; /* variables in an assignment list */ | ||
86 | vardesc upvalues[MAXUPVALUES]; /* upvalues */ | ||
87 | } FuncState; | ||
88 | |||
89 | |||
90 | |||
91 | #define YYPURE 1 | ||
92 | |||
93 | |||
94 | void luaY_syntaxerror (char *s, char *token) | ||
95 | { | ||
96 | if (token[0] == 0) | ||
97 | token = "<eof>"; | ||
98 | luaL_verror("%.100s;\n last token read: \"%.50s\" at line %d in file %.50s", | ||
99 | s, token, L->lexstate->linenumber, L->mainState->f->fileName->str); | ||
100 | } | ||
101 | |||
102 | |||
103 | void luaY_error (char *s) | ||
104 | { | ||
105 | luaY_syntaxerror(s, luaX_lasttoken()); | ||
106 | } | ||
107 | |||
108 | |||
109 | static void check_pc (int n) | ||
110 | { | ||
111 | FuncState *fs = L->currState; | ||
112 | if (fs->pc+n > fs->maxcode) | ||
113 | fs->maxcode = luaM_growvector(&fs->f->code, fs->maxcode, | ||
114 | Byte, codeEM, MAX_INT); | ||
115 | } | ||
116 | |||
117 | |||
118 | static void code_byte (Byte c) | ||
119 | { | ||
120 | check_pc(1); | ||
121 | L->currState->f->code[L->currState->pc++] = c; | ||
122 | } | ||
123 | |||
124 | |||
125 | static void deltastack (int delta) | ||
126 | { | ||
127 | FuncState *fs = L->currState; | ||
128 | fs->stacksize += delta; | ||
129 | if (fs->stacksize > fs->maxstacksize) { | ||
130 | if (fs->stacksize > 255) | ||
131 | luaY_error("function/expression too complex"); | ||
132 | fs->maxstacksize = fs->stacksize; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | |||
137 | static int code_oparg_at (int pc, OpCode op, int builtin, int arg, int delta) | ||
138 | { | ||
139 | Byte *code = L->currState->f->code; | ||
140 | deltastack(delta); | ||
141 | if (arg < builtin) { | ||
142 | code[pc] = op+1+arg; | ||
143 | return 1; | ||
144 | } | ||
145 | else if (arg <= 255) { | ||
146 | code[pc] = op; | ||
147 | code[pc+1] = arg; | ||
148 | return 2; | ||
149 | } | ||
150 | else if (arg <= MAX_WORD) { | ||
151 | code[pc] = op+1+builtin; | ||
152 | code[pc+1] = arg>>8; | ||
153 | code[pc+2] = arg&0xFF; | ||
154 | return 3; | ||
155 | } | ||
156 | else luaY_error("code too long " MES_LIM("64K")); | ||
157 | return 0; /* to avoid warnings */ | ||
158 | } | ||
159 | |||
160 | |||
161 | static int fix_opcode (int pc, OpCode op, int builtin, int arg) | ||
162 | { | ||
163 | FuncState *fs = L->currState; | ||
164 | if (arg < builtin) { /* close space */ | ||
165 | luaO_memdown(fs->f->code+pc+1, fs->f->code+pc+2, fs->pc-(pc+2)); | ||
166 | fs->pc--; | ||
167 | } | ||
168 | else if (arg > 255) { /* open space */ | ||
169 | check_pc(1); | ||
170 | luaO_memup(fs->f->code+pc+1, fs->f->code+pc, fs->pc-pc); | ||
171 | fs->pc++; | ||
172 | } | ||
173 | return code_oparg_at(pc, op, builtin, arg, 0) - 2; | ||
174 | } | ||
175 | |||
176 | |||
177 | static void code_oparg (OpCode op, int builtin, int arg, int delta) | ||
178 | { | ||
179 | check_pc(3); /* maximum code size */ | ||
180 | L->currState->pc += code_oparg_at(L->currState->pc, op, builtin, arg, delta); | ||
181 | } | ||
182 | |||
183 | |||
184 | static void code_opcode (OpCode op, int delta) | ||
185 | { | ||
186 | deltastack(delta); | ||
187 | code_byte(op); | ||
188 | } | ||
189 | |||
190 | |||
191 | static void code_pop (OpCode op) | ||
192 | { | ||
193 | code_opcode(op, -1); | ||
194 | } | ||
195 | |||
196 | /* binary operations get 2 arguments and leave one, so they pop one */ | ||
197 | #define code_binop(op) code_pop(op) | ||
198 | |||
199 | |||
200 | static void code_neutralop (OpCode op) | ||
201 | { | ||
202 | code_opcode(op, 0); | ||
203 | } | ||
204 | |||
205 | /* unary operations get 1 argument and leave one, so they are neutral */ | ||
206 | #define code_unop(op) code_neutralop(op) | ||
207 | |||
208 | |||
209 | static void code_constant (int c) | ||
210 | { | ||
211 | code_oparg(PUSHCONSTANT, 8, c, 1); | ||
212 | } | ||
213 | |||
214 | |||
215 | static int next_constant (FuncState *cs) | ||
216 | { | ||
217 | TProtoFunc *f = cs->f; | ||
218 | if (f->nconsts >= cs->maxconsts) { | ||
219 | cs->maxconsts = luaM_growvector(&f->consts, cs->maxconsts, TObject, | ||
220 | constantEM, MAX_WORD); | ||
221 | } | ||
222 | return f->nconsts++; | ||
223 | } | ||
224 | |||
225 | |||
226 | static int string_constant (TaggedString *s, FuncState *cs) | ||
227 | { | ||
228 | TProtoFunc *f = cs->f; | ||
229 | int c = s->constindex; | ||
230 | if (!(c < f->nconsts && | ||
231 | ttype(&f->consts[c]) == LUA_T_STRING && tsvalue(&f->consts[c]) == s)) { | ||
232 | c = next_constant(cs); | ||
233 | ttype(&f->consts[c]) = LUA_T_STRING; | ||
234 | tsvalue(&f->consts[c]) = s; | ||
235 | s->constindex = c; /* hint for next time */ | ||
236 | } | ||
237 | return c; | ||
238 | } | ||
239 | |||
240 | |||
241 | static void code_string (TaggedString *s) | ||
242 | { | ||
243 | code_constant(string_constant(s, L->currState)); | ||
244 | } | ||
245 | |||
246 | |||
247 | #define LIM 20 | ||
248 | static int real_constant (real r) | ||
249 | { | ||
250 | /* check whether 'r' has appeared within the last LIM entries */ | ||
251 | TObject *cnt = L->currState->f->consts; | ||
252 | int c = L->currState->f->nconsts; | ||
253 | int lim = c < LIM ? 0 : c-LIM; | ||
254 | while (--c >= lim) { | ||
255 | if (ttype(&cnt[c]) == LUA_T_NUMBER && nvalue(&cnt[c]) == r) | ||
256 | return c; | ||
257 | } | ||
258 | /* not found; create a luaM_new entry */ | ||
259 | c = next_constant(L->currState); | ||
260 | cnt = L->currState->f->consts; /* 'next_constant' may reallocate this vector */ | ||
261 | ttype(&cnt[c]) = LUA_T_NUMBER; | ||
262 | nvalue(&cnt[c]) = r; | ||
263 | return c; | ||
264 | } | ||
265 | |||
266 | |||
267 | static void code_number (real f) | ||
268 | { | ||
269 | int i; | ||
270 | if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(int)f) == f) | ||
271 | code_oparg(PUSHNUMBER, 3, i, 1); /* f has an (short) integer value */ | ||
272 | else | ||
273 | code_constant(real_constant(f)); | ||
274 | } | ||
275 | |||
276 | |||
277 | static void flush_record (int n) | ||
278 | { | ||
279 | if (n > 0) | ||
280 | code_oparg(SETMAP, 1, n-1, -2*n); | ||
281 | } | ||
282 | |||
283 | static void flush_list (int m, int n) | ||
284 | { | ||
285 | if (n == 0) return; | ||
286 | code_oparg(SETLIST, 1, m, -n); | ||
287 | code_byte(n); | ||
288 | } | ||
289 | |||
290 | |||
291 | static void luaI_registerlocalvar (TaggedString *varname, int line) | ||
292 | { | ||
293 | FuncState *fs = L->currState; | ||
294 | if (fs->maxvars != -1) { /* debug information? */ | ||
295 | if (fs->nvars >= fs->maxvars) | ||
296 | fs->maxvars = luaM_growvector(&fs->f->locvars, fs->maxvars, | ||
297 | LocVar, "", MAX_WORD); | ||
298 | fs->f->locvars[fs->nvars].varname = varname; | ||
299 | fs->f->locvars[fs->nvars].line = line; | ||
300 | fs->nvars++; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | |||
305 | static void luaI_unregisterlocalvar (int line) | ||
306 | { | ||
307 | luaI_registerlocalvar(NULL, line); | ||
308 | } | ||
309 | |||
310 | |||
311 | static void store_localvar (TaggedString *name, int n) | ||
312 | { | ||
313 | if (L->currState->nlocalvar+n < MAXLOCALS) | ||
314 | L->currState->localvar[L->currState->nlocalvar+n] = name; | ||
315 | else | ||
316 | luaY_error("too many local variables " MES_LIM(SMAXLOCALS)); | ||
317 | luaI_registerlocalvar(name, L->lexstate->linenumber); | ||
318 | } | ||
319 | |||
320 | static void add_localvar (TaggedString *name) | ||
321 | { | ||
322 | store_localvar(name, 0); | ||
323 | L->currState->nlocalvar++; | ||
324 | } | ||
325 | |||
326 | |||
327 | /* | ||
328 | ** dotted variables <a.x> must be stored like regular indexed vars <a["x"]> | ||
329 | */ | ||
330 | static vardesc var2store (vardesc var) | ||
331 | { | ||
332 | if (isdot(var)) { | ||
333 | code_constant(dotindex(var)); | ||
334 | var = 0; | ||
335 | } | ||
336 | return var; | ||
337 | } | ||
338 | |||
339 | |||
340 | static void add_varbuffer (vardesc var, int n) | ||
341 | { | ||
342 | if (n >= MAXVAR) | ||
343 | luaY_error("variable buffer overflow " MES_LIM(SMAXVAR)); | ||
344 | L->currState->varbuffer[n] = var2store(var); | ||
345 | } | ||
346 | |||
347 | |||
348 | static int aux_localname (TaggedString *n, FuncState *st) | ||
349 | { | ||
350 | int i; | ||
351 | for (i=st->nlocalvar-1; i >= 0; i--) | ||
352 | if (n == st->localvar[i]) return i; /* local var index */ | ||
353 | return -1; /* not found */ | ||
354 | } | ||
355 | |||
356 | |||
357 | static vardesc singlevar (TaggedString *n, FuncState *st) | ||
358 | { | ||
359 | int i = aux_localname(n, st); | ||
360 | if (i == -1) { /* check shadowing */ | ||
361 | int l; | ||
362 | for (l=1; l<=(st-L->mainState); l++) | ||
363 | if (aux_localname(n, st-l) >= 0) | ||
364 | luaY_syntaxerror("cannot access a variable in outer scope", n->str); | ||
365 | return string_constant(n, st)+MINGLOBAL; /* global value */ | ||
366 | } | ||
367 | else return i+1; /* local value */ | ||
368 | } | ||
369 | |||
370 | |||
371 | static int indexupvalue (TaggedString *n) | ||
372 | { | ||
373 | vardesc v = singlevar(n, L->currState-1); | ||
374 | int i; | ||
375 | for (i=0; i<L->currState->nupvalues; i++) { | ||
376 | if (L->currState->upvalues[i] == v) | ||
377 | return i; | ||
378 | } | ||
379 | /* new one */ | ||
380 | if (++(L->currState->nupvalues) > MAXUPVALUES) | ||
381 | luaY_error("too many upvalues in a single function " MES_LIM(SMAXUPVALUES)); | ||
382 | L->currState->upvalues[i] = v; /* i = L->currState->nupvalues - 1 */ | ||
383 | return i; | ||
384 | } | ||
385 | |||
386 | |||
387 | static void pushupvalue (TaggedString *n) | ||
388 | { | ||
389 | int i; | ||
390 | if (L->currState == L->mainState) | ||
391 | luaY_error("cannot access upvalue in main"); | ||
392 | if (aux_localname(n, L->currState) >= 0) | ||
393 | luaY_syntaxerror("cannot access an upvalue in current scope", n->str); | ||
394 | i = indexupvalue(n); | ||
395 | code_oparg(PUSHUPVALUE, 2, i, 1); | ||
396 | } | ||
397 | |||
398 | |||
399 | void luaY_codedebugline (int line) | ||
400 | { | ||
401 | if (lua_debug && line != L->lexstate->lastline) { | ||
402 | code_oparg(SETLINE, 0, line, 0); | ||
403 | L->lexstate->lastline = line; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | |||
408 | static void adjuststack (int n) | ||
409 | { | ||
410 | if (n > 0) | ||
411 | code_oparg(POP, 2, n-1, -n); | ||
412 | else if (n < 0) | ||
413 | code_oparg(PUSHNIL, 1, (-n)-1, -n); | ||
414 | } | ||
415 | |||
416 | |||
417 | static long adjust_functioncall (long exp, int nresults) | ||
418 | { | ||
419 | if (exp <= 0) | ||
420 | return -exp; /* exp is -list length */ | ||
421 | else { | ||
422 | int temp = L->currState->f->code[exp]; | ||
423 | int nparams = L->currState->f->code[exp-1]; | ||
424 | exp += fix_opcode(exp-2, CALLFUNC, 2, nresults); | ||
425 | L->currState->f->code[exp] = nparams; | ||
426 | if (nresults != MULT_RET) | ||
427 | deltastack(nresults); | ||
428 | deltastack(-(nparams+1)); | ||
429 | return temp+nresults; | ||
430 | } | ||
431 | } | ||
432 | |||
433 | |||
434 | static void adjust_mult_assign (int vars, long exps) | ||
435 | { | ||
436 | if (exps > 0) { /* must correct function call */ | ||
437 | int diff = L->currState->f->code[exps] - vars; | ||
438 | if (diff < 0) | ||
439 | adjust_functioncall(exps, -diff); | ||
440 | else { | ||
441 | adjust_functioncall(exps, 0); | ||
442 | adjuststack(diff); | ||
443 | } | ||
444 | } | ||
445 | else adjuststack((-exps)-vars); | ||
446 | } | ||
447 | |||
448 | |||
449 | static void code_args (int nparams, int dots) | ||
450 | { | ||
451 | L->currState->nlocalvar += nparams; /* "self" may already be there */ | ||
452 | nparams = L->currState->nlocalvar; | ||
453 | if (!dots) { | ||
454 | L->currState->f->code[1] = nparams; /* fill-in arg information */ | ||
455 | deltastack(nparams); | ||
456 | } | ||
457 | else { | ||
458 | L->currState->f->code[1] = nparams+ZEROVARARG; | ||
459 | deltastack(nparams+1); | ||
460 | add_localvar(luaS_new("arg")); | ||
461 | } | ||
462 | } | ||
463 | |||
464 | |||
465 | static void lua_pushvar (vardesc var) | ||
466 | { | ||
467 | if (isglobal(var)) | ||
468 | code_oparg(GETGLOBAL, 8, globalindex(var), 1); | ||
469 | else if (islocal(var)) | ||
470 | code_oparg(PUSHLOCAL, 8, localindex(var), 1); | ||
471 | else if (isdot(var)) | ||
472 | code_oparg(GETDOTTED, 8, dotindex(var), 0); | ||
473 | else | ||
474 | code_pop(GETTABLE); | ||
475 | } | ||
476 | |||
477 | |||
478 | static void storevar (vardesc var) | ||
479 | { | ||
480 | if (var == 0) /* indexed var */ | ||
481 | code_opcode(SETTABLE0, -3); | ||
482 | else if (isglobal(var)) | ||
483 | code_oparg(SETGLOBAL, 8, globalindex(var), -1); | ||
484 | else /* local var */ | ||
485 | code_oparg(SETLOCAL, 8, localindex(var), -1); | ||
486 | } | ||
487 | |||
488 | |||
489 | /* returns how many elements are left as 'garbage' on the stack */ | ||
490 | static int lua_codestore (int i, int left) | ||
491 | { | ||
492 | if (L->currState->varbuffer[i] != 0 || /* global or local var or */ | ||
493 | left+i == 0) { /* indexed var without values in between */ | ||
494 | storevar(L->currState->varbuffer[i]); | ||
495 | return left; | ||
496 | } | ||
497 | else { /* indexed var with values in between*/ | ||
498 | code_oparg(SETTABLE, 0, left+i, -1); | ||
499 | return left+2; /* table/index are not popped, since they are not on top */ | ||
500 | } | ||
501 | } | ||
502 | |||
503 | |||
504 | static int fix_jump (int pc, OpCode op, int n) | ||
505 | { | ||
506 | /* jump is relative to position following jump instruction */ | ||
507 | return fix_opcode(pc, op, 0, n-(pc+JMPSIZE)); | ||
508 | } | ||
509 | |||
510 | |||
511 | static void fix_upjmp (OpCode op, int pos) | ||
512 | { | ||
513 | int delta = L->currState->pc+JMPSIZE - pos; /* jump is relative */ | ||
514 | if (delta > 255) delta++; | ||
515 | code_oparg(op, 0, delta, 0); | ||
516 | } | ||
517 | |||
518 | |||
519 | static void codeIf (int thenAdd, int elseAdd) | ||
520 | { | ||
521 | int elseinit = elseAdd+JMPSIZE; | ||
522 | if (L->currState->pc == elseinit) { /* no else part */ | ||
523 | L->currState->pc -= JMPSIZE; | ||
524 | elseinit = L->currState->pc; | ||
525 | } | ||
526 | else | ||
527 | elseinit += fix_jump(elseAdd, JMP, L->currState->pc); | ||
528 | fix_jump(thenAdd, IFFJMP, elseinit); | ||
529 | } | ||
530 | |||
531 | |||
532 | static void code_shortcircuit (int pc, OpCode op) | ||
533 | { | ||
534 | fix_jump(pc, op, L->currState->pc); | ||
535 | } | ||
536 | |||
537 | |||
538 | static void codereturn (void) | ||
539 | { | ||
540 | code_oparg(RETCODE, 0, L->currState->nlocalvar, 0); | ||
541 | L->currState->stacksize = L->currState->nlocalvar; | ||
542 | } | ||
543 | |||
544 | |||
545 | static void func_onstack (TProtoFunc *f) | ||
546 | { | ||
547 | int i; | ||
548 | int nupvalues = (L->currState+1)->nupvalues; | ||
549 | int c = next_constant(L->currState); | ||
550 | ttype(&L->currState->f->consts[c]) = LUA_T_PROTO; | ||
551 | L->currState->f->consts[c].value.tf = (L->currState+1)->f; | ||
552 | if (nupvalues == 0) | ||
553 | code_constant(c); | ||
554 | else { | ||
555 | for (i=0; i<nupvalues; i++) | ||
556 | lua_pushvar((L->currState+1)->upvalues[i]); | ||
557 | code_oparg(CLOSURE, 0, c, -nupvalues+1); | ||
558 | code_byte(nupvalues); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | |||
563 | static void init_state (TaggedString *filename) | ||
564 | { | ||
565 | TProtoFunc *f = luaF_newproto(); | ||
566 | FuncState *fs = L->currState; | ||
567 | fs->stacksize = 0; | ||
568 | fs->maxstacksize = 0; | ||
569 | fs->nlocalvar = 0; | ||
570 | fs->nupvalues = 0; | ||
571 | fs->f = f; | ||
572 | f->fileName = filename; | ||
573 | fs->pc = 0; | ||
574 | fs->maxcode = 0; | ||
575 | f->code = NULL; | ||
576 | fs->maxconsts = 0; | ||
577 | if (lua_debug) { | ||
578 | fs->nvars = 0; | ||
579 | fs->maxvars = 0; | ||
580 | } | ||
581 | else | ||
582 | fs->maxvars = -1; /* flag no debug information */ | ||
583 | code_byte(0); /* to be filled with stacksize */ | ||
584 | code_byte(0); /* to be filled with arg information */ | ||
585 | L->lexstate->lastline = 0; /* invalidate it */ | ||
586 | } | ||
587 | |||
588 | |||
589 | static void init_func (void) | ||
590 | { | ||
591 | if (L->currState-L->mainState >= MAXSTATES-1) | ||
592 | luaY_error("too many nested functions " MES_LIM(SMAXSTATES)); | ||
593 | L->currState++; | ||
594 | init_state(L->mainState->f->fileName); | ||
595 | luaY_codedebugline(L->lexstate->linenumber); | ||
596 | L->currState->f->lineDefined = L->lexstate->linenumber; | ||
597 | } | ||
598 | |||
599 | static TProtoFunc *close_func (void) | ||
600 | { | ||
601 | TProtoFunc *f = L->currState->f; | ||
602 | code_neutralop(ENDCODE); | ||
603 | f->code[0] = L->currState->maxstacksize; | ||
604 | f->code = luaM_reallocvector(f->code, L->currState->pc, Byte); | ||
605 | f->consts = luaM_reallocvector(f->consts, f->nconsts, TObject); | ||
606 | if (L->currState->maxvars != -1) { /* debug information? */ | ||
607 | luaI_registerlocalvar(NULL, -1); /* flag end of vector */ | ||
608 | f->locvars = luaM_reallocvector(f->locvars, L->currState->nvars, LocVar); | ||
609 | } | ||
610 | L->currState--; | ||
611 | return f; | ||
612 | } | ||
613 | |||
614 | |||
615 | /* | ||
616 | ** Parse Lua code. | ||
617 | */ | ||
618 | TProtoFunc *luaY_parser (ZIO *z) | ||
619 | { | ||
620 | struct LexState lexstate; | ||
621 | FuncState state[MAXSTATES]; | ||
622 | L->currState = L->mainState = &state[0]; | ||
623 | L->lexstate = &lexstate; | ||
624 | luaX_setinput(z); | ||
625 | init_state(luaS_new(zname(z))); | ||
626 | if (luaY_parse()) lua_error("parse error"); | ||
627 | return close_func(); | ||
628 | } | ||
629 | |||
630 | |||
631 | %} | ||
632 | |||
633 | |||
634 | %union | ||
635 | { | ||
636 | int vInt; | ||
637 | real vReal; | ||
638 | char *pChar; | ||
639 | long vLong; | ||
640 | TaggedString *pTStr; | ||
641 | TProtoFunc *pFunc; | ||
642 | } | ||
643 | |||
644 | %start chunk | ||
645 | |||
646 | %token NIL | ||
647 | %token IF THEN ELSE ELSEIF WHILE DO REPEAT UNTIL END | ||
648 | %token RETURN | ||
649 | %token LOCAL | ||
650 | %token FUNCTION | ||
651 | %token DOTS | ||
652 | %token <vReal> NUMBER | ||
653 | %token <pTStr> NAME STRING | ||
654 | |||
655 | %type <vInt> SaveWord, cond, GetPC, SaveWordPop, SaveWordPush | ||
656 | %type <vLong> exprlist, exprlist1 /* if > 0, points to function return | ||
657 | counter (which has list length); if <= 0, -list lenght */ | ||
658 | %type <vLong> functioncall, expr, sexp /* if != 0, points to function return | ||
659 | counter */ | ||
660 | %type <vInt> varlist1, funcParams, funcvalue | ||
661 | %type <vInt> fieldlist, localnamelist, decinit | ||
662 | %type <vInt> ffieldlist1, lfieldlist1, ffieldlist, lfieldlist, part | ||
663 | %type <vLong> var, varname, funcname /* vardesc */ | ||
664 | |||
665 | |||
666 | %left AND OR | ||
667 | %left EQ NE '>' '<' LE GE | ||
668 | %left CONC | ||
669 | %left '+' '-' | ||
670 | %left '*' '/' | ||
671 | %left UNARY NOT | ||
672 | %right '^' | ||
673 | |||
674 | |||
675 | %% /* beginning of rules section */ | ||
676 | |||
677 | |||
678 | chunk : statlist ret ; | ||
679 | |||
680 | statlist : /* empty */ | ||
681 | | statlist stat sc | ||
682 | { LUA_ASSERT(L->currState->stacksize == L->currState->nlocalvar, | ||
683 | "stack size != # local vars"); } | ||
684 | ; | ||
685 | |||
686 | sc : /* empty */ | ';' ; | ||
687 | |||
688 | stat : IF cond THEN block SaveWord elsepart END { codeIf($2, $5); } | ||
689 | |||
690 | | DO block END | ||
691 | |||
692 | | WHILE GetPC cond DO block END | ||
693 | {{ | ||
694 | FuncState *fs = L->currState; | ||
695 | int expsize = $3-$2; | ||
696 | int newpos = $2+JMPSIZE; | ||
697 | check_pc(expsize); | ||
698 | memcpy(fs->f->code+fs->pc, fs->f->code+$2, expsize); | ||
699 | luaO_memdown(fs->f->code+$2, fs->f->code+$3, fs->pc-$2); | ||
700 | newpos += fix_jump($2, JMP, fs->pc-expsize); | ||
701 | fix_upjmp(IFTUPJMP, newpos); | ||
702 | }} | ||
703 | |||
704 | | REPEAT GetPC block UNTIL expr1 | ||
705 | { | ||
706 | fix_upjmp(IFFUPJMP, $2); | ||
707 | deltastack(-1); /* pops condition */ | ||
708 | } | ||
709 | |||
710 | | varlist1 '=' exprlist1 | ||
711 | {{ | ||
712 | int i; | ||
713 | int left = 0; | ||
714 | adjust_mult_assign($1, $3); | ||
715 | for (i=$1-1; i>=0; i--) | ||
716 | left = lua_codestore(i, left); | ||
717 | adjuststack(left); /* remove eventual 'garbage' left on stack */ | ||
718 | }} | ||
719 | |||
720 | | functioncall { adjust_functioncall($1, 0); } | ||
721 | |||
722 | | LOCAL localnamelist decinit | ||
723 | { | ||
724 | L->currState->nlocalvar += $2; | ||
725 | adjust_mult_assign($2, $3); | ||
726 | } | ||
727 | |||
728 | | FUNCTION funcname body { storevar($2); } | ||
729 | ; | ||
730 | |||
731 | block : {$<vInt>$ = L->currState->nlocalvar;} chunk | ||
732 | { | ||
733 | adjuststack(L->currState->nlocalvar - $<vInt>1); | ||
734 | for (; L->currState->nlocalvar > $<vInt>1; L->currState->nlocalvar--) | ||
735 | luaI_unregisterlocalvar(L->lexstate->linenumber); | ||
736 | } | ||
737 | ; | ||
738 | |||
739 | funcname : varname { $$ = $1; init_func(); } | ||
740 | | fvarname '.' fname | ||
741 | { | ||
742 | $$ = 0; /* flag indexed variable */ | ||
743 | init_func(); | ||
744 | } | ||
745 | | fvarname ':' fname | ||
746 | { | ||
747 | $$ = 0; /* flag indexed variable */ | ||
748 | init_func(); | ||
749 | add_localvar(luaS_new("self")); | ||
750 | } | ||
751 | ; | ||
752 | |||
753 | fvarname : varname { lua_pushvar($1); } ; | ||
754 | |||
755 | fname : NAME { code_string($1); } ; | ||
756 | |||
757 | body : '(' parlist ')' chunk END { func_onstack(close_func()); } ; | ||
758 | |||
759 | elsepart : /* empty */ | ||
760 | | ELSE block | ||
761 | | ELSEIF cond THEN block SaveWord elsepart { codeIf($2, $5); } | ||
762 | ; | ||
763 | |||
764 | ret : /* empty */ | ||
765 | | RETURN exprlist sc | ||
766 | { | ||
767 | adjust_functioncall($2, MULT_RET); | ||
768 | codereturn(); | ||
769 | } | ||
770 | ; | ||
771 | |||
772 | GetPC : /* empty */ { $$ = L->currState->pc; } ; | ||
773 | |||
774 | SaveWord : /* empty */ | ||
775 | { $$ = L->currState->pc; | ||
776 | check_pc(JMPSIZE); | ||
777 | L->currState->pc += JMPSIZE; /* open space */ | ||
778 | } | ||
779 | ; | ||
780 | |||
781 | SaveWordPop : SaveWord { $$ = $1; deltastack(-1); /* pop condition */ } ; | ||
782 | |||
783 | SaveWordPush : SaveWord { $$ = $1; deltastack(1); /* push a value */ } ; | ||
784 | |||
785 | cond : expr1 SaveWordPop { $$ = $2; } ; | ||
786 | |||
787 | expr1 : expr { adjust_functioncall($1, 1); } ; | ||
788 | |||
789 | expr : '(' expr ')' { $$ = $2; } | ||
790 | | expr1 EQ expr1 { code_binop(EQOP); $$ = 0; } | ||
791 | | expr1 '<' expr1 { code_binop(LTOP); $$ = 0; } | ||
792 | | expr1 '>' expr1 { code_binop(GTOP); $$ = 0; } | ||
793 | | expr1 NE expr1 { code_binop(NEQOP); $$ = 0; } | ||
794 | | expr1 LE expr1 { code_binop(LEOP); $$ = 0; } | ||
795 | | expr1 GE expr1 { code_binop(GEOP); $$ = 0; } | ||
796 | | expr1 '+' expr1 { code_binop(ADDOP); $$ = 0; } | ||
797 | | expr1 '-' expr1 { code_binop(SUBOP); $$ = 0; } | ||
798 | | expr1 '*' expr1 { code_binop(MULTOP); $$ = 0; } | ||
799 | | expr1 '/' expr1 { code_binop(DIVOP); $$ = 0; } | ||
800 | | expr1 '^' expr1 { code_binop(POWOP); $$ = 0; } | ||
801 | | expr1 CONC expr1 { code_binop(CONCOP); $$ = 0; } | ||
802 | | '-' expr1 %prec UNARY { code_unop(MINUSOP); $$ = 0;} | ||
803 | | NOT expr1 { code_unop(NOTOP); $$ = 0;} | ||
804 | | sexp { $$ = $1; /* simple expressions */ } | ||
805 | | table { $$ = 0; } | ||
806 | | NUMBER { code_number($1); $$ = 0; } | ||
807 | | STRING { code_string($1); $$ = 0; } | ||
808 | | NIL { adjuststack(-1); $$ = 0; } | ||
809 | | FUNCTION { init_func(); } body { $$ = 0; } | ||
810 | | expr1 AND SaveWordPop expr1 { code_shortcircuit($3, ONFJMP); $$ = 0; } | ||
811 | | expr1 OR SaveWordPop expr1 { code_shortcircuit($3, ONTJMP); $$ = 0; } | ||
812 | ; | ||
813 | |||
814 | sexp1 : sexp { adjust_functioncall($1, 1); } ; | ||
815 | |||
816 | sexp : var { lua_pushvar($1); $$ = 0; } | ||
817 | | '%' NAME { pushupvalue($2); $$ = 0; } | ||
818 | | functioncall { $$ = $1; } | ||
819 | ; | ||
820 | |||
821 | var : varname { $$ = $1; } | ||
822 | | sexp1 '[' expr1 ']' { $$ = 0; } /* indexed variable */ | ||
823 | | sexp1 '.' NAME { $$ = (-string_constant($3, L->currState))-1; } | ||
824 | ; | ||
825 | |||
826 | varname : NAME { $$ = singlevar($1, L->currState); } ; | ||
827 | |||
828 | table : '{' SaveWordPush fieldlist '}' { fix_opcode($2, CREATEARRAY, 2, $3); } ; | ||
829 | |||
830 | functioncall : funcvalue funcParams | ||
831 | { | ||
832 | code_byte(0); /* save space for opcode */ | ||
833 | code_byte($1+$2); /* number of parameters */ | ||
834 | $$ = L->currState->pc; | ||
835 | code_byte(0); /* must be adjusted by other rules */ | ||
836 | } | ||
837 | ; | ||
838 | |||
839 | funcvalue : sexp1 { $$ = 0; } | ||
840 | | sexp1 ':' NAME | ||
841 | { | ||
842 | code_oparg(PUSHSELF, 8, string_constant($3, L->currState), 1); | ||
843 | $$ = 1; | ||
844 | } | ||
845 | ; | ||
846 | |||
847 | funcParams : '(' exprlist ')' { $$ = adjust_functioncall($2, 1); } | ||
848 | | table { $$ = 1; } | ||
849 | | STRING { code_string($1); $$ = 1; } | ||
850 | ; | ||
851 | |||
852 | exprlist : /* empty */ { $$ = 0; } | ||
853 | | exprlist1 { $$ = $1; } | ||
854 | ; | ||
855 | |||
856 | exprlist1 : expr { if ($1 != 0) $$ = $1; else $$ = -1; } | ||
857 | | exprlist1 ',' { $<vLong>$ = adjust_functioncall($1, 1); } expr | ||
858 | { | ||
859 | if ($4 == 0) $$ = -($<vLong>3 + 1); /* -length */ | ||
860 | else { | ||
861 | L->currState->f->code[$4] = $<vLong>3; /* store list length */ | ||
862 | $$ = $4; | ||
863 | } | ||
864 | } | ||
865 | ; | ||
866 | |||
867 | parlist : /* empty */ { code_args(0, 0); } | ||
868 | | DOTS { code_args(0, 1); } | ||
869 | | localnamelist { code_args($1, 0); } | ||
870 | | localnamelist ',' DOTS { code_args($1, 1); } | ||
871 | ; | ||
872 | |||
873 | fieldlist : part { $$ = abs($1); } | ||
874 | | part ';' part | ||
875 | { | ||
876 | if ($1*$3 > 0) /* repeated parts? */ | ||
877 | luaY_error("invalid constructor syntax"); | ||
878 | $$ = abs($1)+abs($3); | ||
879 | } | ||
880 | ; | ||
881 | |||
882 | part : /* empty */ { $$ = 0; } | ||
883 | | ffieldlist { $$ = $1; } | ||
884 | | lfieldlist { $$ = $1; } | ||
885 | ; | ||
886 | |||
887 | lastcomma : /* empty */ | ',' ; | ||
888 | |||
889 | ffieldlist : ffieldlist1 lastcomma | ||
890 | { | ||
891 | flush_record($1%RFIELDS_PER_FLUSH); | ||
892 | $$ = -$1; /* negative signals a "record" part */ | ||
893 | } | ||
894 | ; | ||
895 | |||
896 | lfieldlist : lfieldlist1 lastcomma | ||
897 | { | ||
898 | flush_list($1/LFIELDS_PER_FLUSH, $1%LFIELDS_PER_FLUSH); | ||
899 | $$ = $1; | ||
900 | } | ||
901 | ; | ||
902 | |||
903 | ffieldlist1 : ffield {$$=1;} | ||
904 | | ffieldlist1 ',' ffield | ||
905 | { | ||
906 | $$=$1+1; | ||
907 | if ($$%RFIELDS_PER_FLUSH == 0) | ||
908 | flush_record(RFIELDS_PER_FLUSH); | ||
909 | } | ||
910 | ; | ||
911 | |||
912 | ffield : ffieldkey '=' expr1 ; | ||
913 | |||
914 | ffieldkey : '[' expr1 ']' | ||
915 | | fname | ||
916 | ; | ||
917 | |||
918 | lfieldlist1 : expr1 {$$=1;} | ||
919 | | lfieldlist1 ',' expr1 | ||
920 | { | ||
921 | $$=$1+1; | ||
922 | if ($$%LFIELDS_PER_FLUSH == 0) | ||
923 | flush_list($$/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); | ||
924 | } | ||
925 | ; | ||
926 | |||
927 | varlist1 : var { $$ = 1; add_varbuffer($1, 0); } | ||
928 | | varlist1 ',' var { add_varbuffer($3, $1); $$ = $1+1; } | ||
929 | ; | ||
930 | |||
931 | localnamelist : NAME {store_localvar($1, 0); $$ = 1;} | ||
932 | | localnamelist ',' NAME { store_localvar($3, $1); $$ = $1+1; } | ||
933 | ; | ||
934 | |||
935 | decinit : /* empty */ { $$ = 0; } | ||
936 | | '=' exprlist1 { $$ = $2; } | ||
937 | ; | ||
938 | |||
939 | %% | ||
940 | |||
@@ -1,5 +1,5 @@ | |||
1 | # | 1 | # |
2 | ## $Id: makefile,v 1.10 1998/01/05 17:12:54 roberto Exp roberto $ | 2 | ## $Id: makefile,v 1.11 1998/05/18 22:26:03 roberto Exp roberto $ |
3 | ## Makefile | 3 | ## Makefile |
4 | ## See Copyright Notice in lua.h | 4 | ## See Copyright Notice in lua.h |
5 | # | 5 | # |
@@ -18,7 +18,7 @@ | |||
18 | # define LUA_COMPAT2_5 if yous system does need to be compatible with | 18 | # define LUA_COMPAT2_5 if yous system does need to be compatible with |
19 | # version 2.5 (or older) | 19 | # version 2.5 (or older) |
20 | # | 20 | # |
21 | #define LUA_NUM_TYPE if you need numbers to be different from double | 21 | # define LUA_NUM_TYPE if you need numbers to be different from double |
22 | 22 | ||
23 | CONFIG = -DPOPEN -D_POSIX_SOURCE | 23 | CONFIG = -DPOPEN -D_POSIX_SOURCE |
24 | #CONFIG = -DLUA_COMPAT2_5 -DOLD_ANSI -DDEBUG | 24 | #CONFIG = -DLUA_COMPAT2_5 -DOLD_ANSI -DDEBUG |
@@ -46,8 +46,8 @@ LUAOBJS = \ | |||
46 | llex.o \ | 46 | llex.o \ |
47 | lmem.o \ | 47 | lmem.o \ |
48 | lobject.o \ | 48 | lobject.o \ |
49 | lparser.o \ | ||
49 | lstate.o \ | 50 | lstate.o \ |
50 | lstx.o \ | ||
51 | lstring.o \ | 51 | lstring.o \ |
52 | ltable.o \ | 52 | ltable.o \ |
53 | ltm.o \ | 53 | ltm.o \ |
@@ -75,16 +75,11 @@ liblualib.a : $(LIBOBJS) | |||
75 | liblua.so.1.0 : lua.o | 75 | liblua.so.1.0 : lua.o |
76 | ld -o liblua.so.1.0 $(LUAOBJS) | 76 | ld -o liblua.so.1.0 $(LUAOBJS) |
77 | 77 | ||
78 | lstx.c lstx.h : lua.stx | ||
79 | bison -o lstx.c -p luaY_ -d lua.stx | ||
80 | # yacc -d lua.stx | ||
81 | # sed -e 's/yy/luaY_/g' -e 's/malloc\.h/stdlib\.h/g' y.tab.c > lstx.c | ||
82 | # sed -e 's/yy/luaY_/g' y.tab.h > lstx.h | ||
83 | 78 | ||
84 | clear : | 79 | clear : |
85 | rcsclean | 80 | rcsclean |
86 | rm -f *.o | 81 | rm -f *.o |
87 | rm -f lstx.c lstx.h | 82 | rm -f |
88 | co lua.h lualib.h luadebug.h | 83 | co lua.h lualib.h luadebug.h |
89 | 84 | ||
90 | 85 | ||
@@ -94,6 +89,7 @@ clear : | |||
94 | %.c : RCS/%.c,v | 89 | %.c : RCS/%.c,v |
95 | co $@ | 90 | co $@ |
96 | 91 | ||
92 | |||
97 | lapi.o: lapi.c lapi.h lua.h lobject.h lauxlib.h ldo.h lstate.h lfunc.h \ | 93 | lapi.o: lapi.c lapi.h lua.h lobject.h lauxlib.h ldo.h lstate.h lfunc.h \ |
98 | lgc.h lmem.h lstring.h ltable.h ltm.h luadebug.h lvm.h | 94 | lgc.h lmem.h lstring.h ltable.h ltm.h luadebug.h lvm.h |
99 | lauxlib.o: lauxlib.c lauxlib.h lua.h luadebug.h | 95 | lauxlib.o: lauxlib.c lauxlib.h lua.h luadebug.h |
@@ -107,18 +103,18 @@ lgc.o: lgc.c ldo.h lobject.h lua.h lstate.h lfunc.h lgc.h lmem.h \ | |||
107 | lstring.h ltable.h ltm.h | 103 | lstring.h ltable.h ltm.h |
108 | liolib.o: liolib.c lauxlib.h lua.h luadebug.h lualib.h | 104 | liolib.o: liolib.c lauxlib.h lua.h luadebug.h lualib.h |
109 | llex.o: llex.c lauxlib.h lua.h llex.h lobject.h lzio.h lmem.h \ | 105 | llex.o: llex.c lauxlib.h lua.h llex.h lobject.h lzio.h lmem.h \ |
110 | lparser.h lstate.h lstring.h lstx.h luadebug.h | 106 | lparser.h lstate.h lstring.h luadebug.h |
111 | lmathlib.o: lmathlib.c lauxlib.h lua.h lualib.h | 107 | lmathlib.o: lmathlib.c lauxlib.h lua.h lualib.h |
112 | lmem.o: lmem.c lmem.h lstate.h lobject.h lua.h | 108 | lmem.o: lmem.c lmem.h lstate.h lobject.h lua.h |
113 | lobject.o: lobject.c lobject.h lua.h | 109 | lobject.o: lobject.c lobject.h lua.h |
110 | lparser.o: lparser.c lauxlib.h lua.h ldo.h lobject.h lstate.h lfunc.h \ | ||
111 | llex.h lzio.h lmem.h lopcodes.h lparser.h lstring.h luadebug.h | ||
114 | lstate.o: lstate.c lbuiltin.h ldo.h lobject.h lua.h lstate.h lfunc.h \ | 112 | lstate.o: lstate.c lbuiltin.h ldo.h lobject.h lua.h lstate.h lfunc.h \ |
115 | lgc.h llex.h lzio.h lmem.h lstring.h ltable.h ltm.h | 113 | lgc.h llex.h lzio.h lmem.h lstring.h ltable.h ltm.h |
116 | lstring.o: lstring.c lmem.h lobject.h lua.h lstate.h lstring.h | 114 | lstring.o: lstring.c lmem.h lobject.h lua.h lstate.h lstring.h |
117 | lstrlib.o: lstrlib.c lauxlib.h lua.h lualib.h | 115 | lstrlib.o: lstrlib.c lauxlib.h lua.h lualib.h |
118 | lstx.o: lstx.c lauxlib.h lua.h ldo.h lobject.h lstate.h lfunc.h llex.h \ | ||
119 | lzio.h lmem.h lopcodes.h lparser.h lstring.h luadebug.h | ||
120 | ltable.o: ltable.c lauxlib.h lua.h lmem.h lobject.h lstate.h ltable.h | 116 | ltable.o: ltable.c lauxlib.h lua.h lmem.h lobject.h lstate.h ltable.h |
121 | ltm.o: ltm.c lauxlib.h lua.h lmem.h lobject.h lstate.h ltm.h lapi.h | 117 | ltm.o: ltm.c lauxlib.h lua.h lmem.h lobject.h lstate.h ltm.h |
122 | lua.o: lua.c lua.h luadebug.h lualib.h | 118 | lua.o: lua.c lua.h luadebug.h lualib.h |
123 | lundump.o: lundump.c lauxlib.h lua.h lfunc.h lobject.h lmem.h \ | 119 | lundump.o: lundump.c lauxlib.h lua.h lfunc.h lobject.h lmem.h \ |
124 | lstring.h lundump.h lzio.h | 120 | lstring.h lundump.h lzio.h |