aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/LuaSL/testLua/yueliang-0.4.1/nat-5.0.3/lparser_mk3.lua
diff options
context:
space:
mode:
Diffstat (limited to 'LuaSL/testLua/yueliang-0.4.1/nat-5.0.3/lparser_mk3.lua')
-rw-r--r--LuaSL/testLua/yueliang-0.4.1/nat-5.0.3/lparser_mk3.lua1027
1 files changed, 0 insertions, 1027 deletions
diff --git a/LuaSL/testLua/yueliang-0.4.1/nat-5.0.3/lparser_mk3.lua b/LuaSL/testLua/yueliang-0.4.1/nat-5.0.3/lparser_mk3.lua
deleted file mode 100644
index 17d6f64..0000000
--- a/LuaSL/testLua/yueliang-0.4.1/nat-5.0.3/lparser_mk3.lua
+++ /dev/null
@@ -1,1027 +0,0 @@
1--[[--------------------------------------------------------------------
2
3 lparser.lua
4 Lua 5 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.0.x parser skeleton, for llex_mk3.lua lexer
18-- * written as a module factory with recognizable lparser.c roots
19-- * builds some data, performs logging for educational purposes
20-- * target is to have relatively efficient and clear code
21-- * needs one parameter, a lexer module that implements:
22-- luaX:lex() - returns appropriate [token, semantic info] pairs
23-- luaX.ln - current line number
24-- luaX:errorline(s, [line]) - dies with error message
25--
26-- Usage example:
27-- lex_init = require("llex_mk3.lua")
28-- parser_init = require("lparser_mk3.lua")
29-- local luaX = lex_init(chunk, "=string")
30-- local luaY = parser_init(luaX)
31-- local fs = luaY:parser()
32--
33-- Development notes:
34-- * see test_parser-5.0.lua for grammar elements based on lparser.c
35-- * lparser has a few extra items to help parsing/syntax checking
36-- (a) line number (error reporting), lookahead token storage
37-- (b) per-prototype states needs a storage list
38-- (c) 'break' needs a per-block flag in a stack
39-- (d) 'kind' (v.k) testing needed in expr_stat() and assignment()
40-- for disambiguation, thus v.k manipulation is retained
41-- (e) one line # var (lastln) for ambiguous (split line) function
42-- call checking
43-- (f) most line number function call args retained for future use
44-- (g) Lua 4 compatibility code completely removed
45-- (h) no variable management code! singlevar() always returns VLOCAL
46-- * parsing starts from the end of this file in luaY:parser()
47--
48----------------------------------------------------------------------]]
49
50return
51function(luaX)
52--[[--------------------------------------------------------------------
53-- structures and data initialization
54----------------------------------------------------------------------]]
55
56 local line -- start line # for error messages
57 local lastln -- last line # for ambiguous syntax chk
58 local tok, seminfo -- token, semantic info pair
59 local peek_tok, peek_sem -- ditto, for lookahead
60 local fs -- function state
61 local top_fs = {} -- top-level function state
62 local luaY = {}
63 --------------------------------------------------------------------
64 local block_follow = {} -- lookahead check in chunk(), returnstat()
65 for v in string.gfind("else elseif end until <eof>", "%S+") do
66 block_follow[v] = true
67 end
68 --------------------------------------------------------------------
69 local stat_call = {} -- lookup for calls in stat()
70 for v in string.gfind("if while do for repeat function local return break", "%S+") do
71 stat_call[v] = v.."_stat"
72 end
73 --------------------------------------------------------------------
74 local binopr_left = {} -- binary operators, left priority
75 local binopr_right = {} -- binary operators, right priority
76 for op, lt, rt in string.gfind([[
77{+ 6 6}{- 6 6}{* 7 7}{/ 7 7}{^ 10 9}{.. 5 4}
78{~= 3 3}{== 3 3}{< 3 3}{<= 3 3}{> 3 3}{>= 3 3}
79{and 2 2}{or 1 1}
80]], "{(%S+)%s(%d+)%s(%d+)}") do
81 binopr_left[op] = lt + 0
82 binopr_right[op] = rt + 0
83 end
84 local unopr = { ["not"] = true, ["-"] = true, } -- unary operators
85
86--[[--------------------------------------------------------------------
87-- logging: this logging function is for educational purposes
88-- * logged data can be retrieved from the returned data structure
89-- * or, replace self:log() instances with your custom code...
90----------------------------------------------------------------------]]
91
92 function luaY:log(msg)
93 local log = top_fs.log
94 if not log then log = {}; top_fs.log = log end
95 table.insert(top_fs.log, msg)
96 end
97
98--[[--------------------------------------------------------------------
99-- support functions
100----------------------------------------------------------------------]]
101
102 --------------------------------------------------------------------
103 -- reads in next token
104 --------------------------------------------------------------------
105 function luaY:next()
106 lastln = luaX.ln
107 if peek_tok then -- is there a look-ahead token? if yes, use it
108 tok, seminfo = peek_tok, peek_sem
109 peek_tok = nil
110 else
111 tok, seminfo = luaX:lex() -- read next token
112 end
113 end
114 --------------------------------------------------------------------
115 -- peek at next token (single lookahead for table constructor)
116 --------------------------------------------------------------------
117 function luaY:lookahead()
118 peek_tok, peek_sem = luaX:lex()
119 return peek_tok
120 end
121
122 ------------------------------------------------------------------------
123 -- throws a syntax error
124 ------------------------------------------------------------------------
125 function luaY:syntaxerror(msg)
126 local tok = tok
127 if tok ~= "<number>" and tok ~= "<string>" then
128 if tok == "<name>" then tok = seminfo end
129 tok = "'"..tok.."'"
130 end
131 luaX:errorline(msg.." near "..tok)
132 end
133 --------------------------------------------------------------------
134 -- throws a syntax error if token expected is not there
135 --------------------------------------------------------------------
136 function luaY:error_expected(token)
137 self:syntaxerror("'"..token.."' expected")
138 end
139
140 --------------------------------------------------------------------
141 -- verifies token conditions are met or else throw error
142 --------------------------------------------------------------------
143 function luaY:check_match(what, who, where)
144 if not self:testnext(what) then
145 if where == luaX.ln then
146 self:error_expected(what)
147 else
148 self:syntaxerror("'"..what.."' expected (to close '"..who.."' at line "..where..")")
149 end
150 end
151 end
152 --------------------------------------------------------------------
153 -- tests for a token, returns outcome
154 -- * return value changed to boolean
155 --------------------------------------------------------------------
156 function luaY:testnext(c)
157 if tok == c then self:next(); return true end
158 end
159 --------------------------------------------------------------------
160 -- throws error if condition not matched
161 --------------------------------------------------------------------
162 function luaY:check_condition(c, msg)
163 if not c then self:syntaxerror(msg) end
164 end
165 --------------------------------------------------------------------
166 -- check for existence of a token, throws error if not found
167 --------------------------------------------------------------------
168 function luaY:check(c)
169 if not self:testnext(c) then self:error_expected(c) end
170 end
171
172 --------------------------------------------------------------------
173 -- expect that token is a name, return the name
174 --------------------------------------------------------------------
175 function luaY:str_checkname()
176 self:check_condition(tok == "<name>", "<name> expected")
177 local ts = seminfo
178 self:next()
179 self:log(" str_checkname: '"..ts.."'")
180 return ts
181 end
182 --------------------------------------------------------------------
183 -- adds given string s in string pool, sets e as VK
184 --------------------------------------------------------------------
185 function luaY:codestring(e, s)
186 e.k = "VK"
187 self:log(" codestring: "..string.format("%q", s))
188 end
189 --------------------------------------------------------------------
190 -- consume a name token, adds it to string pool
191 --------------------------------------------------------------------
192 function luaY:checkname(e)
193 self:log(" checkname:")
194 self:codestring(e, self:str_checkname())
195 end
196
197--[[--------------------------------------------------------------------
198-- state management functions with open/close pairs
199----------------------------------------------------------------------]]
200
201 --------------------------------------------------------------------
202 -- enters a code unit, initializes elements
203 --------------------------------------------------------------------
204 function luaY:enterblock(isbreakable)
205 local bl = {} -- per-block state
206 bl.isbreakable = isbreakable
207 bl.prev = fs.bl
208 fs.bl = bl
209 self:log(">> enterblock(isbreakable="..tostring(isbreakable)..")")
210 end
211 --------------------------------------------------------------------
212 -- leaves a code unit, close any upvalues
213 --------------------------------------------------------------------
214 function luaY:leaveblock()
215 local bl = fs.bl
216 fs.bl = bl.prev
217 self:log("<< leaveblock")
218 end
219 --------------------------------------------------------------------
220 -- opening of a function
221 --------------------------------------------------------------------
222 function luaY:open_func()
223 local new_fs -- per-function state
224 if not fs then -- top_fs is created early
225 new_fs = top_fs
226 else
227 new_fs = {}
228 end
229 new_fs.prev = fs -- linked list of function states
230 new_fs.bl = nil
231 fs = new_fs
232 self:log(">> open_func")
233 end
234 --------------------------------------------------------------------
235 -- closing of a function
236 --------------------------------------------------------------------
237 function luaY:close_func()
238 fs = fs.prev
239 self:log("<< close_func")
240 end
241
242--[[--------------------------------------------------------------------
243-- variable (global|local|upvalue) handling
244-- * does nothing for now, always returns "VLOCAL"
245----------------------------------------------------------------------]]
246
247 --------------------------------------------------------------------
248 -- consume a name token, creates a variable (global|local|upvalue)
249 -- * used in prefixexp(), funcname()
250 --------------------------------------------------------------------
251 function luaY:singlevar(v)
252 local varname = self:str_checkname()
253 v.k = "VLOCAL"
254 self:log(" singlevar: name='"..varname.."'")
255 end
256
257--[[--------------------------------------------------------------------
258-- other parsing functions
259-- * for table constructor, parameter list, argument list
260----------------------------------------------------------------------]]
261
262 --------------------------------------------------------------------
263 -- parse a function name suffix, for function call specifications
264 -- * used in primaryexp(), funcname()
265 --------------------------------------------------------------------
266 function luaY:field(v)
267 -- field -> ['.' | ':'] NAME
268 local key = {}
269 self:log(" field: operator="..tok)
270 self:next() -- skip the dot or colon
271 self:checkname(key)
272 v.k = "VINDEXED"
273 end
274 --------------------------------------------------------------------
275 -- parse a table indexing suffix, for constructors, expressions
276 -- * used in recfield(), primaryexp()
277 --------------------------------------------------------------------
278 function luaY:index(v)
279 -- index -> '[' expr ']'
280 self:log(">> index: begin '['")
281 self:next() -- skip the '['
282 self:expr(v)
283 self:check("]")
284 self:log("<< index: end ']'")
285 end
286 --------------------------------------------------------------------
287 -- parse a table record (hash) field
288 -- * used in constructor()
289 --------------------------------------------------------------------
290 function luaY:recfield(cc)
291 -- recfield -> (NAME | '['exp1']') = exp1
292 local key, val = {}, {}
293 if tok == "<name>" then
294 self:log("recfield: name")
295 self:checkname(key)
296 else-- tok == '['
297 self:log("recfield: [ exp1 ]")
298 self:index(key)
299 end
300 self:check("=")
301 self:expr(val)
302 end
303 --------------------------------------------------------------------
304 -- emit a set list instruction if enough elements (LFIELDS_PER_FLUSH)
305 -- * note: retained in this skeleton because it modifies cc.v.k
306 -- * used in constructor()
307 --------------------------------------------------------------------
308 function luaY:closelistfield(cc)
309 if cc.v.k == "VVOID" then return end -- there is no list item
310 cc.v.k = "VVOID"
311 end
312 --------------------------------------------------------------------
313 -- parse a table list (array) field
314 -- * used in constructor()
315 --------------------------------------------------------------------
316 function luaY:listfield(cc)
317 self:log("listfield: expr")
318 self:expr(cc.v)
319 end
320 --------------------------------------------------------------------
321 -- parse a table constructor
322 -- * used in funcargs(), simpleexp()
323 --------------------------------------------------------------------
324 function luaY:constructor(t)
325 -- constructor -> '{' [ field { fieldsep field } [ fieldsep ] ] '}'
326 -- field -> recfield | listfield
327 -- fieldsep -> ',' | ';'
328 self:log(">> constructor: begin")
329 local line = luaX.ln
330 local cc = {}
331 cc.v = {}
332 cc.t = t
333 t.k = "VRELOCABLE"
334 cc.v.k = "VVOID"
335 self:check("{")
336 repeat
337 self:testnext(";") -- compatibility only
338 if tok == "}" then break end
339 -- closelistfield(cc) here
340 local c = tok
341 if c == "<name>" then -- may be listfields or recfields
342 if self:lookahead() ~= "=" then -- look ahead: expression?
343 self:listfield(cc)
344 else
345 self:recfield(cc)
346 end
347 elseif c == "[" then -- constructor_item -> recfield
348 self:recfield(cc)
349 else -- constructor_part -> listfield
350 self:listfield(cc)
351 end
352 until not self:testnext(",") and not self:testnext(";")
353 self:check_match("}", "{", line)
354 -- lastlistfield(cc) here
355 self:log("<< constructor: end")
356 end
357 --------------------------------------------------------------------
358 -- parse the arguments (parameters) of a function declaration
359 -- * used in body()
360 --------------------------------------------------------------------
361 function luaY:parlist()
362 -- parlist -> [ param { ',' param } ]
363 self:log(">> parlist: begin")
364 local dots = false
365 if tok ~= ")" then -- is 'parlist' not empty?
366 repeat
367 local c = tok
368 if c == "..." then
369 self:log("parlist: ... (dots)")
370 dots = true
371 self:next()
372 elseif c == "<name>" then
373 local str = self:str_checkname()
374 else
375 self:syntaxerror("<name> or '...' expected")
376 end
377 until dots or not self:testnext(",")
378 end
379 self:log("<< parlist: end")
380 end
381 --------------------------------------------------------------------
382 -- parse the parameters of a function call
383 -- * contrast with parlist(), used in function declarations
384 -- * used in primaryexp()
385 --------------------------------------------------------------------
386 function luaY:funcargs(f)
387 local args = {}
388 local line = luaX.ln
389 local c = tok
390 if c == "(" then -- funcargs -> '(' [ explist1 ] ')'
391 self:log(">> funcargs: begin '('")
392 if line ~= lastln then
393 self:syntaxerror("ambiguous syntax (function call x new statement)")
394 end
395 self:next()
396 if tok == ")" then -- arg list is empty?
397 args.k = "VVOID"
398 else
399 self:explist1(args)
400 end
401 self:check_match(")", "(", line)
402 elseif c == "{" then -- funcargs -> constructor
403 self:log(">> funcargs: begin '{'")
404 self:constructor(args)
405 elseif c == "<string>" then -- funcargs -> STRING
406 self:log(">> funcargs: begin <string>")
407 self:codestring(args, seminfo)
408 self:next() -- must use 'seminfo' before 'next'
409 else
410 self:syntaxerror("function arguments expected")
411 return
412 end--if c
413 f.k = "VCALL"
414 self:log("<< funcargs: end -- expr is a VCALL")
415 end
416
417--[[--------------------------------------------------------------------
418-- mostly expression functions
419----------------------------------------------------------------------]]
420
421 --------------------------------------------------------------------
422 -- parses an expression in parentheses or a single variable
423 -- * used in primaryexp()
424 --------------------------------------------------------------------
425 function luaY:prefixexp(v)
426 -- prefixexp -> NAME | '(' expr ')'
427 local c = tok
428 if c == "(" then
429 self:log(">> prefixexp: begin ( expr ) ")
430 local line = self.ln
431 self:next()
432 self:expr(v)
433 self:check_match(")", "(", line)
434 self:log("<< prefixexp: end ( expr ) ")
435 elseif c == "<name>" then
436 self:log("prefixexp: <name>")
437 self:singlevar(v)
438 else
439 self:syntaxerror("unexpected symbol")
440 end--if c
441 end
442 --------------------------------------------------------------------
443 -- parses a prefixexp (an expression in parentheses or a single
444 -- variable) or a function call specification
445 -- * used in simpleexp(), assignment(), expr_stat()
446 --------------------------------------------------------------------
447 function luaY:primaryexp(v)
448 -- primaryexp ->
449 -- prefixexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs }
450 self:prefixexp(v)
451 while true do
452 local c = tok
453 if c == "." then -- field
454 self:log("primaryexp: '.' field")
455 self:field(v)
456 elseif c == "[" then -- '[' exp1 ']'
457 self:log("primaryexp: [ exp1 ]")
458 local key = {}
459 self:index(key)
460 elseif c == ":" then -- ':' NAME funcargs
461 self:log("primaryexp: :<name> funcargs")
462 local key = {}
463 self:next()
464 self:checkname(key)
465 self:funcargs(v)
466 elseif c == "(" or c == "<string>" or c == "{" then -- funcargs
467 self:log("primaryexp: "..c.." funcargs")
468 self:funcargs(v)
469 else
470 return
471 end--if c
472 end--while
473 end
474 --------------------------------------------------------------------
475 -- parses general expression types, constants handled here
476 -- * used in subexpr()
477 --------------------------------------------------------------------
478 function luaY:simpleexp(v)
479 -- simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | constructor
480 -- | FUNCTION body | primaryexp
481 local c = tok
482 if c == "<number>" then
483 self:log("simpleexp: <number>="..seminfo)
484 v.k = "VK"
485 self:next() -- must use 'seminfo' before 'next'
486 elseif c == "<string>" then
487 self:log("simpleexp: <string>="..seminfo)
488 self:codestring(v, seminfo)
489 self:next() -- must use 'seminfo' before 'next'
490 elseif c == "nil" then
491 self:log("simpleexp: nil")
492 v.k = "VNIL"
493 self:next()
494 elseif c == "true" then
495 self:log("simpleexp: true")
496 v.k = "VTRUE"
497 self:next()
498 elseif c == "false" then
499 self:log("simpleexp: false")
500 v.k = "VFALSE"
501 self:next()
502 elseif c == "{" then -- constructor
503 self:log("simpleexp: constructor")
504 self:constructor(v)
505 elseif c == "function" then
506 self:log("simpleexp: function")
507 self:next()
508 self:body(v, false, luaX.ln)
509 else
510 self:primaryexp(v)
511 end--if c
512 end
513 ------------------------------------------------------------------------
514 -- Parse subexpressions. Includes handling of unary operators and binary
515 -- operators. A subexpr is given the rhs priority level of the operator
516 -- immediately left of it, if any (limit is -1 if none,) and if a binop
517 -- is found, limit is compared with the lhs priority level of the binop
518 -- in order to determine which executes first.
519 -- * recursively called
520 -- * used in expr()
521 ------------------------------------------------------------------------
522 function luaY:subexpr(v, limit)
523 -- subexpr -> (simpleexp | unop subexpr) { binop subexpr }
524 -- * where 'binop' is any binary operator with a priority
525 -- higher than 'limit'
526 local op = tok
527 local uop = unopr[op]
528 if uop then
529 self:log(" subexpr: uop='"..op.."'")
530 self:next()
531 self:subexpr(v, 8) -- UNARY_PRIORITY
532 else
533 self:simpleexp(v)
534 end
535 -- expand while operators have priorities higher than 'limit'
536 op = tok
537 local binop = binopr_left[op]
538 while binop and binop > limit do
539 local v2 = {}
540 self:log(">> subexpr: binop='"..op.."'")
541 self:next()
542 -- read sub-expression with higher priority
543 local nextop = self:subexpr(v2, binopr_right[op])
544 self:log("<< subexpr: -- evaluate")
545 op = nextop
546 binop = binopr_left[op]
547 end
548 return op -- return first untreated operator
549 end
550 --------------------------------------------------------------------
551 -- Expression parsing starts here. Function subexpr is entered with the
552 -- left operator (which is non-existent) priority of -1, which is lower
553 -- than all actual operators. Expr information is returned in parm v.
554 -- * used in cond(), explist1(), index(), recfield(), listfield(),
555 -- prefixexp(), while_stat(), exp1()
556 --------------------------------------------------------------------
557 function luaY:expr(v)
558 -- expr -> subexpr
559 self:log("expr:")
560 self:subexpr(v, -1)
561 end
562
563--[[--------------------------------------------------------------------
564-- third level parsing functions
565----------------------------------------------------------------------]]
566
567 --------------------------------------------------------------------
568 -- parse a variable assignment sequence
569 -- * recursively called
570 -- * used in expr_stat()
571 --------------------------------------------------------------------
572 function luaY:assignment(v)
573 local e = {}
574 local c = v.v.k
575 self:check_condition(c == "VLOCAL" or c == "VUPVAL" or c == "VGLOBAL"
576 or c == "VINDEXED", "syntax error")
577 if self:testnext(",") then -- assignment -> ',' primaryexp assignment
578 local nv = {} -- expdesc
579 nv.v = {}
580 self:log("assignment: ',' -- next LHS element")
581 self:primaryexp(nv.v)
582 -- lparser.c deals with some register usage conflict here
583 self:assignment(nv)
584 else -- assignment -> '=' explist1
585 self:check("=")
586 self:log("assignment: '=' -- RHS elements follows")
587 self:explist1(e)
588 return -- avoid default
589 end
590 e.k = "VNONRELOC"
591 end
592 --------------------------------------------------------------------
593 -- parse a for loop body for both versions of the for loop
594 -- * used in fornum(), forlist()
595 --------------------------------------------------------------------
596 function luaY:forbody(line, isnum)
597 self:check("do")
598 self:enterblock(true) -- loop block
599 self:block()
600 self:leaveblock()
601 end
602 --------------------------------------------------------------------
603 -- parse a numerical for loop, calls forbody()
604 -- * used in for_stat()
605 --------------------------------------------------------------------
606 function luaY:fornum(line)
607 -- fornum -> NAME = exp1, exp1 [, exp1] DO body
608 self:log(">> fornum: begin")
609 self:check("=")
610 self:log("fornum: index start")
611 self:exp1() -- initial value
612 self:check(",")
613 self:log("fornum: index stop")
614 self:exp1() -- limit
615 if self:testnext(",") then
616 self:log("fornum: index step")
617 self:exp1() -- optional step
618 else
619 -- default step = 1
620 end
621 self:log("fornum: body")
622 self:forbody(line, true)
623 self:log("<< fornum: end")
624 end
625 --------------------------------------------------------------------
626 -- parse a generic for loop, calls forbody()
627 -- * used in for_stat()
628 --------------------------------------------------------------------
629 function luaY:forlist()
630 -- forlist -> NAME {, NAME} IN explist1 DO body
631 self:log(">> forlist: begin")
632 local e = {}
633 while self:testnext(",") do
634 self:str_checkname()
635 end
636 self:check("in")
637 local line = line
638 self:log("forlist: explist1")
639 self:explist1(e)
640 self:log("forlist: body")
641 self:forbody(line, false)
642 self:log("<< forlist: end")
643 end
644 --------------------------------------------------------------------
645 -- parse a function name specification
646 -- * used in func_stat()
647 --------------------------------------------------------------------
648 function luaY:funcname(v)
649 -- funcname -> NAME {field} [':' NAME]
650 self:log(">> funcname: begin")
651 local needself = false
652 self:singlevar(v)
653 while tok == "." do
654 self:log("funcname: -- '.' field")
655 self:field(v)
656 end
657 if tok == ":" then
658 self:log("funcname: -- ':' field")
659 needself = true
660 self:field(v)
661 end
662 self:log("<< funcname: end")
663 return needself
664 end
665 --------------------------------------------------------------------
666 -- parse the single expressions needed in numerical for loops
667 -- * used in fornum()
668 --------------------------------------------------------------------
669 function luaY:exp1()
670 -- exp1 -> expr
671 local e = {}
672 self:log(">> exp1: begin")
673 self:expr(e)
674 self:log("<< exp1: end")
675 end
676 --------------------------------------------------------------------
677 -- parse condition in a repeat statement or an if control structure
678 -- * used in repeat_stat(), test_then_block()
679 --------------------------------------------------------------------
680 function luaY:cond(v)
681 -- cond -> expr
682 self:log(">> cond: begin")
683 self:expr(v) -- read condition
684 self:log("<< cond: end")
685 end
686 --------------------------------------------------------------------
687 -- parse part of an if control structure, including the condition
688 -- * used in if_stat()
689 --------------------------------------------------------------------
690 function luaY:test_then_block(v)
691 -- test_then_block -> [IF | ELSEIF] cond THEN block
692 self:next() -- skip IF or ELSEIF
693 self:log("test_then_block: test condition")
694 self:cond(v)
695 self:check("then")
696 self:log("test_then_block: then block")
697 self:block() -- 'then' part
698 end
699 --------------------------------------------------------------------
700 -- parse a local function statement
701 -- * used in local_stat()
702 --------------------------------------------------------------------
703 function luaY:localfunc()
704 -- localfunc -> NAME body
705 local v, b = {}
706 self:log("localfunc: begin")
707 local str = self:str_checkname()
708 v.k = "VLOCAL"
709 self:log("localfunc: body")
710 self:body(b, false, luaX.ln)
711 self:log("localfunc: end")
712 end
713 --------------------------------------------------------------------
714 -- parse a local variable declaration statement
715 -- * used in local_stat()
716 --------------------------------------------------------------------
717 function luaY:localstat()
718 -- localstat -> NAME {',' NAME} ['=' explist1]
719 self:log(">> localstat: begin")
720 local e = {}
721 repeat
722 local str = self:str_checkname()
723 until not self:testnext(",")
724 if self:testnext("=") then
725 self:log("localstat: -- assignment")
726 self:explist1(e)
727 else
728 e.k = "VVOID"
729 end
730 self:log("<< localstat: end")
731 end
732 --------------------------------------------------------------------
733 -- parse a list of comma-separated expressions
734 -- * used in return_stat(), localstat(), funcargs(), assignment(),
735 -- forlist()
736 --------------------------------------------------------------------
737 function luaY:explist1(e)
738 -- explist1 -> expr { ',' expr }
739 self:log(">> explist1: begin")
740 self:expr(e)
741 while self:testnext(",") do
742 self:log("explist1: ',' -- continuation")
743 self:expr(e)
744 end
745 self:log("<< explist1: end")
746 end
747 --------------------------------------------------------------------
748 -- parse function declaration body
749 -- * used in simpleexp(), localfunc(), func_stat()
750 --------------------------------------------------------------------
751 function luaY:body(e, needself, line)
752 -- body -> '(' parlist ')' chunk END
753 self:open_func()
754 self:log("body: begin")
755 self:check("(")
756 if needself then
757 -- handle 'self' processing here
758 end
759 self:log("body: parlist")
760 self:parlist()
761 self:check(")")
762 self:log("body: chunk")
763 self:chunk()
764 self:check_match("end", "function", line)
765 self:log("body: end")
766 self:close_func()
767 end
768 --------------------------------------------------------------------
769 -- parse a code block or unit
770 -- * used in do_stat(), while_stat(), repeat_stat(), forbody(),
771 -- test_then_block(), if_stat()
772 --------------------------------------------------------------------
773 function luaY:block()
774 -- block -> chunk
775 self:log("block: begin")
776 self:enterblock(false)
777 self:chunk()
778 self:leaveblock()
779 self:log("block: end")
780 end
781
782--[[--------------------------------------------------------------------
783-- second level parsing functions, all with '_stat' suffix
784-- * stat() -> *_stat()
785----------------------------------------------------------------------]]
786
787 --------------------------------------------------------------------
788 -- initial parsing for a for loop, calls fornum() or forlist()
789 -- * used in stat()
790 --------------------------------------------------------------------
791 function luaY:for_stat()
792 -- stat -> for_stat -> fornum | forlist
793 local line = line
794 self:log("for_stat: begin")
795 self:enterblock(false) -- block to control variable scope
796 self:next() -- skip 'for'
797 local str = self:str_checkname() -- first variable name
798 local c = tok
799 if c == "=" then
800 self:log("for_stat: numerical loop")
801 self:fornum(line)
802 elseif c == "," or c == "in" then
803 self:log("for_stat: list-based loop")
804 self:forlist()
805 else
806 self:syntaxerror("'=' or 'in' expected")
807 end
808 self:check_match("end", "for", line)
809 self:leaveblock()
810 self:log("for_stat: end")
811 end
812 --------------------------------------------------------------------
813 -- parse a while-do control structure, body processed by block()
814 -- * used in stat()
815 --------------------------------------------------------------------
816 function luaY:while_stat()
817 -- stat -> while_stat -> WHILE cond DO block END
818 local line = line
819 local v = {}
820 self:next() -- skip WHILE
821 self:log("while_stat: begin/condition")
822 self:expr(v) -- parse condition
823 self:enterblock(true)
824 self:check("do")
825 self:log("while_stat: block")
826 self:block()
827 self:check_match("end", "while", line)
828 self:leaveblock()
829 self:log("while_stat: end")
830 end
831 --------------------------------------------------------------------
832 -- parse a repeat-until control structure, body parsed by block()
833 -- * used in stat()
834 --------------------------------------------------------------------
835 function luaY:repeat_stat()
836 -- stat -> repeat_stat -> REPEAT block UNTIL cond
837 local line = line
838 local v = {}
839 self:log("repeat_stat: begin")
840 self:enterblock(true)
841 self:next()
842 self:block()
843 self:check_match("until", "repeat", line)
844 self:log("repeat_stat: condition")
845 self:cond(v)
846 self:leaveblock()
847 self:log("repeat_stat: end")
848 end
849 --------------------------------------------------------------------
850 -- parse an if control structure
851 -- * used in stat()
852 --------------------------------------------------------------------
853 function luaY:if_stat()
854 -- stat -> if_stat -> IF cond THEN block
855 -- {ELSEIF cond THEN block} [ELSE block] END
856 local line = line
857 local v = {}
858 self:log("if_stat: if...then")
859 self:test_then_block(v) -- IF cond THEN block
860 while tok == "elseif" do
861 self:log("if_stat: elseif...then")
862 self:test_then_block(v) -- ELSEIF cond THEN block
863 end
864 if tok == "else" then
865 self:log("if_stat: else...")
866 self:next() -- skip ELSE
867 self:block() -- 'else' part
868 end
869 self:check_match("end", "if", line)
870 self:log("if_stat: end")
871 end
872 --------------------------------------------------------------------
873 -- parse a return statement
874 -- * used in stat()
875 --------------------------------------------------------------------
876 function luaY:return_stat()
877 -- stat -> return_stat -> RETURN explist
878 local e = {}
879 self:next() -- skip RETURN
880 local c = tok
881 if block_follow[c] or c == ";" then
882 -- return no values
883 self:log("return_stat: no return values")
884 else
885 self:log("return_stat: begin")
886 self:explist1(e) -- optional return values
887 self:log("return_stat: end")
888 end
889 end
890 --------------------------------------------------------------------
891 -- parse a break statement
892 -- * used in stat()
893 --------------------------------------------------------------------
894 function luaY:break_stat()
895 -- stat -> break_stat -> BREAK
896 local bl = fs.bl
897 self:next() -- skip BREAK
898 while bl and not bl.isbreakable do -- find a breakable block
899 bl = bl.prev
900 end
901 if not bl then
902 self:syntaxerror("no loop to break")
903 end
904 self:log("break_stat: -- break out of loop")
905 end
906 --------------------------------------------------------------------
907 -- parse a function call with no returns or an assignment statement
908 -- * the struct with .prev is used for name searching in lparse.c,
909 -- so it is retained for now; present in assignment() also
910 -- * used in stat()
911 --------------------------------------------------------------------
912 function luaY:expr_stat()
913 -- stat -> expr_stat -> func | assignment
914 local v = {}
915 v.v = {}
916 self:primaryexp(v.v)
917 if v.v.k == "VCALL" then -- stat -> func
918 -- call statement uses no results
919 self:log("expr_stat: function call k='"..v.v.k.."'")
920 else -- stat -> assignment
921 self:log("expr_stat: assignment k='"..v.v.k.."'")
922 v.prev = nil
923 self:assignment(v)
924 end
925 end
926 --------------------------------------------------------------------
927 -- parse a function statement
928 -- * used in stat()
929 --------------------------------------------------------------------
930 function luaY:function_stat()
931 -- stat -> function_stat -> FUNCTION funcname body
932 local line = line
933 local v, b = {}, {}
934 self:log("function_stat: begin")
935 self:next() -- skip FUNCTION
936 local needself = self:funcname(v)
937 self:log("function_stat: body needself='"..tostring(needself).."'")
938 self:body(b, needself, line)
939 self:log("function_stat: end")
940 end
941 --------------------------------------------------------------------
942 -- parse a simple block enclosed by a DO..END pair
943 -- * used in stat()
944 --------------------------------------------------------------------
945 function luaY:do_stat()
946 -- stat -> do_stat -> DO block END
947 self:next() -- skip DO
948 self:log("do_stat: begin")
949 self:block()
950 self:log("do_stat: end")
951 self:check_match("end", "do", line)
952 end
953 --------------------------------------------------------------------
954 -- parse a statement starting with LOCAL
955 -- * used in stat()
956 --------------------------------------------------------------------
957 function luaY:local_stat()
958 -- stat -> local_stat -> LOCAL FUNCTION localfunc
959 -- -> LOCAL localstat
960 self:next() -- skip LOCAL
961 if self:testnext("function") then -- local function?
962 self:log("local_stat: local function")
963 self:localfunc()
964 else
965 self:log("local_stat: local statement")
966 self:localstat()
967 end
968 end
969
970--[[--------------------------------------------------------------------
971-- main function, top level parsing functions
972-- * [entry] -> parser() -> chunk() -> stat()
973----------------------------------------------------------------------]]
974
975 --------------------------------------------------------------------
976 -- initial parsing for statements, calls '_stat' suffixed functions
977 -- * used in chunk()
978 --------------------------------------------------------------------
979 function luaY:stat()
980 line = luaX.ln
981 local c = tok
982 local fn = stat_call[c]
983 -- handles: if while do for repeat function local return break
984 if fn then
985 self:log("-- STATEMENT: begin '"..c.."' line="..line)
986 self[fn](self)
987 self:log("-- STATEMENT: end '"..c.."'")
988 -- return or break must be last statement
989 if c == "return" or c == "break" then return true end
990 else
991 self:log("-- STATEMENT: begin 'expr' line="..line)
992 self:expr_stat()
993 self:log("-- STATEMENT: end 'expr'")
994 end
995 self:log("")
996 return false
997 end
998 --------------------------------------------------------------------
999 -- parse a chunk, which consists of a bunch of statements
1000 -- * used in parser(), body(), block()
1001 --------------------------------------------------------------------
1002 function luaY:chunk()
1003 -- chunk -> { stat [';'] }
1004 self:log("chunk:")
1005 local islast = false
1006 while not islast and not block_follow[tok] do
1007 islast = self:stat()
1008 self:testnext(";")
1009 end
1010 end
1011 --------------------------------------------------------------------
1012 -- performs parsing, returns parsed data structure
1013 --------------------------------------------------------------------
1014 function luaY:parser()
1015 self:log("-- TOP: begin")
1016 self:open_func()
1017 self:log("")
1018 self:next() -- read first token
1019 self:chunk()
1020 self:check_condition(tok == "<eof>", "<eof> expected")
1021 self:close_func()
1022 self:log("-- TOP: end")
1023 return top_fs
1024 end
1025 --------------------------------------------------------------------
1026 return luaY -- return actual module to user, done
1027end