diff options
author | David Walter Seikel | 2014-04-21 20:59:39 +1000 |
---|---|---|
committer | David Walter Seikel | 2014-04-21 20:59:39 +1000 |
commit | 9621add2918cc4943e6693b74ae85d51dd264fcf (patch) | |
tree | fff1edf2c69d7a08a0e12885eecc9b96ed847a6a /LuaSL/testLua/yueliang-0.4.1/nat-5.1.3/lparser_mk2.lua | |
parent | LuaSL_test's window doesn't need to be so huge. (diff) | |
download | SledjHamr-9621add2918cc4943e6693b74ae85d51dd264fcf.zip SledjHamr-9621add2918cc4943e6693b74ae85d51dd264fcf.tar.gz SledjHamr-9621add2918cc4943e6693b74ae85d51dd264fcf.tar.bz2 SledjHamr-9621add2918cc4943e6693b74ae85d51dd264fcf.tar.xz |
We don't need the testlua directory any more.
Diffstat (limited to '')
-rw-r--r-- | LuaSL/testLua/yueliang-0.4.1/nat-5.1.3/lparser_mk2.lua | 1294 |
1 files changed, 0 insertions, 1294 deletions
diff --git a/LuaSL/testLua/yueliang-0.4.1/nat-5.1.3/lparser_mk2.lua b/LuaSL/testLua/yueliang-0.4.1/nat-5.1.3/lparser_mk2.lua deleted file mode 100644 index f94fb84..0000000 --- a/LuaSL/testLua/yueliang-0.4.1/nat-5.1.3/lparser_mk2.lua +++ /dev/null | |||
@@ -1,1294 +0,0 @@ | |||
1 | --[[-------------------------------------------------------------------- | ||
2 | |||
3 | lparser.lua | ||
4 | Lua 5.1 parser in Lua | ||
5 | This file is part of Yueliang. | ||
6 | |||
7 | Copyright (c) 2008 Kein-Hong Man <khman@users.sf.net> | ||
8 | The COPYRIGHT file describes the conditions | ||
9 | under which this software may be distributed. | ||
10 | |||
11 | See the ChangeLog for more information. | ||
12 | |||
13 | ----------------------------------------------------------------------]] | ||
14 | |||
15 | --[[-------------------------------------------------------------------- | ||
16 | -- Notes: | ||
17 | -- * this is a Lua 5.1.x parser skeleton, for the llex_mk2.lua lexer | ||
18 | -- * builds some data, performs logging for educational purposes | ||
19 | -- * target is to have relatively efficient and clear code | ||
20 | -- * NO parsing limitations, since it is only a parser skeleton. Some | ||
21 | -- limits set in the default sources (in luaconf.h) are: | ||
22 | -- LUAI_MAXVARS = 200 | ||
23 | -- LUAI_MAXUPVALUES = 60 | ||
24 | -- LUAI_MAXCCALLS = 200 | ||
25 | -- * NO support for 'arg' vararg functions (LUA_COMPAT_VARARG) | ||
26 | -- * init(llex) needs one parameter, a lexer module that implements: | ||
27 | -- llex.lex() - returns appropriate [token, semantic info] pairs | ||
28 | -- llex.ln - current line number | ||
29 | -- llex.errorline(s, [line]) - dies with error message | ||
30 | -- | ||
31 | -- Usage example: | ||
32 | -- local llex = require("llex_mk2") | ||
33 | -- local lparser = require("lparser_mk2") | ||
34 | -- llex.init(source_code, source_code_name) | ||
35 | -- lparser.init(llex) | ||
36 | -- local fs = lparser.parser() | ||
37 | -- | ||
38 | -- Development notes: | ||
39 | -- * see test_parser-5.1.lua for grammar elements based on lparser.c | ||
40 | -- * next() (renamed to nextt) and lookahead() has been moved from llex; | ||
41 | -- it's more convenient to keep tok, seminfo as local variables here | ||
42 | -- * syntaxerror() is from llex, easier to keep here since little token | ||
43 | -- translation needed in preparation of error message | ||
44 | -- * lparser has a few extra items to help parsing/syntax checking | ||
45 | -- (a) line number (error reporting), lookahead token storage | ||
46 | -- * (b) per-prototype states needs a storage list | ||
47 | -- * (c) 'break' needs a per-block flag in a stack | ||
48 | -- * (d) 'kind' (v.k) testing needed in expr_stat() and assignment() | ||
49 | -- for disambiguation, thus v.k manipulation is retained | ||
50 | -- * (e) one line # var (lastln) for ambiguous (split line) function | ||
51 | -- call checking | ||
52 | -- * (f) LUA_COMPAT_VARARG compatibility code completely removed | ||
53 | -- * (g) minimal variable management code to differentiate each type | ||
54 | -- * parsing starts from the end of this file in parser() | ||
55 | ----------------------------------------------------------------------]] | ||
56 | |||
57 | local base = _G | ||
58 | local string = require "string" | ||
59 | module "lparser" | ||
60 | local _G = base.getfenv() | ||
61 | |||
62 | --[[-------------------------------------------------------------------- | ||
63 | -- variable and data structure initialization | ||
64 | ----------------------------------------------------------------------]] | ||
65 | |||
66 | ---------------------------------------------------------------------- | ||
67 | -- initialization: main variables | ||
68 | ---------------------------------------------------------------------- | ||
69 | |||
70 | local llex, llex_lex -- references lexer module, function | ||
71 | local line -- start line # for error messages | ||
72 | local lastln -- last line # for ambiguous syntax chk | ||
73 | local tok, seminfo -- token, semantic info pair | ||
74 | local peek_tok, peek_sem -- ditto, for lookahead | ||
75 | local fs -- current function state | ||
76 | local top_fs -- top-level function state | ||
77 | |||
78 | -- forward references for local functions | ||
79 | local explist1, expr, block, exp1, body | ||
80 | |||
81 | ---------------------------------------------------------------------- | ||
82 | -- initialization: data structures | ||
83 | ---------------------------------------------------------------------- | ||
84 | |||
85 | local gmatch = string.gmatch | ||
86 | |||
87 | local block_follow = {} -- lookahead check in chunk(), returnstat() | ||
88 | for v in gmatch("else elseif end until <eof>", "%S+") do | ||
89 | block_follow[v] = true | ||
90 | end | ||
91 | |||
92 | local stat_call = {} -- lookup for calls in stat() | ||
93 | for v in gmatch("if while do for repeat function local return break", "%S+") do | ||
94 | stat_call[v] = v.."_stat" | ||
95 | end | ||
96 | |||
97 | local binopr_left = {} -- binary operators, left priority | ||
98 | local binopr_right = {} -- binary operators, right priority | ||
99 | for op, lt, rt in gmatch([[ | ||
100 | {+ 6 6}{- 6 6}{* 7 7}{/ 7 7}{% 7 7} | ||
101 | {^ 10 9}{.. 5 4} | ||
102 | {~= 3 3}{== 3 3} | ||
103 | {< 3 3}{<= 3 3}{> 3 3}{>= 3 3} | ||
104 | {and 2 2}{or 1 1} | ||
105 | ]], "{(%S+)%s(%d+)%s(%d+)}") do | ||
106 | binopr_left[op] = lt + 0 | ||
107 | binopr_right[op] = rt + 0 | ||
108 | end | ||
109 | |||
110 | local unopr = { ["not"] = true, ["-"] = true, | ||
111 | ["#"] = true, } -- unary operators | ||
112 | local UNARY_PRIORITY = 8 -- priority for unary operators | ||
113 | |||
114 | --[[-------------------------------------------------------------------- | ||
115 | -- logging: this logging function is for educational purposes | ||
116 | -- * logged data can be retrieved from the returned data structure | ||
117 | ----------------------------------------------------------------------]] | ||
118 | |||
119 | local function log(msg) | ||
120 | local log = top_fs.log | ||
121 | if not log then -- initialize message table | ||
122 | log = {}; top_fs.log = log | ||
123 | end | ||
124 | log[#log + 1] = msg | ||
125 | end | ||
126 | |||
127 | --[[-------------------------------------------------------------------- | ||
128 | -- support functions | ||
129 | ----------------------------------------------------------------------]] | ||
130 | |||
131 | ---------------------------------------------------------------------- | ||
132 | -- handles incoming token, semantic information pairs; these two | ||
133 | -- functions are from llex, they are put here because keeping the | ||
134 | -- tok, seminfo variables here as locals is more convenient | ||
135 | -- * NOTE: 'nextt' is named 'next' originally | ||
136 | ---------------------------------------------------------------------- | ||
137 | |||
138 | -- reads in next token | ||
139 | local function nextt() | ||
140 | lastln = llex.ln | ||
141 | if peek_tok then -- is there a look-ahead token? if yes, use it | ||
142 | tok, seminfo = peek_tok, peek_sem | ||
143 | peek_tok = nil | ||
144 | else | ||
145 | tok, seminfo = llex_lex() -- read next token | ||
146 | end | ||
147 | end | ||
148 | |||
149 | -- peek at next token (single lookahead for table constructor) | ||
150 | local function lookahead() | ||
151 | peek_tok, peek_sem = llex_lex() | ||
152 | return peek_tok | ||
153 | end | ||
154 | |||
155 | ---------------------------------------------------------------------- | ||
156 | -- throws a syntax error, or if token expected is not there | ||
157 | ---------------------------------------------------------------------- | ||
158 | |||
159 | local function syntaxerror(msg) | ||
160 | local tok = tok | ||
161 | if tok ~= "<number>" and tok ~= "<string>" then | ||
162 | if tok == "<name>" then tok = seminfo end | ||
163 | tok = "'"..tok.."'" | ||
164 | end | ||
165 | llex.errorline(msg.." near "..tok) | ||
166 | end | ||
167 | |||
168 | local function error_expected(token) | ||
169 | syntaxerror("'"..token.."' expected") | ||
170 | end | ||
171 | |||
172 | ---------------------------------------------------------------------- | ||
173 | -- tests for a token, returns outcome | ||
174 | -- * return value changed to boolean | ||
175 | ---------------------------------------------------------------------- | ||
176 | |||
177 | local function testnext(c) | ||
178 | if tok == c then nextt(); return true end | ||
179 | end | ||
180 | |||
181 | ---------------------------------------------------------------------- | ||
182 | -- check for existence of a token, throws error if not found | ||
183 | ---------------------------------------------------------------------- | ||
184 | |||
185 | local function check(c) | ||
186 | if tok ~= c then error_expected(c) end | ||
187 | end | ||
188 | |||
189 | ---------------------------------------------------------------------- | ||
190 | -- verify existence of a token, then skip it | ||
191 | ---------------------------------------------------------------------- | ||
192 | |||
193 | local function checknext(c) | ||
194 | check(c); nextt() | ||
195 | end | ||
196 | |||
197 | ---------------------------------------------------------------------- | ||
198 | -- throws error if condition not matched | ||
199 | ---------------------------------------------------------------------- | ||
200 | |||
201 | local function check_condition(c, msg) | ||
202 | if not c then syntaxerror(msg) end | ||
203 | end | ||
204 | |||
205 | ---------------------------------------------------------------------- | ||
206 | -- verifies token conditions are met or else throw error | ||
207 | ---------------------------------------------------------------------- | ||
208 | |||
209 | local function check_match(what, who, where) | ||
210 | if not testnext(what) then | ||
211 | if where == llex.ln then | ||
212 | error_expected(what) | ||
213 | else | ||
214 | syntaxerror("'"..what.."' expected (to close '"..who.."' at line "..where..")") | ||
215 | end | ||
216 | end | ||
217 | end | ||
218 | |||
219 | ---------------------------------------------------------------------- | ||
220 | -- expect that token is a name, return the name | ||
221 | ---------------------------------------------------------------------- | ||
222 | |||
223 | local function str_checkname() | ||
224 | check("<name>") | ||
225 | local ts = seminfo | ||
226 | nextt() | ||
227 | log(" str_checkname: '"..ts.."'") | ||
228 | return ts | ||
229 | end | ||
230 | |||
231 | ---------------------------------------------------------------------- | ||
232 | -- adds given string s in string pool, sets e as VK | ||
233 | ---------------------------------------------------------------------- | ||
234 | |||
235 | local function codestring(e, s) | ||
236 | e.k = "VK" | ||
237 | log(" codestring: "..string.format("%q", s)) | ||
238 | end | ||
239 | |||
240 | ---------------------------------------------------------------------- | ||
241 | -- consume a name token, adds it to string pool | ||
242 | ---------------------------------------------------------------------- | ||
243 | |||
244 | local function checkname(e) | ||
245 | log(" checkname:") | ||
246 | codestring(e, str_checkname()) | ||
247 | end | ||
248 | |||
249 | --[[-------------------------------------------------------------------- | ||
250 | -- state management functions with open/close pairs | ||
251 | ----------------------------------------------------------------------]] | ||
252 | |||
253 | ---------------------------------------------------------------------- | ||
254 | -- enters a code unit, initializes elements | ||
255 | ---------------------------------------------------------------------- | ||
256 | |||
257 | local function enterblock(isbreakable) | ||
258 | local bl = {} -- per-block state | ||
259 | bl.isbreakable = isbreakable | ||
260 | bl.prev = fs.bl | ||
261 | bl.locallist = {} | ||
262 | fs.bl = bl | ||
263 | log(">> enterblock(isbreakable="..base.tostring(isbreakable)..")") | ||
264 | end | ||
265 | |||
266 | ---------------------------------------------------------------------- | ||
267 | -- leaves a code unit, close any upvalues | ||
268 | ---------------------------------------------------------------------- | ||
269 | |||
270 | local function leaveblock() | ||
271 | local bl = fs.bl | ||
272 | fs.bl = bl.prev | ||
273 | log("<< leaveblock") | ||
274 | end | ||
275 | |||
276 | ---------------------------------------------------------------------- | ||
277 | -- opening of a function | ||
278 | -- * top_fs is only for anchoring the top fs, so that parser() can | ||
279 | -- return it to the caller function along with useful output | ||
280 | -- * used in parser() and body() | ||
281 | ---------------------------------------------------------------------- | ||
282 | |||
283 | local function open_func() | ||
284 | local new_fs -- per-function state | ||
285 | if not fs then -- top_fs is created early | ||
286 | new_fs = top_fs | ||
287 | else | ||
288 | new_fs = {} | ||
289 | end | ||
290 | new_fs.prev = fs -- linked list of function states | ||
291 | new_fs.bl = nil | ||
292 | new_fs.locallist = {} | ||
293 | fs = new_fs | ||
294 | log(">> open_func") | ||
295 | end | ||
296 | |||
297 | ---------------------------------------------------------------------- | ||
298 | -- closing of a function | ||
299 | -- * used in parser() and body() | ||
300 | ---------------------------------------------------------------------- | ||
301 | |||
302 | local function close_func() | ||
303 | fs = fs.prev | ||
304 | log("<< close_func") | ||
305 | end | ||
306 | |||
307 | --[[-------------------------------------------------------------------- | ||
308 | -- variable (global|local|upvalue) handling | ||
309 | -- * a pure parser does not really need this, but if we want to produce | ||
310 | -- useful output, might as well write minimal code to manage this... | ||
311 | -- * entry point is singlevar() for variable lookups | ||
312 | -- * three entry points for local variable creation, in order to keep | ||
313 | -- to original C calls, but the extra arguments such as positioning | ||
314 | -- are removed as we are not allocating registers -- we are only | ||
315 | -- doing simple classification | ||
316 | -- * lookup tables (bl.locallist) are maintained awkwardly in the basic | ||
317 | -- block data structures, PLUS the function data structure (this is | ||
318 | -- an inelegant hack, since bl is nil for the top level of a function) | ||
319 | ----------------------------------------------------------------------]] | ||
320 | |||
321 | ---------------------------------------------------------------------- | ||
322 | -- register a local variable, set in active variable list | ||
323 | -- * code for a simple lookup only | ||
324 | -- * used in new_localvarliteral(), parlist(), fornum(), forlist(), | ||
325 | -- localfunc(), localstat() | ||
326 | ---------------------------------------------------------------------- | ||
327 | |||
328 | local function new_localvar(name) | ||
329 | local bl = fs.bl | ||
330 | local locallist | ||
331 | if bl then | ||
332 | locallist = bl.locallist | ||
333 | else | ||
334 | locallist = fs.locallist | ||
335 | end | ||
336 | locallist[name] = true | ||
337 | log(" new_localvar: '"..name.."'") | ||
338 | end | ||
339 | |||
340 | ---------------------------------------------------------------------- | ||
341 | -- creates a new local variable given a name | ||
342 | -- * used in fornum(), forlist(), parlist(), body() | ||
343 | ---------------------------------------------------------------------- | ||
344 | |||
345 | local function new_localvarliteral(name) | ||
346 | new_localvar(name) | ||
347 | end | ||
348 | |||
349 | ---------------------------------------------------------------------- | ||
350 | -- search the local variable namespace of the given fs for a match | ||
351 | -- * a simple lookup only, no active variable list kept, so no useful | ||
352 | -- index value can be returned by this function | ||
353 | -- * used only in singlevaraux() | ||
354 | ---------------------------------------------------------------------- | ||
355 | |||
356 | local function searchvar(fs, n) | ||
357 | local bl = fs.bl | ||
358 | if bl then | ||
359 | locallist = bl.locallist | ||
360 | while locallist do | ||
361 | if locallist[n] then return 1 end -- found | ||
362 | bl = bl.prev | ||
363 | locallist = bl and bl.locallist | ||
364 | end | ||
365 | end | ||
366 | locallist = fs.locallist | ||
367 | if locallist[n] then return 1 end -- found | ||
368 | return -1 -- not found | ||
369 | end | ||
370 | |||
371 | ---------------------------------------------------------------------- | ||
372 | -- handle locals, globals and upvalues and related processing | ||
373 | -- * search mechanism is recursive, calls itself to search parents | ||
374 | -- * used only in singlevar() | ||
375 | ---------------------------------------------------------------------- | ||
376 | |||
377 | local function singlevaraux(fs, n, var, base) | ||
378 | if fs == nil then -- no more levels? | ||
379 | var.k = "VGLOBAL" -- default is global variable | ||
380 | return "VGLOBAL" | ||
381 | else | ||
382 | local v = searchvar(fs, n) -- look up at current level | ||
383 | if v >= 0 then | ||
384 | var.k = "VLOCAL" | ||
385 | -- codegen may need to deal with upvalue here | ||
386 | return "VLOCAL" | ||
387 | else -- not found at current level; try upper one | ||
388 | if singlevaraux(fs.prev, n, var, 0) == "VGLOBAL" then | ||
389 | return "VGLOBAL" | ||
390 | end | ||
391 | -- else was LOCAL or UPVAL, handle here | ||
392 | var.k = "VUPVAL" -- upvalue in this level | ||
393 | return "VUPVAL" | ||
394 | end--if v | ||
395 | end--if fs | ||
396 | end | ||
397 | |||
398 | ---------------------------------------------------------------------- | ||
399 | -- consume a name token, creates a variable (global|local|upvalue) | ||
400 | -- * used in prefixexp(), funcname() | ||
401 | ---------------------------------------------------------------------- | ||
402 | |||
403 | local function singlevar(v) | ||
404 | local varname = str_checkname() | ||
405 | singlevaraux(fs, varname, v, 1) | ||
406 | log(" singlevar(kind): '"..v.k.."'") | ||
407 | end | ||
408 | |||
409 | --[[-------------------------------------------------------------------- | ||
410 | -- other parsing functions | ||
411 | -- * for table constructor, parameter list, argument list | ||
412 | ----------------------------------------------------------------------]] | ||
413 | |||
414 | ---------------------------------------------------------------------- | ||
415 | -- parse a function name suffix, for function call specifications | ||
416 | -- * used in primaryexp(), funcname() | ||
417 | ---------------------------------------------------------------------- | ||
418 | |||
419 | local function field(v) | ||
420 | -- field -> ['.' | ':'] NAME | ||
421 | local key = {} | ||
422 | log(" field: operator="..tok) | ||
423 | nextt() -- skip the dot or colon | ||
424 | checkname(key) | ||
425 | v.k = "VINDEXED" | ||
426 | end | ||
427 | |||
428 | ---------------------------------------------------------------------- | ||
429 | -- parse a table indexing suffix, for constructors, expressions | ||
430 | -- * used in recfield(), primaryexp() | ||
431 | ---------------------------------------------------------------------- | ||
432 | |||
433 | local function yindex(v) | ||
434 | -- index -> '[' expr ']' | ||
435 | log(">> index: begin '['") | ||
436 | nextt() -- skip the '[' | ||
437 | expr(v) | ||
438 | checknext("]") | ||
439 | log("<< index: end ']'") | ||
440 | end | ||
441 | |||
442 | ---------------------------------------------------------------------- | ||
443 | -- parse a table record (hash) field | ||
444 | -- * used in constructor() | ||
445 | ---------------------------------------------------------------------- | ||
446 | |||
447 | local function recfield(cc) | ||
448 | -- recfield -> (NAME | '['exp1']') = exp1 | ||
449 | local key, val = {}, {} | ||
450 | if tok == "<name>" then | ||
451 | log("recfield: name") | ||
452 | checkname(key) | ||
453 | else-- tok == '[' | ||
454 | log("recfield: [ exp1 ]") | ||
455 | yindex(key) | ||
456 | end | ||
457 | checknext("=") | ||
458 | expr(val) | ||
459 | end | ||
460 | |||
461 | ---------------------------------------------------------------------- | ||
462 | -- emit a set list instruction if enough elements (LFIELDS_PER_FLUSH) | ||
463 | -- * note: retained in this skeleton because it modifies cc.v.k | ||
464 | -- * used in constructor() | ||
465 | ---------------------------------------------------------------------- | ||
466 | |||
467 | local function closelistfield(cc) | ||
468 | if cc.v.k == "VVOID" then return end -- there is no list item | ||
469 | cc.v.k = "VVOID" | ||
470 | end | ||
471 | |||
472 | ---------------------------------------------------------------------- | ||
473 | -- parse a table list (array) field | ||
474 | -- * used in constructor() | ||
475 | ---------------------------------------------------------------------- | ||
476 | |||
477 | local function listfield(cc) | ||
478 | log("listfield: expr") | ||
479 | expr(cc.v) | ||
480 | end | ||
481 | |||
482 | ---------------------------------------------------------------------- | ||
483 | -- parse a table constructor | ||
484 | -- * used in funcargs(), simpleexp() | ||
485 | ---------------------------------------------------------------------- | ||
486 | |||
487 | local function constructor(t) | ||
488 | -- constructor -> '{' [ field { fieldsep field } [ fieldsep ] ] '}' | ||
489 | -- field -> recfield | listfield | ||
490 | -- fieldsep -> ',' | ';' | ||
491 | log(">> constructor: begin") | ||
492 | local line = llex.ln | ||
493 | local cc = {} | ||
494 | cc.v = {} | ||
495 | cc.t = t | ||
496 | t.k = "VRELOCABLE" | ||
497 | cc.v.k = "VVOID" | ||
498 | checknext("{") | ||
499 | repeat | ||
500 | if tok == "}" then break end | ||
501 | -- closelistfield(cc) here | ||
502 | local c = tok | ||
503 | if c == "<name>" then -- may be listfields or recfields | ||
504 | if lookahead() ~= "=" then -- look ahead: expression? | ||
505 | listfield(cc) | ||
506 | else | ||
507 | recfield(cc) | ||
508 | end | ||
509 | elseif c == "[" then -- constructor_item -> recfield | ||
510 | recfield(cc) | ||
511 | else -- constructor_part -> listfield | ||
512 | listfield(cc) | ||
513 | end | ||
514 | until not testnext(",") and not testnext(";") | ||
515 | check_match("}", "{", line) | ||
516 | -- lastlistfield(cc) here | ||
517 | log("<< constructor: end") | ||
518 | end | ||
519 | |||
520 | ---------------------------------------------------------------------- | ||
521 | -- parse the arguments (parameters) of a function declaration | ||
522 | -- * used in body() | ||
523 | ---------------------------------------------------------------------- | ||
524 | |||
525 | local function parlist() | ||
526 | -- parlist -> [ param { ',' param } ] | ||
527 | log(">> parlist: begin") | ||
528 | if tok ~= ")" then -- is 'parlist' not empty? | ||
529 | repeat | ||
530 | local c = tok | ||
531 | if c == "<name>" then -- param -> NAME | ||
532 | new_localvar(str_checkname()) | ||
533 | elseif c == "..." then | ||
534 | log("parlist: ... (dots)") | ||
535 | nextt() | ||
536 | fs.is_vararg = true | ||
537 | else | ||
538 | syntaxerror("<name> or '...' expected") | ||
539 | end | ||
540 | until fs.is_vararg or not testnext(",") | ||
541 | end--if | ||
542 | log("<< parlist: end") | ||
543 | end | ||
544 | |||
545 | ---------------------------------------------------------------------- | ||
546 | -- parse the parameters of a function call | ||
547 | -- * contrast with parlist(), used in function declarations | ||
548 | -- * used in primaryexp() | ||
549 | ---------------------------------------------------------------------- | ||
550 | |||
551 | local function funcargs(f) | ||
552 | local args = {} | ||
553 | local line = llex.ln | ||
554 | local c = tok | ||
555 | if c == "(" then -- funcargs -> '(' [ explist1 ] ')' | ||
556 | log(">> funcargs: begin '('") | ||
557 | if line ~= lastln then | ||
558 | syntaxerror("ambiguous syntax (function call x new statement)") | ||
559 | end | ||
560 | nextt() | ||
561 | if tok == ")" then -- arg list is empty? | ||
562 | args.k = "VVOID" | ||
563 | else | ||
564 | explist1(args) | ||
565 | end | ||
566 | check_match(")", "(", line) | ||
567 | elseif c == "{" then -- funcargs -> constructor | ||
568 | log(">> funcargs: begin '{'") | ||
569 | constructor(args) | ||
570 | elseif c == "<string>" then -- funcargs -> STRING | ||
571 | log(">> funcargs: begin <string>") | ||
572 | codestring(args, seminfo) | ||
573 | nextt() -- must use 'seminfo' before 'next' | ||
574 | else | ||
575 | syntaxerror("function arguments expected") | ||
576 | return | ||
577 | end--if c | ||
578 | f.k = "VCALL" | ||
579 | log("<< funcargs: end -- expr is a VCALL") | ||
580 | end | ||
581 | |||
582 | --[[-------------------------------------------------------------------- | ||
583 | -- mostly expression functions | ||
584 | ----------------------------------------------------------------------]] | ||
585 | |||
586 | ---------------------------------------------------------------------- | ||
587 | -- parses an expression in parentheses or a single variable | ||
588 | -- * used in primaryexp() | ||
589 | ---------------------------------------------------------------------- | ||
590 | |||
591 | local function prefixexp(v) | ||
592 | -- prefixexp -> NAME | '(' expr ')' | ||
593 | local c = tok | ||
594 | if c == "(" then | ||
595 | log(">> prefixexp: begin ( expr ) ") | ||
596 | local line = llex.ln | ||
597 | nextt() | ||
598 | expr(v) | ||
599 | check_match(")", "(", line) | ||
600 | log("<< prefixexp: end ( expr ) ") | ||
601 | elseif c == "<name>" then | ||
602 | log("prefixexp: <name>") | ||
603 | singlevar(v) | ||
604 | else | ||
605 | syntaxerror("unexpected symbol") | ||
606 | end--if c | ||
607 | end | ||
608 | |||
609 | ---------------------------------------------------------------------- | ||
610 | -- parses a prefixexp (an expression in parentheses or a single | ||
611 | -- variable) or a function call specification | ||
612 | -- * used in simpleexp(), assignment(), expr_stat() | ||
613 | ---------------------------------------------------------------------- | ||
614 | |||
615 | local function primaryexp(v) | ||
616 | -- primaryexp -> | ||
617 | -- prefixexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } | ||
618 | prefixexp(v) | ||
619 | while true do | ||
620 | local c = tok | ||
621 | if c == "." then -- field | ||
622 | log("primaryexp: '.' field") | ||
623 | field(v) | ||
624 | elseif c == "[" then -- '[' exp1 ']' | ||
625 | log("primaryexp: [ exp1 ]") | ||
626 | local key = {} | ||
627 | yindex(key) | ||
628 | elseif c == ":" then -- ':' NAME funcargs | ||
629 | log("primaryexp: :<name> funcargs") | ||
630 | local key = {} | ||
631 | nextt() | ||
632 | checkname(key) | ||
633 | funcargs(v) | ||
634 | elseif c == "(" or c == "<string>" or c == "{" then -- funcargs | ||
635 | log("primaryexp: "..c.." funcargs") | ||
636 | funcargs(v) | ||
637 | else | ||
638 | return | ||
639 | end--if c | ||
640 | end--while | ||
641 | end | ||
642 | |||
643 | ---------------------------------------------------------------------- | ||
644 | -- parses general expression types, constants handled here | ||
645 | -- * used in subexpr() | ||
646 | ---------------------------------------------------------------------- | ||
647 | |||
648 | local function simpleexp(v) | ||
649 | -- simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | | ||
650 | -- constructor | FUNCTION body | primaryexp | ||
651 | local c = tok | ||
652 | if c == "<number>" then | ||
653 | log("simpleexp: <number>="..seminfo) | ||
654 | v.k = "VKNUM" | ||
655 | elseif c == "<string>" then | ||
656 | log("simpleexp: <string>="..seminfo) | ||
657 | codestring(v, seminfo) | ||
658 | elseif c == "nil" then | ||
659 | log("simpleexp: nil") | ||
660 | v.k = "VNIL" | ||
661 | elseif c == "true" then | ||
662 | log("simpleexp: true") | ||
663 | v.k = "VTRUE" | ||
664 | elseif c == "false" then | ||
665 | log("simpleexp: false") | ||
666 | v.k = "VFALSE" | ||
667 | elseif c == "..." then -- vararg | ||
668 | check_condition(fs.is_vararg == true, | ||
669 | "cannot use '...' outside a vararg function"); | ||
670 | log("simpleexp: ...") | ||
671 | v.k = "VVARARG" | ||
672 | elseif c == "{" then -- constructor | ||
673 | log("simpleexp: constructor") | ||
674 | constructor(v) | ||
675 | return | ||
676 | elseif c == "function" then | ||
677 | log("simpleexp: function") | ||
678 | nextt() | ||
679 | body(v, false, llex.ln) | ||
680 | return | ||
681 | else | ||
682 | primaryexp(v) | ||
683 | return | ||
684 | end--if c | ||
685 | nextt() | ||
686 | end | ||
687 | |||
688 | ------------------------------------------------------------------------ | ||
689 | -- Parse subexpressions. Includes handling of unary operators and binary | ||
690 | -- operators. A subexpr is given the rhs priority level of the operator | ||
691 | -- immediately left of it, if any (limit is -1 if none,) and if a binop | ||
692 | -- is found, limit is compared with the lhs priority level of the binop | ||
693 | -- in order to determine which executes first. | ||
694 | -- * recursively called | ||
695 | -- * used in expr() | ||
696 | ------------------------------------------------------------------------ | ||
697 | |||
698 | local function subexpr(v, limit) | ||
699 | -- subexpr -> (simpleexp | unop subexpr) { binop subexpr } | ||
700 | -- * where 'binop' is any binary operator with a priority | ||
701 | -- higher than 'limit' | ||
702 | local op = tok | ||
703 | local uop = unopr[op] | ||
704 | if uop then | ||
705 | log(" subexpr: uop='"..op.."'") | ||
706 | nextt() | ||
707 | subexpr(v, UNARY_PRIORITY) | ||
708 | else | ||
709 | simpleexp(v) | ||
710 | end | ||
711 | -- expand while operators have priorities higher than 'limit' | ||
712 | op = tok | ||
713 | local binop = binopr_left[op] | ||
714 | while binop and binop > limit do | ||
715 | local v2 = {} | ||
716 | log(">> subexpr: binop='"..op.."'") | ||
717 | nextt() | ||
718 | -- read sub-expression with higher priority | ||
719 | local nextop = subexpr(v2, binopr_right[op]) | ||
720 | log("<< subexpr: -- evaluate") | ||
721 | op = nextop | ||
722 | binop = binopr_left[op] | ||
723 | end | ||
724 | return op -- return first untreated operator | ||
725 | end | ||
726 | |||
727 | ---------------------------------------------------------------------- | ||
728 | -- Expression parsing starts here. Function subexpr is entered with the | ||
729 | -- left operator (which is non-existent) priority of -1, which is lower | ||
730 | -- than all actual operators. Expr information is returned in parm v. | ||
731 | -- * used in cond(), explist1(), index(), recfield(), listfield(), | ||
732 | -- prefixexp(), while_stat(), exp1() | ||
733 | ---------------------------------------------------------------------- | ||
734 | |||
735 | -- this is a forward-referenced local | ||
736 | function expr(v) | ||
737 | -- expr -> subexpr | ||
738 | log("expr:") | ||
739 | subexpr(v, 0) | ||
740 | end | ||
741 | |||
742 | --[[-------------------------------------------------------------------- | ||
743 | -- third level parsing functions | ||
744 | ----------------------------------------------------------------------]] | ||
745 | |||
746 | ------------------------------------------------------------------------ | ||
747 | -- parse a variable assignment sequence | ||
748 | -- * recursively called | ||
749 | -- * used in expr_stat() | ||
750 | ------------------------------------------------------------------------ | ||
751 | |||
752 | local function assignment(v) | ||
753 | local e = {} | ||
754 | local c = v.v.k | ||
755 | check_condition(c == "VLOCAL" or c == "VUPVAL" or c == "VGLOBAL" | ||
756 | or c == "VINDEXED", "syntax error") | ||
757 | if testnext(",") then -- assignment -> ',' primaryexp assignment | ||
758 | local nv = {} -- expdesc | ||
759 | nv.v = {} | ||
760 | log("assignment: ',' -- next LHS element") | ||
761 | primaryexp(nv.v) | ||
762 | -- lparser.c deals with some register usage conflict here | ||
763 | assignment(nv) | ||
764 | else -- assignment -> '=' explist1 | ||
765 | checknext("=") | ||
766 | log("assignment: '=' -- RHS elements follows") | ||
767 | explist1(e) | ||
768 | return -- avoid default | ||
769 | end | ||
770 | e.k = "VNONRELOC" | ||
771 | end | ||
772 | |||
773 | ---------------------------------------------------------------------- | ||
774 | -- parse a for loop body for both versions of the for loop | ||
775 | -- * used in fornum(), forlist() | ||
776 | ---------------------------------------------------------------------- | ||
777 | |||
778 | local function forbody(isnum) | ||
779 | -- forbody -> DO block | ||
780 | checknext("do") | ||
781 | enterblock(false) -- scope for declared variables | ||
782 | block() | ||
783 | leaveblock() -- end of scope for declared variables | ||
784 | end | ||
785 | |||
786 | ---------------------------------------------------------------------- | ||
787 | -- parse a numerical for loop, calls forbody() | ||
788 | -- * used in for_stat() | ||
789 | ---------------------------------------------------------------------- | ||
790 | |||
791 | local function fornum(varname) | ||
792 | -- fornum -> NAME = exp1, exp1 [, exp1] DO body | ||
793 | local line = line | ||
794 | new_localvarliteral("(for index)") | ||
795 | new_localvarliteral("(for limit)") | ||
796 | new_localvarliteral("(for step)") | ||
797 | new_localvar(varname) | ||
798 | log(">> fornum: begin") | ||
799 | checknext("=") | ||
800 | log("fornum: index start") | ||
801 | exp1() -- initial value | ||
802 | checknext(",") | ||
803 | log("fornum: index stop") | ||
804 | exp1() -- limit | ||
805 | if testnext(",") then | ||
806 | log("fornum: index step") | ||
807 | exp1() -- optional step | ||
808 | else | ||
809 | -- default step = 1 | ||
810 | end | ||
811 | log("fornum: body") | ||
812 | forbody(true) | ||
813 | log("<< fornum: end") | ||
814 | end | ||
815 | |||
816 | ---------------------------------------------------------------------- | ||
817 | -- parse a generic for loop, calls forbody() | ||
818 | -- * used in for_stat() | ||
819 | ---------------------------------------------------------------------- | ||
820 | |||
821 | local function forlist(indexname) | ||
822 | -- forlist -> NAME {, NAME} IN explist1 DO body | ||
823 | log(">> forlist: begin") | ||
824 | local e = {} | ||
825 | -- create control variables | ||
826 | new_localvarliteral("(for generator)") | ||
827 | new_localvarliteral("(for state)") | ||
828 | new_localvarliteral("(for control)") | ||
829 | -- create declared variables | ||
830 | new_localvar(indexname) | ||
831 | while testnext(",") do | ||
832 | new_localvar(str_checkname()) | ||
833 | end | ||
834 | checknext("in") | ||
835 | local line = line | ||
836 | log("forlist: explist1") | ||
837 | explist1(e) | ||
838 | log("forlist: body") | ||
839 | forbody(false) | ||
840 | log("<< forlist: end") | ||
841 | end | ||
842 | |||
843 | ---------------------------------------------------------------------- | ||
844 | -- parse a function name specification | ||
845 | -- * used in func_stat() | ||
846 | ---------------------------------------------------------------------- | ||
847 | |||
848 | local function funcname(v) | ||
849 | -- funcname -> NAME {field} [':' NAME] | ||
850 | log(">> funcname: begin") | ||
851 | local needself = false | ||
852 | singlevar(v) | ||
853 | while tok == "." do | ||
854 | log("funcname: -- '.' field") | ||
855 | field(v) | ||
856 | end | ||
857 | if tok == ":" then | ||
858 | log("funcname: -- ':' field") | ||
859 | needself = true | ||
860 | field(v) | ||
861 | end | ||
862 | log("<< funcname: end") | ||
863 | return needself | ||
864 | end | ||
865 | |||
866 | ---------------------------------------------------------------------- | ||
867 | -- parse the single expressions needed in numerical for loops | ||
868 | -- * used in fornum() | ||
869 | ---------------------------------------------------------------------- | ||
870 | |||
871 | -- this is a forward-referenced local | ||
872 | function exp1() | ||
873 | -- exp1 -> expr | ||
874 | local e = {} | ||
875 | log(">> exp1: begin") | ||
876 | expr(e) | ||
877 | log("<< exp1: end") | ||
878 | end | ||
879 | |||
880 | ---------------------------------------------------------------------- | ||
881 | -- parse condition in a repeat statement or an if control structure | ||
882 | -- * used in repeat_stat(), test_then_block() | ||
883 | ---------------------------------------------------------------------- | ||
884 | |||
885 | local function cond() | ||
886 | -- cond -> expr | ||
887 | log(">> cond: begin") | ||
888 | local v = {} | ||
889 | expr(v) -- read condition | ||
890 | log("<< cond: end") | ||
891 | end | ||
892 | |||
893 | ---------------------------------------------------------------------- | ||
894 | -- parse part of an if control structure, including the condition | ||
895 | -- * used in if_stat() | ||
896 | ---------------------------------------------------------------------- | ||
897 | |||
898 | local function test_then_block() | ||
899 | -- test_then_block -> [IF | ELSEIF] cond THEN block | ||
900 | nextt() -- skip IF or ELSEIF | ||
901 | log("test_then_block: test condition") | ||
902 | cond() | ||
903 | checknext("then") | ||
904 | log("test_then_block: then block") | ||
905 | block() -- 'then' part | ||
906 | end | ||
907 | |||
908 | ---------------------------------------------------------------------- | ||
909 | -- parse a local function statement | ||
910 | -- * used in local_stat() | ||
911 | ---------------------------------------------------------------------- | ||
912 | |||
913 | local function localfunc() | ||
914 | -- localfunc -> NAME body | ||
915 | local v, b = {} | ||
916 | log("localfunc: begin") | ||
917 | new_localvar(str_checkname()) | ||
918 | v.k = "VLOCAL" | ||
919 | log("localfunc: body") | ||
920 | body(b, false, llex.ln) | ||
921 | log("localfunc: end") | ||
922 | end | ||
923 | |||
924 | ---------------------------------------------------------------------- | ||
925 | -- parse a local variable declaration statement | ||
926 | -- * used in local_stat() | ||
927 | ---------------------------------------------------------------------- | ||
928 | |||
929 | local function localstat() | ||
930 | -- localstat -> NAME {',' NAME} ['=' explist1] | ||
931 | log(">> localstat: begin") | ||
932 | local e = {} | ||
933 | repeat | ||
934 | new_localvar(str_checkname()) | ||
935 | until not testnext(",") | ||
936 | if testnext("=") then | ||
937 | log("localstat: -- assignment") | ||
938 | explist1(e) | ||
939 | else | ||
940 | e.k = "VVOID" | ||
941 | end | ||
942 | log("<< localstat: end") | ||
943 | end | ||
944 | |||
945 | ---------------------------------------------------------------------- | ||
946 | -- parse a list of comma-separated expressions | ||
947 | -- * used in return_stat(), localstat(), funcargs(), assignment(), | ||
948 | -- forlist() | ||
949 | ---------------------------------------------------------------------- | ||
950 | |||
951 | -- this is a forward-referenced local | ||
952 | function explist1(e) | ||
953 | -- explist1 -> expr { ',' expr } | ||
954 | log(">> explist1: begin") | ||
955 | expr(e) | ||
956 | while testnext(",") do | ||
957 | log("explist1: ',' -- continuation") | ||
958 | expr(e) | ||
959 | end | ||
960 | log("<< explist1: end") | ||
961 | end | ||
962 | |||
963 | ---------------------------------------------------------------------- | ||
964 | -- parse function declaration body | ||
965 | -- * used in simpleexp(), localfunc(), func_stat() | ||
966 | ---------------------------------------------------------------------- | ||
967 | |||
968 | -- this is a forward-referenced local | ||
969 | function body(e, needself, line) | ||
970 | -- body -> '(' parlist ')' chunk END | ||
971 | open_func() | ||
972 | log("body: begin") | ||
973 | checknext("(") | ||
974 | if needself then | ||
975 | new_localvarliteral("self") | ||
976 | end | ||
977 | log("body: parlist") | ||
978 | parlist() | ||
979 | checknext(")") | ||
980 | log("body: chunk") | ||
981 | chunk() | ||
982 | check_match("end", "function", line) | ||
983 | log("body: end") | ||
984 | close_func() | ||
985 | end | ||
986 | |||
987 | ---------------------------------------------------------------------- | ||
988 | -- parse a code block or unit | ||
989 | -- * used in do_stat(), while_stat(), forbody(), test_then_block(), | ||
990 | -- if_stat() | ||
991 | ---------------------------------------------------------------------- | ||
992 | |||
993 | -- this is a forward-referenced local | ||
994 | function block() | ||
995 | -- block -> chunk | ||
996 | log("block: begin") | ||
997 | enterblock(false) | ||
998 | chunk() | ||
999 | leaveblock() | ||
1000 | log("block: end") | ||
1001 | end | ||
1002 | |||
1003 | --[[-------------------------------------------------------------------- | ||
1004 | -- second level parsing functions, all with '_stat' suffix | ||
1005 | -- * since they are called via a table lookup, they cannot be local | ||
1006 | -- functions (a lookup table of local functions might be smaller...) | ||
1007 | -- * stat() -> *_stat() | ||
1008 | ----------------------------------------------------------------------]] | ||
1009 | |||
1010 | ---------------------------------------------------------------------- | ||
1011 | -- initial parsing for a for loop, calls fornum() or forlist() | ||
1012 | -- * removed 'line' parameter (used to set debug information only) | ||
1013 | -- * used in stat() | ||
1014 | ---------------------------------------------------------------------- | ||
1015 | |||
1016 | function for_stat() | ||
1017 | -- stat -> for_stat -> FOR (fornum | forlist) END | ||
1018 | local line = line | ||
1019 | log("for_stat: begin") | ||
1020 | enterblock(true) -- scope for loop and control variables | ||
1021 | nextt() -- skip 'for' | ||
1022 | local varname = str_checkname() -- first variable name | ||
1023 | local c = tok | ||
1024 | if c == "=" then | ||
1025 | log("for_stat: numerical loop") | ||
1026 | fornum(varname) | ||
1027 | elseif c == "," or c == "in" then | ||
1028 | log("for_stat: list-based loop") | ||
1029 | forlist(varname) | ||
1030 | else | ||
1031 | syntaxerror("'=' or 'in' expected") | ||
1032 | end | ||
1033 | check_match("end", "for", line) | ||
1034 | leaveblock() -- loop scope (`break' jumps to this point) | ||
1035 | log("for_stat: end") | ||
1036 | end | ||
1037 | |||
1038 | ---------------------------------------------------------------------- | ||
1039 | -- parse a while-do control structure, body processed by block() | ||
1040 | -- * used in stat() | ||
1041 | ---------------------------------------------------------------------- | ||
1042 | |||
1043 | function while_stat() | ||
1044 | -- stat -> while_stat -> WHILE cond DO block END | ||
1045 | local line = line | ||
1046 | nextt() -- skip WHILE | ||
1047 | log("while_stat: begin/condition") | ||
1048 | cond() -- parse condition | ||
1049 | enterblock(true) | ||
1050 | checknext("do") | ||
1051 | log("while_stat: block") | ||
1052 | block() | ||
1053 | check_match("end", "while", line) | ||
1054 | leaveblock() | ||
1055 | log("while_stat: end") | ||
1056 | end | ||
1057 | |||
1058 | ---------------------------------------------------------------------- | ||
1059 | -- parse a repeat-until control structure, body parsed by chunk() | ||
1060 | -- * originally, repeatstat() calls breakstat() too if there is an | ||
1061 | -- upvalue in the scope block; nothing is actually lexed, it is | ||
1062 | -- actually the common code in breakstat() for closing of upvalues | ||
1063 | -- * used in stat() | ||
1064 | ---------------------------------------------------------------------- | ||
1065 | |||
1066 | function repeat_stat() | ||
1067 | -- stat -> repeat_stat -> REPEAT block UNTIL cond | ||
1068 | local line = line | ||
1069 | log("repeat_stat: begin") | ||
1070 | enterblock(true) -- loop block | ||
1071 | enterblock(false) -- scope block | ||
1072 | nextt() -- skip REPEAT | ||
1073 | chunk() | ||
1074 | check_match("until", "repeat", line) | ||
1075 | log("repeat_stat: condition") | ||
1076 | cond() | ||
1077 | -- close upvalues at scope level below | ||
1078 | leaveblock() -- finish scope | ||
1079 | leaveblock() -- finish loop | ||
1080 | log("repeat_stat: end") | ||
1081 | end | ||
1082 | |||
1083 | ---------------------------------------------------------------------- | ||
1084 | -- parse an if control structure | ||
1085 | -- * used in stat() | ||
1086 | ---------------------------------------------------------------------- | ||
1087 | |||
1088 | function if_stat() | ||
1089 | -- stat -> if_stat -> IF cond THEN block | ||
1090 | -- {ELSEIF cond THEN block} [ELSE block] END | ||
1091 | local line = line | ||
1092 | local v = {} | ||
1093 | log("if_stat: if...then") | ||
1094 | test_then_block() -- IF cond THEN block | ||
1095 | while tok == "elseif" do | ||
1096 | log("if_stat: elseif...then") | ||
1097 | test_then_block() -- ELSEIF cond THEN block | ||
1098 | end | ||
1099 | if tok == "else" then | ||
1100 | log("if_stat: else...") | ||
1101 | nextt() -- skip ELSE | ||
1102 | block() -- 'else' part | ||
1103 | end | ||
1104 | check_match("end", "if", line) | ||
1105 | log("if_stat: end") | ||
1106 | end | ||
1107 | |||
1108 | ---------------------------------------------------------------------- | ||
1109 | -- parse a return statement | ||
1110 | -- * used in stat() | ||
1111 | ---------------------------------------------------------------------- | ||
1112 | |||
1113 | function return_stat() | ||
1114 | -- stat -> return_stat -> RETURN explist | ||
1115 | local e = {} | ||
1116 | nextt() -- skip RETURN | ||
1117 | local c = tok | ||
1118 | if block_follow[c] or c == ";" then | ||
1119 | -- return no values | ||
1120 | log("return_stat: no return values") | ||
1121 | else | ||
1122 | log("return_stat: begin") | ||
1123 | explist1(e) -- optional return values | ||
1124 | log("return_stat: end") | ||
1125 | end | ||
1126 | end | ||
1127 | |||
1128 | ---------------------------------------------------------------------- | ||
1129 | -- parse a break statement | ||
1130 | -- * used in stat() | ||
1131 | ---------------------------------------------------------------------- | ||
1132 | |||
1133 | function break_stat() | ||
1134 | -- stat -> break_stat -> BREAK | ||
1135 | local bl = fs.bl | ||
1136 | nextt() -- skip BREAK | ||
1137 | while bl and not bl.isbreakable do -- find a breakable block | ||
1138 | bl = bl.prev | ||
1139 | end | ||
1140 | if not bl then | ||
1141 | syntaxerror("no loop to break") | ||
1142 | end | ||
1143 | log("break_stat: -- break out of loop") | ||
1144 | end | ||
1145 | |||
1146 | ---------------------------------------------------------------------- | ||
1147 | -- parse a function call with no returns or an assignment statement | ||
1148 | -- * the struct with .prev is used for name searching in lparse.c, | ||
1149 | -- so it is retained for now; present in assignment() also | ||
1150 | -- * used in stat() | ||
1151 | ---------------------------------------------------------------------- | ||
1152 | |||
1153 | function expr_stat() | ||
1154 | -- stat -> expr_stat -> func | assignment | ||
1155 | local v = {} | ||
1156 | v.v = {} | ||
1157 | primaryexp(v.v) | ||
1158 | if v.v.k == "VCALL" then -- stat -> func | ||
1159 | -- call statement uses no results | ||
1160 | log("expr_stat: function call k='"..v.v.k.."'") | ||
1161 | else -- stat -> assignment | ||
1162 | log("expr_stat: assignment k='"..v.v.k.."'") | ||
1163 | v.prev = nil | ||
1164 | assignment(v) | ||
1165 | end | ||
1166 | end | ||
1167 | |||
1168 | ---------------------------------------------------------------------- | ||
1169 | -- parse a function statement | ||
1170 | -- * used in stat() | ||
1171 | ---------------------------------------------------------------------- | ||
1172 | |||
1173 | function function_stat() | ||
1174 | -- stat -> function_stat -> FUNCTION funcname body | ||
1175 | local line = line | ||
1176 | local v, b = {}, {} | ||
1177 | log("function_stat: begin") | ||
1178 | nextt() -- skip FUNCTION | ||
1179 | local needself = funcname(v) | ||
1180 | log("function_stat: body needself='"..base.tostring(needself).."'") | ||
1181 | body(b, needself, line) | ||
1182 | log("function_stat: end") | ||
1183 | end | ||
1184 | |||
1185 | ---------------------------------------------------------------------- | ||
1186 | -- parse a simple block enclosed by a DO..END pair | ||
1187 | -- * used in stat() | ||
1188 | ---------------------------------------------------------------------- | ||
1189 | |||
1190 | function do_stat() | ||
1191 | -- stat -> do_stat -> DO block END | ||
1192 | local line = line | ||
1193 | nextt() -- skip DO | ||
1194 | log("do_stat: begin") | ||
1195 | block() | ||
1196 | log("do_stat: end") | ||
1197 | check_match("end", "do", line) | ||
1198 | end | ||
1199 | |||
1200 | ---------------------------------------------------------------------- | ||
1201 | -- parse a statement starting with LOCAL | ||
1202 | -- * used in stat() | ||
1203 | ---------------------------------------------------------------------- | ||
1204 | |||
1205 | function local_stat() | ||
1206 | -- stat -> local_stat -> LOCAL FUNCTION localfunc | ||
1207 | -- -> LOCAL localstat | ||
1208 | nextt() -- skip LOCAL | ||
1209 | if testnext("function") then -- local function? | ||
1210 | log("local_stat: local function") | ||
1211 | localfunc() | ||
1212 | else | ||
1213 | log("local_stat: local statement") | ||
1214 | localstat() | ||
1215 | end | ||
1216 | end | ||
1217 | |||
1218 | --[[-------------------------------------------------------------------- | ||
1219 | -- main functions, top level parsing functions | ||
1220 | -- * accessible functions are: init(lexer), parser() | ||
1221 | -- * [entry] -> parser() -> chunk() -> stat() | ||
1222 | ----------------------------------------------------------------------]] | ||
1223 | |||
1224 | ---------------------------------------------------------------------- | ||
1225 | -- initial parsing for statements, calls '_stat' suffixed functions | ||
1226 | -- * used in chunk() | ||
1227 | ---------------------------------------------------------------------- | ||
1228 | |||
1229 | local function stat() | ||
1230 | -- stat -> if_stat while_stat do_stat for_stat repeat_stat | ||
1231 | -- function_stat local_stat return_stat break_stat | ||
1232 | -- expr_stat | ||
1233 | line = llex.ln -- may be needed for error messages | ||
1234 | local c = tok | ||
1235 | local fn = stat_call[c] | ||
1236 | -- handles: if while do for repeat function local return break | ||
1237 | if fn then | ||
1238 | log("-- STATEMENT: begin '"..c.."' line="..line) | ||
1239 | _G[fn]() | ||
1240 | log("-- STATEMENT: end '"..c.."'") | ||
1241 | -- return or break must be last statement | ||
1242 | if c == "return" or c == "break" then return true end | ||
1243 | else | ||
1244 | log("-- STATEMENT: begin 'expr' line="..line) | ||
1245 | expr_stat() | ||
1246 | log("-- STATEMENT: end 'expr'") | ||
1247 | end | ||
1248 | log("") | ||
1249 | return false | ||
1250 | end | ||
1251 | |||
1252 | ---------------------------------------------------------------------- | ||
1253 | -- parse a chunk, which consists of a bunch of statements | ||
1254 | -- * used in parser(), body(), block(), repeat_stat() | ||
1255 | ---------------------------------------------------------------------- | ||
1256 | |||
1257 | function chunk() | ||
1258 | -- chunk -> { stat [';'] } | ||
1259 | log("chunk:") | ||
1260 | local islast = false | ||
1261 | while not islast and not block_follow[tok] do | ||
1262 | islast = stat() | ||
1263 | testnext(";") | ||
1264 | end | ||
1265 | end | ||
1266 | |||
1267 | ---------------------------------------------------------------------- | ||
1268 | -- performs parsing, returns parsed data structure | ||
1269 | ---------------------------------------------------------------------- | ||
1270 | |||
1271 | function parser() | ||
1272 | log("-- TOP: begin") | ||
1273 | open_func() | ||
1274 | fs.is_vararg = true -- main func. is always vararg | ||
1275 | log("") | ||
1276 | nextt() -- read first token | ||
1277 | chunk() | ||
1278 | check("<eof>") | ||
1279 | close_func() | ||
1280 | log("-- TOP: end") | ||
1281 | return top_fs | ||
1282 | end | ||
1283 | |||
1284 | ---------------------------------------------------------------------- | ||
1285 | -- initialization function | ||
1286 | ---------------------------------------------------------------------- | ||
1287 | |||
1288 | function init(lexer) | ||
1289 | llex = lexer -- set lexer (assume user-initialized) | ||
1290 | llex_lex = llex.llex | ||
1291 | top_fs = {} -- reset top level function state | ||
1292 | end | ||
1293 | |||
1294 | return _G | ||