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 /lua.stx | |
parent | abc6eac404da8181ad945ac6950f61a65ba7dfa5 (diff) | |
download | lua-7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6.tar.gz lua-7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6.tar.bz2 lua-7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6.zip |
NEW LL(1) PARSER
Diffstat (limited to 'lua.stx')
-rw-r--r-- | lua.stx | 940 |
1 files changed, 0 insertions, 940 deletions
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 | |||