# 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.