1 # Copyright (C) 2006-2008, The Perl Foundation.
6 PASTGrammar.tg - A grammar for transforming the output of a PGE parse
7 into an abstract syntax tree (PAST).
14 grammar Lua::PAST::Grammar is TGE::Grammar;
17 transform past (ROOT) :language('PIR') {
20 set_hll_global ['Lua::PAST'], '$looplevel', $P0
23 set_hll_global ['Lua::PAST'], '?vararg', $P0
25 new symbtab, 'Lua::Symbtab'
26 symbtab.'push_scope'()
27 set_hll_global ['Lua::PAST'], '$symbtab', symbtab
30 past = tree.'get'('past', $P0, 'Lua::Grammar::block')
34 $P0 = get_hll_global ['PAST'], 'Var'
35 arg = $P0.'new'('node'=>node, 'name'=>'vararg', 'scope'=>'parameter', 'slurpy'=>1)
36 $P0 = get_hll_global ['PAST'], 'Block'
37 .return $P0.'new'(arg, past, 'node'=>node, 'name'=>'&main')
40 $S0 = "symbol table (" . $S1
46 transform past (Lua::Grammar::block) :language('PIR') {
48 $P0 = get_hll_global ['PAST'], 'Stmts'
49 past = $P0.'new'('node'=>node)
50 $P0 = node['statement']
52 .local pmc iter, cpast
53 new iter, 'Iterator', $P0
57 cpast = tree.'get'('past', $P0, 'Lua::Grammar::statement')
61 $P0 = node['last_statement']
64 cpast = tree.'get'('past', $P0, 'Lua::Grammar::statement')
68 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
74 transform past (Lua::Grammar::statement) :language('PIR') {
75 $S0 = node.'find_key'()
77 $S0 = concat 'Lua::Grammar::', $S0
78 .return tree.'get'('past', $P0, $S0)
82 transform past (Lua::Grammar::do_block) :language('PIR') {
84 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
85 symbtab.'push_scope'()
87 .return tree.'get'('past', $P0, 'Lua::Grammar::block')
91 transform past (Lua::Grammar::if_stat) :language('PIR') {
93 $P0 = node['expression']
94 expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
96 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
97 symbtab.'push_scope'()
98 .local pmc past, cpast, blk
100 blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
101 $P0 = get_hll_global ['PAST'], 'Op'
102 past = $P0.'new'(expr, blk, 'node'=>node, 'pasttype'=>'if')
104 $P0 = node['elseif_block']
107 new iter, 'Iterator', $P0
111 $P1 = tree.'get'('past', $P0, 'Lua::Grammar::elseif_block')
116 $P0 = node['else_block']
118 symbtab.'push_scope'()
121 blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
128 transform past (Lua::Grammar::elseif_block) :language('PIR') {
130 $P0 = node['expression']
131 expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
133 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
134 symbtab.'push_scope'()
137 blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
138 $P0 = get_hll_global ['PAST'], 'Op'
139 .return $P0.'new'(expr, blk, 'node'=>node, 'pasttype'=>'if')
143 transform past (Lua::Grammar::while_stat) :language('PIR') {
145 looplevel = get_hll_global ['Lua::PAST'], '$looplevel'
148 $P0 = node['expression']
149 expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
151 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
152 symbtab.'push_scope'()
155 blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
157 $P0 = get_hll_global ['PAST'], 'Op'
158 .return $P0.'new'(expr, blk, 'node'=>node, 'pasttype'=>'while')
162 transform past (Lua::Grammar::repeat_stat) :language('PIR') {
164 looplevel = get_hll_global ['Lua::PAST'], '$looplevel'
167 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
168 symbtab.'push_scope'()
171 blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
173 $P0 = node['expression']
174 expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
176 $P0 = get_hll_global ['PAST'], 'Op'
177 .return $P0.'new'(blk, expr, 'node'=>node, 'pasttype'=>'repeat')
181 transform past (Lua::Grammar::for_stat) :language('PIR') {
183 looplevel = get_hll_global ['Lua::PAST'], '$looplevel'
186 $S0 = node.'find_key'()
188 $S1 = concat 'Lua::Grammar::', $S0
189 past = tree.'get'('past', $P0, $S1)
191 $P0 = node['for_body']
193 blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
200 transform past (Lua::Grammar::fornum) :language('PIR') {
202 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
203 symbtab.'push_scope'()
205 $S0 = $P0.'result_object'()
207 $S1 = symbtab.'insert'($S0)
208 $P0 = get_hll_global ['PAST'], 'Var'
209 name = $P0.'new'('node'=>node, 'name'=>$S1, 'scope'=>'lexical', 'isdecl'=>1, 'lvalue'=>1)
211 new explist, 'ResizablePMCArray'
212 $P0 = node['expression']
214 .local pmc iter, expr
215 new iter, 'Iterator', $P0
219 expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
223 unless $I0 < 3 goto L3
224 $P0 = get_hll_global ['PAST'], 'Val'
225 expr = $P0.'new'('node'=>node, 'name'=>'LuaNumber', 'value'=>'1')
228 $P0 = get_hll_global ['PAST'], 'Op'
229 .return $P0.'new'(name, explist, 'node'=>node, 'pasttype'=>'fornum')
233 transform past (Lua::Grammar::forlist) :language('PIR') {
235 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
236 symbtab.'push_scope'()
238 new namelist, 'ResizablePMCArray'
239 $P0 = node['name_list']
241 .local pmc iter, cpast
242 new iter, 'Iterator', $P0
246 $S0 = $P0.'result_object'()
247 $S1 = symbtab.'insert'($S0)
248 $P0 = get_hll_global ['PAST'], 'Var'
249 cpast = $P0.'new'('node'=>node, 'name'=>$S1, 'scope'=>'lexical', 'isdecl'=>1, 'lvalue'=>1)
253 $P0 = node['expression_list']
255 explist = tree.'get'('explist', $P0, 'Lua::Grammar::expression_list')
256 $P0 = get_hll_global ['PAST'], 'Op'
257 .return $P0.'new'(namelist, explist, 'node'=>node, 'pasttype'=>'forlist')
261 transform past (Lua::Grammar::local_stat) :language('PIR') {
262 $S0 = node.'find_key'()
264 $S0 = concat 'Lua::Grammar::', $S0
265 .return tree.'get'('past', $P0, $S0)
269 transform past (Lua::Grammar::local_declaration) :language('PIR') {
271 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
273 $P0 = node['expression_list']
276 explist = tree.'get'('explist', $P0, 'Lua::Grammar::expression_list')
278 unless null explist goto L2
279 new explist, 'ResizablePMCArray'
283 new namelist, 'ResizablePMCArray'
284 .local pmc iter, cpast
285 new iter, 'Iterator', $P0
289 $S0 = $P0.'result_object'()
290 $S1 = symbtab.'insert'($S0)
291 $P0 = get_hll_global ['PAST'], 'Var'
292 cpast = $P0.'new'('node'=>node, 'name'=>$S1, 'scope'=>'lexical', 'isdecl'=>1, 'lvalue'=>1)
296 $P0 = get_hll_global ['PAST'], 'Op'
297 .return $P0.'new'(namelist, explist, 'node'=>node, 'pasttype'=>'assignlist')
301 transform past (Lua::Grammar::local_function) :language('PIR') {
303 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
306 $S0 = $P0.'result_object'()
307 $S1 = symbtab.'insert'($S0)
308 $P1 = get_hll_global ['PAST'], 'Var'
309 var = $P1.'new'('node'=>$P0, 'name'=>$S1, 'scope'=>'lexical', 'isdecl'=>1, 'lvalue'=>1)
311 $P0 = node['function_body']
312 past = tree.'get'('past', $P0, 'Lua::Grammar::function_body')
314 $P0 = get_hll_global ['PAST'], 'Op'
315 $P1 = $P0.'new'(var, past, 'node'=>node, 'pasttype'=>'assign')
320 transform past (Lua::Grammar::return_statement) :language('PIR') {
321 $P1 = get_hll_global ['PAST'], 'Op'
322 $P0 = node['expression_list']
326 explist = tree.'get'('explist', $P0, 'Lua::Grammar::expression_list')
327 .return $P1.'new'(explist :flat, 'node'=>node, 'pasttype'=>'return')
329 .return $P1.'new'('node'=>node, 'pasttype'=>'return')
333 transform past (Lua::Grammar::break_statement) :language('PIR') {
335 looplevel = get_hll_global ['Lua::PAST'], '$looplevel'
336 if looplevel <= 0 goto L1
337 $P0 = get_hll_global ['PAST'], 'Op'
338 .return $P0.'new'('node'=>node, 'pasttype'=>'break')
340 node.'syntaxerror'("no loop to break")
344 transform past (Lua::Grammar::expression_stat) :language('PIR') {
345 $P0 = node['assignment']
346 unless null $P0 goto L1
347 $P0 = node['primary_expression']
348 .return tree.'get'('past', $P0, 'Lua::Grammar::primary_expression')
350 .local pmc varlist, explist
352 explist = tree.'get'('explist', $P0, 'Lua::Grammar::assignment')
353 varlist = tree.'get'('varlist', $P0, 'Lua::Grammar::assignment')
355 $P0 = node['primary_expression']
356 expr = tree.'get'('past', $P0, 'Lua::Grammar::primary_expression')
358 unshift varlist, expr
359 $P0 = get_hll_global ['PAST'], 'Op'
360 .return $P0.'new'(varlist, explist, 'node'=>node, 'pasttype'=>'assignlist')
364 transform varlist (Lua::Grammar::assignment) :language('PIR') {
366 $P0 = node['expression_list']
368 new varlist, 'ResizablePMCArray'
371 $P0 = node['assignment']
372 varlist = tree.'get'('varlist', $P0, 'Lua::Grammar::assignment')
374 $P0 = node['primary_expression']
375 expr = tree.'get'('past', $P0, 'Lua::Grammar::primary_expression')
377 unshift varlist, expr
382 transform explist (Lua::Grammar::assignment) :language('PIR') {
383 $P0 = node['expression_list']
385 .return tree.'get'('explist', $P0, 'Lua::Grammar::expression_list')
387 $P0 = node['assignment']
388 .return tree.'get'('explist', $P0, 'Lua::Grammar::assignment')
392 transform explist (Lua::Grammar::function_args) :language('PIR') {
393 .local pmc explist, past
394 $P0 = node['constructor']
396 past = tree.'get'('past', $P0, 'Lua::Grammar::constructor')
397 new explist, 'ResizablePMCArray'
403 past = tree.'get'('past', $P0, 'Lua::Grammar::string')
404 new explist, 'ResizablePMCArray'
408 $P0 = node['expression_list']
409 unless null $P0 goto L3
410 new explist, 'ResizablePMCArray'
414 .return tree.'get'('explist', $P0, 'Lua::Grammar::expression_list')
418 transform past (Lua::Grammar::function_stat) :language('PIR') {
420 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
422 $P0 = node['functionname']
423 var = tree.'get'('past', $P0, 'Lua::Grammar::functionname')
424 $S0 = $P0.'result_object'()
427 $P1 = get_hll_global ['PAST'], 'Var'
428 $S1 = symbtab.'insert'('self')
429 past = $P1.'new'('node'=>$P0, 'name'=>$S1, 'scope'=>'parameter')
430 set_hll_global ['Lua::PAST'], '$?self', past
432 $S0 = tree.'get'('Name', $P0, 'Lua::Grammar::functionname')
433 $P0 = node['function_body']
434 past = tree.'get'('past', $P0, 'Lua::Grammar::function_body')
436 $P0 = get_hll_global ['PAST'], 'Op'
437 .return $P0.'new'(var, past, 'node'=>node, 'pasttype'=>'assign')
441 transform Name (Lua::Grammar::functionname) :language('PIR') {
446 new iter, 'Iterator', $P0
449 if name == '' goto L3
453 $S0 = $P0.'result_object'()
461 transform past (Lua::Grammar::functionname) :language('PIR') {
463 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
466 new iter, 'Iterator', $P0
468 $S0 = $P0.'result_object'()
470 $P0 = get_hll_global ['PAST'], 'Var'
471 ($I0, $S1) = symbtab.'lookup'($S0)
473 past = $P0.'new'('node'=>node, 'name'=>$S1, 'scope'=>'lexical')
476 past = $P0.'new'('node'=>node, 'name'=>$S0, 'scope'=>'package')
480 $S0 = $P0.'result_object'()
482 $P1 = get_hll_global ['PAST'], 'Val'
483 key = $P1.'new'('node'=>$P0, 'name'=>'key', 'value'=>$S0)
484 $P0 = get_hll_global ['PAST'], 'Var'
485 past = $P0.'new'(past, key, 'node'=>node, 'scope'=>'keyed')
493 transform past (Lua::Grammar::function_body) :language('PIR') {
495 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
496 symbtab.'push_scope'()
498 new parlist, 'ResizablePMCArray'
500 var = get_hll_global ['Lua::PAST'], '$?self'
504 set_hll_global ['Lua::PAST'], '$?self', var
506 $P0 = node['parameter_list']
508 $P1 = $P0['name_list']
512 new iter, 'Iterator', $P1
516 $S0 = $P1.'result_object'()
517 $S1 = symbtab.'insert'($S0)
518 $P2 = get_hll_global ['PAST'], 'Var'
519 var = $P2.'new'('node'=>$P1, 'name'=>$S1, 'scope'=>'parameter')
527 $P2 = get_hll_global ['PAST'], 'Var'
528 var = $P2.'new'('node'=>$P1, 'name'=>'vararg', 'scope'=>'parameter', 'slurpy'=>1)
533 $P2 = get_hll_global ['PAST'], 'Var'
534 var = $P2.'new'('node'=>$P0, 'name'=>'extra', 'scope'=>'parameter', 'slurpy'=>1)
537 .local pmc has_vararg
538 has_vararg = get_hll_global ['Lua::PAST'], '?vararg'
541 set_hll_global ['Lua::PAST'], '?vararg', $P0
543 looplevel = get_hll_global ['Lua::PAST'], '$looplevel'
546 set_hll_global ['Lua::PAST'], '$looplevel', $P0
549 past = tree.'get'('past', $P0, 'Lua::Grammar::block')
550 set_hll_global ['Lua::PAST'], '$looplevel', looplevel
551 set_hll_global ['Lua::PAST'], '?vararg', has_vararg
552 $P0 = get_hll_global ['PAST'], 'Block'
553 .return $P0.'new'(parlist :flat, past, 'node'=>node)
557 transform past (Lua::Grammar::constructor) :language('PIR') {
559 $P0 = get_hll_global ['PAST'], 'Val'
560 past = $P0.'new'('node'=>node, 'name'=>'constructor')
561 $P0 = node['tablefieldlist']
564 $P0 = $P0['tablefield']
565 .local pmc iter, field
567 new iter, 'Iterator', $P0
571 $S0 = $P0.'find_key'()
573 unless $S0 == 'expression' goto L3
574 field = tree.'get'('past', $P0, 'Lua::Grammar::expression')
578 $S0 = concat 'Lua::Grammar::', $S0
579 field = tree.'get'('record', $P0, $S0)
587 transform record (Lua::Grammar::record_field) :language('PIR') {
589 new record, 'FixedPMCArray'
591 $S0 = node.'find_key'()
593 $S0 = concat 'Lua::Grammar::', $S0
594 $P1 = tree.'get'('key', $P0, $S0)
596 $P0 = node['expression']
597 $P1 = tree.'get'('past', $P0, 'Lua::Grammar::expression')
603 transform key (Lua::Grammar::Name) :language('PIR') {
604 $S0 = node.'result_object'()
605 $P0 = get_hll_global ['PAST'], 'Val'
606 .return $P0.'new'('node'=>node, 'name'=>'key', 'value'=>$S0)
610 transform key (Lua::Grammar::index) :language('PIR') {
611 $P0 = node['expression']
612 .return tree.'get'('past', $P0, 'Lua::Grammar::expression')
616 transform explist (Lua::Grammar::expression_list) :language('PIR') {
618 new explist, 'ResizablePMCArray'
619 $P0 = node['expression']
620 .local pmc iter, expr
621 new iter, 'Iterator', $P0
625 expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
633 transform past (Lua::Grammar::expression) :language('PIR') {
635 .return tree.'get'('past', $P0, 'Lua::Grammar::expr')
639 transform past (Lua::Grammar::expr) :language('PIR') {
642 unless type == 'term:' goto L1
643 $S0 = node.'find_key'()
645 $S0 = concat 'Lua::Grammar::', $S0
646 .return tree.'get'('past', $P0, $S0)
648 .local pmc optable, optok
650 optable = get_hll_global [ 'Lua::Grammar' ], '$optable'
651 optok = optable[type]
652 pirop = optok['pirop']
654 $P0 = get_hll_global ['PAST'], 'Op'
655 if pirop == '' goto L2
656 past = $P0.'new'('node'=>node, 'name'=>type, 'pasttype'=>'pirop', 'pirop'=>pirop)
660 past = $P0.'new'('node'=>node, 'name'=>type, 'pasttype'=>$S0)
663 .local pmc iter, expr
664 new iter, 'Iterator', $P0
668 expr = tree.'get'('past', $P0, 'Lua::Grammar::expr')
676 transform past (Lua::Grammar::simple_expression) :language('PIR') {
677 $S0 = node.'find_key'()
679 $S0 = concat 'Lua::Grammar::', $S0
680 .return tree.'get'('past', $P0, $S0)
684 transform past (Lua::Grammar::primary_expression) :language('PIR') {
686 $P0 = node['prefix_expression']
687 past = tree.'get'('past', $P0, 'Lua::Grammar::prefix_expression')
688 $P0 = node['slice_expression']
690 .local pmc iter, key, args
691 new iter, 'Iterator', $P0
695 $P1 = $P0['function_args']
697 args = tree.'get'('explist', $P1, 'Lua::Grammar::function_args')
701 key = tree.'get'('key', $P1, 'Lua::Grammar::Name')
702 $P2 = get_hll_global ['PAST'], 'Var'
703 meth = $P2.'new'(past, key, 'node'=>node, 'scope'=>'keyed')
705 $P2 = get_hll_global ['PAST'], 'Op'
706 past = $P2.'new'(meth, obj, args :flat, 'node'=>node, 'pasttype'=>'call')
709 $P2 = get_hll_global ['PAST'], 'Op'
710 past = $P2.'new'(past, args :flat, 'node'=>node, 'pasttype'=>'call')
715 key = tree.'get'('key', $P1, 'Lua::Grammar::Name')
716 $P2 = get_hll_global ['PAST'], 'Var'
717 past = $P2.'new'(past, key, 'node'=>node, 'scope'=>'keyed')
722 key = tree.'get'('key', $P1, 'Lua::Grammar::index')
723 $P2 = get_hll_global ['PAST'], 'Var'
724 past = $P2.'new'(past, key, 'node'=>node, 'scope'=>'keyed')
727 internal_error("primary expression")
733 transform past (Lua::Grammar::prefix_expression) :language('PIR') {
734 $S0 = node.'find_key'()
736 $S0 = concat 'Lua::Grammar::', $S0
737 .return tree.'get'('past', $P0, $S0)
741 transform past (Lua::Grammar::parenthesed_expression) :language('PIR') {
743 $P0 = node['expression']
744 past = tree.'get'('past', $P0, 'Lua::Grammar::expression')
745 $P0 = get_hll_global ['PAST'], 'Op'
746 .return $P0.'new'(past, 'node'=>node, 'pasttype'=>'parenthese')
750 transform past (Lua::Grammar::Name) :language('PIR') {
752 symbtab = get_hll_global ['Lua::PAST'], '$symbtab'
753 $P0 = get_hll_global ['PAST'], 'Var'
754 $S0 = node.'result_object'()
755 ($I0, $S1) = symbtab.'lookup'($S0)
757 .return $P0.'new'('node'=>node, 'name'=>$S1, 'scope'=>'lexical')
759 .return $P0.'new'('node'=>node, 'name'=>$S0, 'scope'=>'package')
763 transform past (Lua::Grammar::vararg) :language('PIR') {
764 .local pmc has_vararg
765 has_vararg = get_hll_global ['Lua::PAST'], '?vararg'
766 unless has_vararg goto L1
767 $P0 = get_hll_global ['PAST'], 'Op'
768 .return $P0.'new'('node'=>node, 'pasttype'=>'vararg')
770 node.'syntaxerror'("cannot use '...' outside a vararg function")
774 transform past (Lua::Grammar::nil) :language('PIR') {
775 $P0 = get_hll_global ['PAST'], 'Val'
776 .return $P0.'new'('node'=>node, 'name'=>'LuaNil')
780 transform past (Lua::Grammar::true) :language('PIR') {
781 $P0 = get_hll_global ['PAST'], 'Val'
782 .return $P0.'new'('node'=>node, 'name'=>'LuaBoolean', 'value'=>1)
786 transform past (Lua::Grammar::false) :language('PIR') {
787 $P0 = get_hll_global ['PAST'], 'Val'
788 .return $P0.'new'('node'=>node, 'name'=>'LuaBoolean', 'value'=>0)
792 transform past (Lua::Grammar::number) :language('PIR') {
793 $S0 = node.'result_object'()
794 $P0 = get_hll_global ['PAST'], 'Val'
795 .return $P0.'new'('node'=>node, 'name'=>'LuaNumber', 'value'=>$S0)
799 transform past (Lua::Grammar::string) :language('PIR') {
800 $S0 = node.'find_key'()
802 $S0 = $P0.'result_object'()
803 $P0 = get_hll_global ['PAST'], 'Val'
804 .return $P0.'new'('node'=>node, 'name'=>'LuaString', 'value'=>$S0)
809 Klaas-Jan Stol <parrotcode@gmail.com>