hi,
attached a patch that adds the last few bits of the Python grammar.
Please note that there may be bugs, but I put in all rules, (not using
the optable, that one is commented out)
I had to put some things into comments in the ASTgrammar, the expression
stuff needs work.
I removed the left recursion as Pm suggested.
After this, it's time for cleanup and getting basic stuff (expresssions)
working again.
regards,
kjs
Index: languages/pynie/src/parser/Grammar.pg
===================================================================
--- languages/pynie/src/parser/Grammar.pg (revision 17192)
+++ languages/pynie/src/parser/Grammar.pg (working copy)
@@ -7,9 +7,7 @@
##
## These are a set of rules for parsing programs written in Python.
## Many of the rules are derived from the "Python Language Reference
-## Manual", version 2.5 by Guido van Rossum (Fred L. Drake, Jr., Editor).
-## Available online at http://docs.python.org/ref/ and
-## http://docs.python.org/ref/grammar.txt .
+## Manual", by Guido van Rossum (Fred L. Drake, Jr., Editor).
grammar Pynie::Grammar ;
@@ -25,8 +23,8 @@
token suite {
| <stmt_list> <?newline>
| <?newline> <?indent> <statement>
- [ <?indent_same> <statement> ]*
- [ <?dedent> | <?die: IndentationError: unindent does not match any outer indentation level> ]
+ [ <?indent_same> <statement> ]*
+ [ <?dedent> | <?die: IndentationError: unindent does not match any outer indentation level> ]
}
token statement {
@@ -96,15 +94,16 @@
<'@'> <dotted_name> [ <'('> [ <argument_list> <','>? ]? <')'> ]? <?newline>
}
+## FIX: this should be cleaned up.
rule argument_list {
- | <positional_arguments> [ <','> <keyword_arguments> ]?
- [ <','> <'*'> <expression> ]?
- [ <','> <'**'> <expression> ]?
+ <positional_arguments> [ <','> <keyword_arguments> ]?
+ [ <','> <'*'> <expression> ]?
+ [ <','> <'**'> <expression> ]?
| <keyword_arguments>
[ <','> <'*'> <expression> ]?
[ <','> <'**'> <expression> ]?
| <','> <'*'> <expression>
- [ <','> <'**'> <expression> ]?
+ [ <','> <'**'> <expression> ]?
| <','> <'**'> <expression>
}
@@ -130,7 +129,8 @@
rule parameter_list {
[ <defparameter> <','> ]*
- [ <'*'> <identifier> [ <','> <'**'> <identifier> ]?
+ [
+ <'*'> <identifier> [ <','> <'**'> <identifier> ]?
| <'**'> <identifier>
| <defparameter> <','>?
]
@@ -162,11 +162,11 @@
}
rule or_test {
- <and_test> | <or_test> <'or'> <and_test>
+ <and_test> [ <'or'> <and_test> ]*
}
rule and_test {
- <not_test> | <and_test> <'and'> <not_test>
+ <not_test> [ <'and'> <not_test> ]*
}
rule not_test {
@@ -210,52 +210,72 @@
rule target_list { <target> [ <','> <target> ]* <','>? }
rule target {
- | <identifier>
- | <'('> <target_list> <')'>
- | <'['> <target_list> <']'>
- | <attributeref>
+ | <identifier>
+ | <'('> <target_list> <')'>
+ | <'['> <target_list> <']'>
+ | <primary> <attributeref>
+ | <primary> <subscription>
+ | <primary> <slicing>
+}
+
+rule call {
+ | <'('> [ <argument_list>? <','>? ]? <')'>
+ | <'('> [ <argument_list> <','>? | <test> <genexpr_for> ] <')'>
+}
+
+rule primary {
+ <atom> <postop>*
+}
+
+rule postop {
+ | <attributeref>
| <subscription>
| <slicing>
+ | <call>
}
+rule atom {
+ <identifier> | <literal> | <enclosure>
+}
+
rule attributeref {
- <primary> <'.'> <identifier>
+ <'.'> <identifier>
}
rule subscription {
- <primary> <'['> <expression_list> <']'>
+ <'['> <expression_list> <']'>
}
rule slicing {
- <simple_slicing> | <extended_slicing>
+ <simple_slicing> | <extended_slicing>
}
rule simple_slicing {
- <primary> <'['> <short_slice> <']'>
+ <'['> <short_slice> <']'>
}
rule extended_slicing {
- <primary> <'['> <slice_list> <']'>
+ <'['> <slice_list> <']'>
}
rule slice_list {
- <slice_item> [ <','> <slice_item> ]* <','>?
+ <slice_item> [ <','> <slice_item> ]* <','>?
}
rule slice_item {
- <expression> | <proper_slice> | <'...'>
+ <expression> | <proper_slice> | <'...'>
}
rule proper_slice {
- <short_slice> | <long_slice>
+ <short_slice> | <long_slice>
}
rule short_slice {
- <expression>? <':'> <expression>?
+ <expression>? <':'> <expression>?
}
rule long_slice {
- <short_slice> <':'> <expression>?
+ <short_slice> <':'> <expression>?
}
token identifier { <!reserved> [ <?alpha> | <'_'> ] \w* }
@@ -334,10 +354,10 @@
| <imagnumber>
}
-token integer {
- | <[1..9]> \d* | <'0'>
- | <'0'> <[0..7]>+
- | <'0'> <[xX]> [ \d | <[a..f]> | <[A..F]> ]+
+token integer {
+ | <[1..9]> \d* | <'0'>
+ | <'0'> <[0..7]>+
+ | <'0'> <[xX]> [ \d | <[a..f]> | <[A..F]> ]+
}
token intpart { \d+ }
@@ -363,8 +383,8 @@
}
regex longstring {
- | """ ( [ \\ . | . ]* ) """
- | ''' ( [ \\ . | . ]* ) '''
+ | """ ( [ \\ . | <-["""]> ]* ) """
+ | ''' ( [ \\ . | <-[''']> ]* ) '''
}
@@ -376,32 +396,30 @@
rule list_display { <'['> <listmaker>? <']'> }
-rule listmaker {
- <expression>
- [ <list_for>
- | [ <','> <expression> ]* <','>?
- ]
+rule listmaker {
+ <expression> [ <list_for>
+ | [ <','> <expression> ]* <','>? ]
}
rule list_iter {
- <list_for> | <list_if>
+ <list_for> | <list_if>
}
rule list_for {
- <'for'> <expression_list> <'in'> <testlist>
- <list_iter>?
+ <'for'> <expression_list> <'in'> <testlist>
+ <list_iter>?
}
rule test {
- <or_test> | <lambda_form>
+ <or_test> | <lambda_form>
}
rule testlist {
- <test> [ <','> <test> ]* <','>?
+ <test> [ <','> <test> ]* <','>?
}
rule list_if {
- <'if'> <test> <list_iter>?
+ <'if'> <test> <list_iter>?
}
token augop {
@@ -409,145 +427,176 @@
| <'>>='> | <'<<='> | <'&='> | <'^='> | <'|='>
}
-
-rule call {
- <primary> <'('> [ <argument_list>? <','>? ]? <')'>
- # XXX
-}
-
-rule primary {
- | <atom>
- #| <attributeref>
- #| <subscription>
- #| <slicing>
- #| <call>
-}
-
-rule atom {
- <identifier> | <literal> | <enclosure>
-}
-
rule parenth_form {
- <'('> <expression_list>? <')'>
+ <'('> <expression_list>? <')'>
}
rule enclosure {
- | <parenth_form>
- | <list_display>
- | <generator_expression>
- | <dict_display>
- | <string_conversion>
+ | <parenth_form>
+ | <list_display>
+ | <generator_expression>
+ | <dict_display>
+ | <string_conversion>
}
rule generator_expression {
- <'('> <test> <genexpr_for> <')'>
+ <'('> <test> <genexpr_for> <')'>
}
rule genexpr_for {
- <'for'> <expression_list> <'in'> <test>
- <genexpr_iter>?
+ <'for'> <expression_list> <'in'> <test>
+ <genexpr_iter>?
}
rule genexpr_iter {
- <genexpr_for> | <genexpr_if>
+ <genexpr_for> | <genexpr_if>
}
rule genexpr_if {
- <'if'> <test> <genexpr_iter>?
+ <'if'> <test> <genexpr_iter>?
}
rule dict_display {
- <'{'> <key_datum_list>? <'}'>
+ <'{'> <key_datum_list>? <'}'>
}
rule key_datum_list {
- <key_datum> [ <','> <key_datum> ]* <','>?
+ <key_datum> [ <','> <key_datum> ]* <','>?
}
rule key_datum {
- <expression> <':'> <expression>
+ <expression> <':'> <expression>
}
rule string_conversion {
- <'`'> <expression_list> <'`'>
+ <'`'> <expression_list> <'`'>
}
-## This identifies operators for the bottom-up parser
-## See operator precedence table at http://docs.python.org/ref/summary.html
-token 'expression' is optable { ... }
+rule expression {
+ | <or_test> [ <'if'> <or_test> <'else'> <test> ]?
+ | <lambda_form>
+}
-proto 'term:' is precedence('=')
- is parsed(&term)
- { ... }
+rule power {
+ <primary> [ <'**'> <u_expr> ]?
+}
-# should this be primary??
-token term {
- | <literal>
- | <identifier>
- | <list_display>
+rule u_expr {
+ | <power>
+ | <'-'> <u_expr>
+ | <'+'> <u_expr>
+ | <'\~'> <u_expr>
}
-proto 'infix:**' is looser('term:') {...}
+rule m_expr {
+ <u_expr> [ [<'*'> | <'//'> | <'/'> | <'\%'> ] <u_expr> ]*
+}
-proto 'prefix:~' is looser('infix:**') { ... }
-proto 'prefix:+' is looser('prefix:~') { ... }
-proto 'prefix:-' is equiv('prefix:+') { ... }
+rule a_expr {
+ <m_expr> [ [ <'+'> | <'-'> ] <m_expr> ]*
+}
-proto 'infix:*' is looser('prefix:+')
- is pirop('mul')
- { ... }
+rule shift_expr {
+ <a_expr> [ [ <'<<'> | <'>>'> ] <a_expr> ]*
+}
-proto 'infix:/' is equiv('infix:*')
- is pirop('div')
- { ... }
+rule and_expr {
+ <shift_expr> [ <'&'> <shift_expr> ]*
+}
-proto 'infix:%' is equiv('infix:*')
- is pirop('mod')
- { ... }
+rule xor_expr {
+ <and_expr> [ <'^'> <and_expr> ]*
+}
+
+rule or_expr {
+ <xor_expr> [ <'|'> <xor_expr> ]*
+}
-proto 'infix:+' is looser('infix:*')
- is pirop('add')
- { ... }
+rule comparison {
+ <or_expr> [ <comp_operator> <or_expr> ]*
+}
+
+rule comp_operator {
+ <'<'> | <'>'> | <'=='> | <'>='> | <'<='> | <'<>'> | <'!='> | <'is'> <'not'>? | <'not'>? <'in'>
+}
-proto 'infix:-' is equiv('infix:+')
- is pirop('sub')
- { ... }
-
-
-
-proto 'infix:<<' is looser('infix:+') { ... }
-proto 'infix:>>' is equiv('infix:<<') { ... }
-proto 'infix:&' is looser('infix:<<') { ... }
-proto 'infix:^' is looser('infix:&') { ... }
-proto 'infix:|' is looser('infix:^') { ... }
-
-proto 'infix:==' is looser('infix:|') { ... }
-proto 'infix:!=' is equiv('infix:==') { ... }
-proto 'infix:<=' is equiv('infix:==') { ... }
-proto 'infix:>=' is equiv('infix:==') { ... }
-proto 'infix:<' is equiv('infix:==') { ... }
-proto 'infix:>' is equiv('infix:==') { ... }
-
-# "is not" infix operator is handled by combining 'prefix:not' and 'infix:is'
-proto 'infix:is' is looser('infix:==') { ... }
-proto 'infix:in' is looser('infix:is') { ... }
-
-proto 'prefix:not' is looser('infix:in') { ... }
-
-# to handle "not in" as infix op, combine 'prefix:in' and 'infix:not'
-# this also allows for "x = 1 not 2", which is of course Wrong.
-# Fix this later (new category of operator??)
+### This identifies operators for the bottom-up parser
+### See operator precedence table at http://docs.python.org/ref/summary.html
#
-proto 'infix:not' is looser('infix:in') { ... }
-proto 'prefix:in' is looser('infix:is') { ... }
+#token 'expression' is optable { ... }
+#
+#proto 'term:' is precedence('=')
+# is parsed(&term)
+# { ... }
+#
+## should this be primary??
+#token term {
+# | <literal>
+# | <identifier>
+# | <list_display>
+#}
+#
+#proto 'infix:**' is looser('term:') {...}
+#
+#proto 'prefix:~' is looser('infix:**') { ... }
+#proto 'prefix:+' is looser('prefix:~') { ... }
+#proto 'prefix:-' is equiv('prefix:+') { ... }
+#
+#proto 'infix:*' is looser('prefix:+')
+# is pirop('mul')
+# { ... }
+#
+#proto 'infix:/' is equiv('infix:*')
+# is pirop('div')
+# { ... }
+#
+#proto 'infix:%' is equiv('infix:*')
+# is pirop('mod')
+# { ... }
+#
+#proto 'infix:+' is looser('infix:*')
+# is pirop('add')
+# { ... }
+#
+#proto 'infix:-' is equiv('infix:+')
+# is pirop('sub')
+# { ... }
+#
+#
+#
+#proto 'infix:<<' is looser('infix:+') { ... }
+#proto 'infix:>>' is equiv('infix:<<') { ... }
+#proto 'infix:&' is looser('infix:<<') { ... }
+#proto 'infix:^' is looser('infix:&') { ... }
+#proto 'infix:|' is looser('infix:^') { ... }
+#
+#proto 'infix:==' is looser('infix:|') { ... }
+#proto 'infix:!=' is equiv('infix:==') { ... }
+#proto 'infix:<=' is equiv('infix:==') { ... }
+#proto 'infix:>=' is equiv('infix:==') { ... }
+#proto 'infix:<' is equiv('infix:==') { ... }
+#proto 'infix:>' is equiv('infix:==') { ... }
+#
+## "is not" infix operator is handled by combining 'prefix:not' and 'infix:is'
+#proto 'infix:is' is looser('infix:==') { ... }
+#proto 'infix:in' is looser('infix:is') { ... }
+#
+#proto 'prefix:not' is looser('infix:in') { ... }
+#
+## to handle "not in" as infix op, combine 'prefix:in' and 'infix:not'
+## this also allows for "x = 1 not 2", which is of course Wrong.
+## Fix this later (new category of operator??)
+##
+#proto 'infix:not' is looser('infix:in') { ... }
+#proto 'prefix:in' is looser('infix:is') { ... }
+#
+#proto 'infix:and' is looser('prefix:not') { ... }
+#proto 'infix:or' is looser('infix:and') { ... }
-proto 'infix:and' is looser('prefix:not') { ... }
-proto 'infix:or' is looser('infix:and') { ... }
-
## Python reserved words and keywords
token reserved {
Index: languages/pynie/src/PAST/Grammar.tg
===================================================================
--- languages/pynie/src/PAST/Grammar.tg (revision 17192)
+++ languages/pynie/src/PAST/Grammar.tg (working copy)
@@ -28,12 +28,33 @@
compound_stmt:
$P0 = node['compound_stmt']
+ if_stmt:
$P1 = $P0['if_stmt']
if null $P1 goto while_stmt
.return tree.'get'('past', $P1, 'Pynie::Grammar::if_stmt')
while_stmt:
$P1 = $P0['while_stmt']
+ if null $P1 goto for_stmt
.return tree.'get'('past', $P1, 'Pynie::Grammar::while_stmt')
+ for_stmt:
+ $P1 = $P0['for_stmt']
+ if null $P1 goto try_stmt
+ .return tree.'get'('past', $P1, 'Pynie::Grammar::for_stmt')
+ try_stmt:
+ $P1 = $P0['try_stmt']
+ if null $P1 goto with_stmt
+ .return tree.'get'('past', $P1, 'Pynie::Grammar::try_stmt')
+ with_stmt:
+ $P1 = $P0['with_stmt']
+ if null $P1 goto funcdef
+ .return tree.'get'('past', $P1, 'Pynie::Grammar::with_stmt')
+ funcdef:
+ $P1 = $P0['funcdef']
+ if null $P1 goto classdef
+ .return tree.'get'('past', $P1, 'Pynie::Grammar::funcdef')
+ classdef:
+ $P1 = $P0['classdef']
+ .return tree.'get'('past', $P1, 'Pynie::Grammar::classdef')
}
@@ -68,7 +89,98 @@
.return tree.'get'('past', cnode, key)
}
+transform past (Pynie::Grammar::assert_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+## From http://docs.python.org/ref/assert.html
+## The simple form, "assert expression", is equivalent to
+##
+##if __debug__:
+## if not expression: raise AssertionError
+##
+##The extended form, "assert expression1, expression2", is equivalent to
+##
+##if __debug__:
+## if not expression1: raise AssertionError, expression2
+##
+ #past.'init'('node'=>node, 'pasttype'=>'if')
+ #$P0 = node['expression']
+
+
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# assert_stmt not implemented')
+ .return (past)
+
+}
+
+transform past (Pynie::Grammar::augmented_assignment_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# augmented assignment stmt not implemented')
+ .return (past)
+}
+
+transform past (Pynie::Grammar::del_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# del stmt not implemented')
+ .return (past)
+}
+
+# Handle "pass" statement; only emit a comment
+# Alternative would be to _not_ create a PAST node, but then
+# extra logic would be necessary in both stmt_list() and simple_stmt().
+#
+transform past (Pynie::Grammar::pass_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# pass')
+ .return (past)
+}
+
+transform past (Pynie::Grammar::return_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'pirop', 'pirop'=>'return')
+ $P0 = node['expression_list']
+
+## FIX:
+## Returning something does not work; 'method 'from' not found...
+ if null $P0 goto skip_expression_list
+ .local pmc expr_list_past
+ expr_list_past = tree.'get'('past', $P0, 'Pynie::Grammar::expression_list')
+ past.'push'(expr_list_past)
+ skip_expression_list:
+ .return (past)
+}
+
+## FIX:
+## generated code is nonsense for yield_stmt
+transform past (Pynie::Grammar::yield_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'pirop', 'pirop'=>'yield')
+ $P0 = node['expression_list']
+ .local pmc expr_list_past
+ expr_list_past = tree.'get'('past', $P0, 'Pynie::Grammar::expression_list')
+ past.'push'(expr_list_past)
+ .return (past)
+}
+
+transform past (Pynie::Grammar::break_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# break not implemented')
+ .return (past)
+}
+
+transform past (Pynie::Grammar::continue_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# continue not implemented')
+ .return (past)
+}
+
transform past (Pynie::Grammar::print_stmt) :language('PIR') {
.local pmc past
past = new 'PAST::Op'
@@ -94,7 +206,29 @@
.return (past)
}
+transform past (Pynie::Grammar::import_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# import stmt not implemented')
+ .return (past)
+}
+transform past (Pynie::Grammar::raise_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# raise stmt not implemented')
+ .return (past)
+}
+
+transform past (Pynie::Grammar::global_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# global stmt not implemented')
+ .return (past)
+}
+
+
+
transform past (Pynie::Grammar::expression) :language('PIR') {
$P0 = node['expr']
.return tree.'get'('past', $P0, 'Pynie::Grammar::expr')
@@ -102,41 +236,45 @@
transform past (Pynie::Grammar::expr) :language('PIR') {
- .local string type
- type = node['type']
- if type == 'term:' goto past_term
-
- .local pmc optable, optok
- .local string pasttype, pirop, returns
- .local int islvalue
- optable = get_hll_global [ 'Pynie::Grammar' ], '$optable'
- optok = optable[type]
- pasttype = optok['past']
- pirop = optok['pirop']
- returns = optok['returns']
- islvalue = optok['lvalue']
-
- .local pmc past, iter
- past = new 'PAST::Op'
- past.'init'('node'=>node, 'name'=>type, 'pasttype'=>pasttype, 'pirop'=>pirop, 'returns'=>returns)
-
- $P0 = node.'get_array'()
- if null $P0 goto iter_end
- iter = new .Iterator, $P0
- unless iter goto iter_end
- $P0[0;'islvalue'] = islvalue
- iter_loop:
- .local pmc cnode, cpast
- cnode = shift iter
- cpast = tree.'get'('past', cnode, 'Pynie::Grammar::expr')
- if null cpast goto iter_loop
- past.'push'(cpast)
- if iter goto iter_loop
- iter_end:
- .return (past)
-
- past_term:
- .return tree.'get'('past_term', node, 'Pynie::Grammar::expr')
+ .local pmc past
+ past = new 'PAST::Val'
+ past.'init'('node'=>node, 'vtype'=>'.Undef')
+ .return (past)
+ # .local string type
+ # type = node['type']
+ # if type == 'term:' goto past_term
+ #
+ # .local pmc optable, optok
+ # .local string pasttype, pirop, returns
+ # .local int islvalue
+ # optable = get_hll_global [ 'Pynie::Grammar' ], '$optable'
+ # optok = optable[type]
+ # pasttype = optok['past']
+ # pirop = optok['pirop']
+ # returns = optok['returns']
+ # islvalue = optok['lvalue']
+ #
+ # .local pmc past, iter
+ # past = new 'PAST::Op'
+ # past.'init'('node'=>node, 'name'=>type, 'pasttype'=>pasttype, 'pirop'=>pirop, 'returns'=>returns)
+ #
+ # $P0 = node.'get_array'()
+ # if null $P0 goto iter_end
+ # iter = new .Iterator, $P0
+ # unless iter goto iter_end
+ # $P0[0;'islvalue'] = islvalue
+ #iter_loop:
+ # .local pmc cnode, cpast
+ # cnode = shift iter
+ # cpast = tree.'get'('past', cnode, 'Pynie::Grammar::expr')
+ # if null cpast goto iter_loop
+ # past.'push'(cpast)
+ # if iter goto iter_loop
+ #iter_end:
+ # .return (past)
+ #
+ #past_term:
+ # .return tree.'get'('past_term', node, 'Pynie::Grammar::expr')
}
@@ -297,23 +435,170 @@
transform past (Pynie::Grammar::while_stmt) :language('PIR') {
- .local pmc exprnode, stmtnode
- exprnode = node['expression']
- stmtnode = node['suite']
- stmtnode = stmtnode[0]
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# while stmt not implemented')
+ .return (past)
- .local pmc past, exprpast, stmtpast
+ # .local pmc exprnode, stmtnode
+ # exprnode = node['expression']
+ # stmtnode = node['suite']
+ # stmtnode = stmtnode[0]
+ #
+ # .local pmc past, exprpast, stmtpast
+ # past = new 'PAST::Op'
+ # past.'init'('node'=>node, 'pasttype'=>'while')
+ # exprpast = tree.'get'('past', exprnode, 'Pynie::Grammar::expression')
+ # past.'push'(exprpast)
+ # stmtpast = tree.'get'('past', stmtnode, 'Pynie::Grammar::suite')
+ # past.'push'(stmtpast)
+ # .return (past)
+}
+
+## FIX: complete this
+transform past (Pynie::Grammar::for_stmt) :language('PIR') {
+
+ .local pmc past
past = new 'PAST::Op'
- past.'init'('node'=>node, 'pasttype'=>'while')
- exprpast = tree.'get'('past', exprnode, 'Pynie::Grammar::expression')
- past.'push'(exprpast)
- stmtpast = tree.'get'('past', stmtnode, 'Pynie::Grammar::suite')
- past.'push'(stmtpast)
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# for stmt not implemented')
.return (past)
+
+# .local pmc tlistnode, elistnode, suitenode
+# tlistnode = node['target_list']
+# elistnode = node['expression_list']
+# suitenode = node['suite']
+#
+# .local pmc past, tlistpast, elistpast, suitepast
+# past = new 'PAST::Op'
+# past.'init'('node'=>node, 'pasttype'=>'while')
+#
+# tlistpast = tree.'get'('past', tlistnode, 'Pynie::Grammar::target_list')
+# #past.'push'(tlistpast)
+#
+# elistpast = tree.'get'('past', elistnode, 'Pynie::Grammar::expression_list')
+# past.'push'(elistpast)
+#
+# suitepast = tree.'get'('past', suitenode, 'Pynie::Grammar::suite')
+# past.'push'(suitepast)
+#
+# .return (past)
}
+transform past (Pynie::Grammar::try_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# try stmt not implemented')
+ .return (past)
+}
+transform past (Pynie::Grammar::with_stmt) :language('PIR') {
+ .local pmc past
+ past = new 'PAST::Op'
+ past.'init'('node'=>node, 'pasttype'=>'inline', 'inline'=>'# with stmt not implemented')
+ .return (past)
+}
+transform past (Pynie::Grammar::funcdef) :language('PIR') {
+
+ .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:
+ .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)
+ .return (past)
+}
+
+transform past (Pynie::Grammar::funcname) :language('PIR') {
+ $P0 = node['identifier']
+ .return tree.'get'('past', $P0, 'Pynie::Grammar::identifier')
+}
+
+
+## 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')
+ .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.
+transform past (Pynie::Grammar::classname) :language('PIR') {
+ $P0 = node['identifier']
+ .return tree.'get'('past', $P0, 'Pynie::Grammar::identifier')
+}
+
+transform past (Pynie::Grammar::inheritance) :language('PIR') {
+ $P0 = node['expression_list']
+ .return tree.'get'('past', $P0, 'Pynie::Grammar::expression_list')
+}
+
transform past (Pynie::Grammar::suite) :language('PIR') {
$P0 = node['stmt_list']
if null $P0 goto statements