# New Ticket Created by Klaas-Jan Stol # Please include the string: [perl #41678] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=41678 >
hi, attached a new patch for lang/pynie. This patch includes the changes of my previous patch (is not applied yet). (the in/not test renames) This patch also includes: * fix for while_stmt (test 06 is now passing) * start of function def and parameters * start of class def * add transform for compound_stmt regards, kjs
Index: languages/pynie/src/parser/Grammar.pg =================================================================== --- languages/pynie/src/parser/Grammar.pg (revision 17307) +++ languages/pynie/src/parser/Grammar.pg (working copy) @@ -150,12 +150,13 @@ rule classdef { - <'class'> <classname> <inheritance>? <':'> <suite> + <'class'> <identifier> <inheritance>? <':'> <suite> } -rule classname { - <identifier> -} +# prevent another subrule +#rule classname { +# <identifier> +#} rule inheritance { <'('> <expression_list>? <')'> @@ -482,15 +483,15 @@ rule not_test { | <'not'> <not_test> - | <not_in_test> + | <in_test> } -rule not_in_test { - <is_not_test> [ <'not'>? <'in'> <is_not_test> ]* +rule in_test { + <is_test> [ (<'not'>)? <'in'> <is_test> ]* } -rule is_not_test { - <comparison> [ <'is'> <'not'>? <comparison> ]* +rule is_test { + <comparison> [ <'is'> (<'not'>)? <comparison> ]* } token 'comparison' is optable { ... } Index: languages/pynie/src/PAST/Grammar.tg =================================================================== --- languages/pynie/src/PAST/Grammar.tg (revision 17307) +++ languages/pynie/src/PAST/Grammar.tg (working copy) @@ -28,6 +28,12 @@ .return tree.'get'('past', $P0, $S0) } +transform past (Pynie::Grammar::compound_stmt) :language('PIR') { + $S0 = node.'find_key'() + $P0 = node[$S0] + $S0 = concat 'Pynie::Grammar::', $S0 + .return tree.'get'('past', $P0, $S0) +} transform past (Pynie::Grammar::stmt_list) :language('PIR') { .local pmc past @@ -203,10 +209,15 @@ transform past (Pynie::Grammar::expression) :language('PIR') { + $S0 = node.'find_key'() $P0 = node['or_test'] + if null $P0 goto lambda $P0 = $P0[0] # this is a hack, 'rule expression' has 1 or more <or_test>s, so it stores them in an array. Handle $P0[1] later. #printerr "pynie::grammar::expression\n" .return tree.'get'('past', $P0, 'Pynie::Grammar::or_test') + lambda: + $P0 = node['lambda'] + .return tree.'get'('past', $P0, 'Pynie::Grammar::lambda_form') } transform past (Pynie::Grammar::or_test) :language('PIR') { @@ -226,30 +237,94 @@ } transform past (Pynie::Grammar::and_test) :language('PIR') { - $P0 = node['not_test'] - $P0 = $P0[0] # this is a hack, 'rule expression' has 1 or more <or_test>s, so it stores them in an array. Handle $P0[1] later. - #printerr "pynie::grammar::and_test\n" - .return tree.'get'('past', $P0, 'Pynie::Grammar::not_test') + .local pmc past, iter, clist, cnode + clist = node['not_test'] + clist = clone clist + cnode = pop clist + past = tree.'get'('past', cnode, 'Pynie::Grammar::not_test') + unless clist goto end + clist_loop: + cnode = pop clist + $P0 = tree.'get'('past', cnode, 'Pynie::Grammar::not_test') + past = past.'new'('PAST::Op', $P0, past, 'node'=>node, 'pasttype'=>'if') + if clist goto clist_loop + end: + .return (past) } transform past (Pynie::Grammar::not_test) :language('PIR') { - $P0 = node['not_in_test'] - #printerr "pynie::grammar::not_test\n" - .return tree.'get'('past', $P0, 'Pynie::Grammar::not_in_test') + .local string key, fullkey + .local pmc cnode, past, notpast + + cnode = node['not_test'] + if null cnode goto do_in_test + notpast = tree.'get'('past', cnode, 'Pynie::Grammar::not_test') + + past = new 'PAST::Op' + past.'init'('node'=>cnode, 'pasttype'=>'pirop', 'pirop'=>'not') + past.'push'(notpast) + + .return (past) + + do_in_test: + cnode = node['in_test'] + past = tree.'get'('past', cnode, 'Pynie::Grammar::in_test') + .return (past) } -transform past (Pynie::Grammar::not_in_test) :language('PIR') { - $P0 = node['is_not_test'] - $P0 = $P0[0] # this is a hack, 'rule expression' has 1 or more <or_test>s, so it stores them in an array. Handle $P0[1] later. - #printerr "pynie::grammar::not_in_test\n" - .return tree.'get'('past', $P0, 'Pynie::Grammar::is_not_test') +transform past (Pynie::Grammar::in_test) :language('PIR') { + .local pmc past, iter, clist, cnode + clist = node['is_test'] + clist = clone clist + cnode = pop clist + past = tree.'get'('past', cnode, 'Pynie::Grammar::is_test') + unless clist goto end + clist_loop: + cnode = pop clist + $P0 = tree.'get'('past', cnode, 'Pynie::Grammar::is_test') + # + # FIX THIS; also check for "not" + # + past = past.'new'('PAST::Op', $P0, past, 'node'=>node, 'pasttype'=>'pirop', 'pirop'=>'IN (FIX)') + if clist goto clist_loop + end: + .return (past) } -transform past (Pynie::Grammar::is_not_test) :language('PIR') { - $P0 = node['comparison'] - $P0 = $P0[0] - $P0 = $P0['expr'] - #printerr "pynie::grammar::is_not_test\n" +transform past (Pynie::Grammar::is_test) :language('PIR') { + .local pmc past, iter, clist, cnode + .local int hasnot + + hasnot = 1 + # HACK: + # TODO: figure out how presence of "not" can be checked. + # then set flag for each iteration. + + clist = node['comparison'] + clist = clone clist + + cnode = pop clist + past = tree.'get'('past', cnode, 'Pynie::Grammar::comparison') + unless clist goto end + + clist_loop: + cnode = pop clist + $P0 = tree.'get'('past', cnode, 'Pynie::Grammar::comparison') + if hasnot == 0 goto do_issame + $S0 = "isntsame" + goto done + do_issame: + $S0 = "issame" + done: + past = past.'new'('PAST::Op', $P0, past, 'node'=>node, 'pasttype'=>'pirop', 'pirop'=>$S0) + if clist goto clist_loop + end: + .return (past) +} + + +transform past (Pynie::Grammar::comparison) :language('PIR') { + $P0 = node['expr'] .return tree.'get'('past', $P0, 'Pynie::Grammar::expr') } @@ -440,7 +515,7 @@ dec suitec elsenode = suitelist[suitec] elsepast = tree.'get'('past', elsenode, 'Pynie::Grammar::suite') - elsepast.'suitetype'('immediate') + #elsepast.'suitetype'('immediate') expr_suite_pair: ## each remaining suite is paired with an "if" (or "elsif") @@ -462,23 +537,30 @@ transform past (Pynie::Grammar::while_stmt) :language('PIR') { - # .local pmc past - # past = new 'PAST::Op' - # past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# while stmt not implemented') - # .return (past) - - .local pmc exprnode, stmtnode + .local pmc exprnode, stmtnode, suitenode exprnode = node['expression'] - stmtnode = node['suite'] - stmtnode = stmtnode[0] + suitenode = node['suite'] + stmtnode = suitenode[0] - .local pmc past, exprpast, stmtpast - past = new 'PAST::Op' - past.'init'('node'=>node, 'pasttype'=>'while') + .local pmc past, whilepast, exprpast, stmtpast + past = new 'PAST::Stmts' + past.'init'('node'=>node) + + whilepast = new 'PAST::Op' + whilepast.'init'('node'=>node, 'pasttype'=>'while') exprpast = tree.'get'('past', exprnode, 'Pynie::Grammar::expression') - past.'push'(exprpast) + whilepast.'push'(exprpast) stmtpast = tree.'get'('past', stmtnode, 'Pynie::Grammar::suite') + whilepast.'push'(stmtpast) + past.'push'(whilepast) + + stmtnode = suitenode[1] + if null stmtnode goto no_else + unless stmtnode goto no_else # check for .Undef # why does that happen? + stmtpast = tree.'get'('past', stmtnode, 'Pynie::Grammar::suite') past.'push'(stmtpast) + + no_else: .return (past) } @@ -526,93 +608,167 @@ } transform past (Pynie::Grammar::funcdef) :language('PIR') { + .local pmc past, decnode, fnamenode, plistnode, suitenode + decnode = node['decorators'] + fnamenode = node['funcname'] + plistnode = node['parameter_list'] + suitenode = node['suite'] .local pmc past past = new 'PAST::Block' - .local pmc decnode, fnamenode, plistnode, suitenode -# decnode = node['decorators'] - fnamenode = node['funcname'] -# plistnode = node['parameter_list'] -# suitenode = node['suite'] -# -# .local pmc past -# past = new 'PAST::Block' -# -# if null decnode goto skip_decorators -# # handle decorators -# #printerr "Function decorators not implemented!\n" -# exit 1 -# -# skip_decorators: + if null decnode goto skip_decorators + # handle decorators + printerr "Function decorators not implemented!\n" + skip_decorators: .local pmc fnamepast fnamepast = tree.'get'('past', fnamenode, 'Pynie::Grammar::funcname') -# -# if null plistnode goto skip_parameter_list -# #.local plistpast -# #plistpast = tree.'get'('past', plistnode, 'Pynie::Grammar::parameter_list') -# #printerr "Parameters not implemented!\n" -# exit 1 -# -# skip_parameter_list: -# .local pmc stmtpast -# stmtpast = tree.'get'('past', suitenode, 'Pynie::Grammar::suite') -# -# # FIX -# past.'init'('node'=>node, 'name'=>fnamepast) -# .local pmc past -# - past.'init'('node'=>node, 'name'=>fnamepast) + + printerr "function name: " + S0 = fnamepast['name'] + printerr S0 + printerr "\n" + + # handle parameters + if null plistnode goto function_body + .local pmc plistpast + plistpast = tree.'get'('past', plistnode, 'Pynie::Grammar::parameter_list') + #past.'push'(plistpast) + + function_body: + .local pmc stmtpast + stmtpast = tree.'get'('past', suitenode, 'Pynie::Grammar::suite') + + #past.'init'('node'=>node, 'name'=>fnamepast) .return (past) } + + transform past (Pynie::Grammar::funcname) :language('PIR') { $P0 = node['identifier'] .return tree.'get'('past', $P0, 'Pynie::Grammar::identifier') } +transform past (Pynie::Grammar::parameter_list) :language('PIR') { + .local pmc past, iter + past = new 'PAST::VarList' + $P0 = node['defparameter'] + past.'init'('node'=>$P0) + + $S0 = $P0.'find_key'() + #printerr $S0 + $P0 = $P0[$S0] + $P2 = tree.'get'('past', $P0, 'Pynie::Grammar::defparameter') + past.'push'($P2) + + # handle others later + + .return (past) +} + + +transform past (Pynie::Grammar::defparameter) :language('PIR') { + .local pmc past + past = new 'PAST::VarList' + $P0 = node[0] + past.'init'('node'=>$P0) + #$S0 = node.'find_key'() + #printerr $S0 + + .local pmc iter, parampast + iter = new .Iterator, node + iter_loop: + unless iter goto iter_end + + # get next object + $P1 = shift iter + + # what kind of parameter? + $S0 = $P1.'find_key'() + #printerr $S0 + #printerr "\n" + + # get that node + $P1 = $P1[$S0] + $S0 = concat 'Pynie::Grammar::', $S0 + parampast = tree.'get'('past', $P1, $S0) + past.'push'(parampast) + goto iter_loop + iter_end: + + + + .return (past) +} + +transform past (Pynie::Grammar::parameter) :language('PIR') { + .local pmc past + + + $P0 = node['identifier'] + if null $P0 goto sublist + $P1 = tree.'get'('past', $P0, 'Pynie::Grammar::identifier') + $S0 = $P1['name'] + + #printerr "parameter: " + #printerr $S0 + #printerr "\n" + + past = new 'PAST::Var' + past.'init'('node'=>$P0, 'scope'=>'parameter', 'name'=>$S0) + .return (past) + + sublist: + # TODO + +} + ## FIX: fix this, not sure about how to handle instructions such ## as subclass etc. ## transform past (Pynie::Grammar::classdef) :language('PIR') { .local pmc past - past = new 'PAST::Op' - past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# classdef stmt not implemented') + past = new 'PAST::Stmts' + past.'init'('node'=>node) + + #past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# classdef stmt not implemented') + #.return (past) + + .local pmc instr + instr = new 'PAST::Op' + + $P0 = node['inheritance'] + if null $P0 goto skip_inheritance + instr.'init'('node'=>node, 'pasttype'=>'pirop', 'pirop'=>'subclass') + # inheritancenot implemented right now + printerr "inheritance not implemented\n" + goto handle_class_body + + skip_inheritance: + instr.'init'('node'=>node, 'pasttype'=>'pirop', 'pirop'=>'newclass') + $P0 = node['identifier'] + $P1 = tree.'get'('past', $P0, 'Pynie::Grammar::identifier') + $S0 = $P1['name'] + $P2 = new 'PAST::Val' + $P2.'init'('node'=>$P1, 'ctype'=>'s', 'vtype'=>'.String', 'name'=>$S0) + instr.'push'($P2) + + handle_class_body: + # add newclass or subclass instruction to Stmts node + past.'push'(instr) + + # add a .namespace[ <class_id> ] instruction to add methods? + #$P1 = new 'PAST::Block' + + $P0 = node['suite'] + $P1 = tree.'get'('past', $P0, 'Pynie::Grammar::suite') + past.'push'($P1) + + done: .return (past) - -# .local pmc past -# past = new 'PAST::Stmts' -# past.'init'('node'=>node) -# -# .local pmc instr -# instr = new 'PAST::Op' -# -# $P0 = node['inheritance'] -# if null $P0 goto skip_inheritance -# instr.'init'('node'=>node, 'pasttype'=>'pirop', 'pirop'=>'subclass') -# # inheritancenot implemented right now -# goto handle_class_body -# -# skip_inheritance: -# instr.'init'('node'=>node, 'pasttype'=>'pirop', 'pirop'=>'newclass') -# $P0 = node['classname'] -# $P1 = tree.'get'('past', $P0, 'Pynie::Grammar::classname') -# instr.'push'($P1) -# -# handle_class_body: -# # add newclass or subclass instruction to Stmts node -# past.'push'(instr) -# -# # add a .namespace[ <class_id> ] instruction to add methods? -# $P0 = node['suite'] -# $P1 = tree.'get'('past', $P0, 'Pynie::Grammar::suite') -# past.'push'($P1) -# -# -# done: -# .return (past) } ## FIX: Return class name as a string, not using "get_global" as in identifier.