Author: pmichaud
Date: Fri May 11 08:39:17 2007
New Revision: 18505
Added:
trunk/languages/abc/src/abc-2.pg
- copied, changed from r18504, /trunk/languages/abc/src/abc.pg
Log:
[abc]:
* Initial draft of grammar that builds AST during parsing, instead
of a separate TGE grammar.
Copied: trunk/languages/abc/src/abc-2.pg (from r18504,
/trunk/languages/abc/src/abc.pg)
==============================================================================
--- /trunk/languages/abc/src/abc.pg (original)
+++ trunk/languages/abc/src/abc-2.pg Fri May 11 08:39:17 2007
@@ -1,19 +1,51 @@
grammar ABC::Grammar;
## an example 'bc' grammar
+## This version uses a Perl 6 subset to build the abstract
+## syntax tree as the program is being parsed, instead of a separate
+## parse->PAST step in TGE. It's still incomplete:
+## - build PAST from operator precedence parser
+## - handle lvalue contexts
+## It won't even parse yet, so don't try. :-)
-token TOP { <program> }
+token TOP { <program> { return $<program> }; }
## recognize terms
-token term {
- | $<float>:=[ \d+\.\d* | \.\d+ ]
- | $<integer>:=[\d+]
- | $<ident>:=[<[a..z]><[_a..z0..9]>*]
- [ $<array>:=[ \[ <expression> \] ]
- | $<call>:=[ \( <expression> \) ]
- ]?
+token float {
+ \d+ '.' \d* | '.' \d+
+ { return PAST::Val.new( :node($/), :vtype('.Float'), :name($/); }
}
+token integer {
+ \d+
+ { return PAST::Val.new( :node($/), :vtype('.Integer'), :name($/); }
+}
+
+## FIXME: still need to handle lvalue variables
+token variable {
+ <[a..z]><[_a..z0..9]>*
+ { return PAST::Var.new( :node($/), :name($/), :viviself('.Integer'); }
+}
+
+## FIXME: still need to handle lvalue array
+token term {
+ | <float> { return $<float>; }
+ | <integer> { return $<integer>; }
+ | <variable>
+ [ '[' <expression> ']'
+ { return PAST::Var( $<variable>, $<expression>,
+ :node($/),
+ :name($<variable>.text ~ '_array'),
+ :viviself('.Integer') ); }
+ | '(' <expression> ')'
+ { return PAST::Op( $<expression>
+ :node($/),
+ :name($<variable>.text),
+ :pasttype('call') ); }
+ | <null> { return $<variable>; }
+ ]
+}
+
## Standalone strings do not handle backslashed caracters.
## However, when a string is passed to 'print', special chars are handled.
token string { <-["]>* }
@@ -24,31 +56,64 @@
print [ <string> | <expression> ] [ , [ <string> | <expression> ] ]*
}
-rule compound_statement { \{ <statement_list> \} }
-rule if_statement { if \( <expression> \) <statement> [ else <statement> ]? }
-rule while_statement { while \( <expression> \) <statement> }
+rule compound_statement {
+ '{' <statement_list> '}' { return $<statement_list>; }
+}
+
+rule if_statement {
+ 'if' '(' <expression> ')' <statement>
+ [ 'else' <statement> ]?
+ { $x = PAST::Op.new( $<expression>, $<statement>[0],
+ :node($/), :pasttype('if') );
+ if ($<statement>[1]) { $x.push($<statement>[1]); }
+ return $x;
+ }
+}
+
+rule while_statement {
+ 'while' '(' <expression> ')' <statement>
+ { return PAST::Op.new( $<expression>, $<statement>,
+ :node($/), :pasttype('while') );
+ }
+}
+
rule for_statement {
- for \( <expression> ; <expression> ; <expression> \) <statement>
+ 'for' '(' <expression> ; <expression> ; <expression> ')' <statement>
+ { $iter = PAST::Stmts.new( $<statement>, $<expression>[2] );
+ $loop = PAST::Op.new( $<expression>[1], $iter, :pasttype('while') );
+ return PAST::Stmts.new( $<expression>[0], $loop );
+ }
}
+
rule statement {
- | <if_statement>
- | <while_statement>
- | <for_statement>
- | <compound_statement>
+ | <if_statement> { return $<if_statement> ; }
+ | <while_statement> { return $<while_statement>; }
+ | <for_statement> { return $<for_statement>; }
+ | <compound_statement> { return $<compound_statement>; }
| \" <string> \"
| break
| continue
| halt
| return [ \( <expression> \) ]?
- | <expression>
+ | <expression> { return $<expression>; }
}
-rule statement_list { <statement>? [ ; <statement>? ]* }
-rule program { ^ <statement_list> [ $ | <die: parse error> ] }
-rule pseudo_statement { limits | quit | warranty }
+rule statement_list {
+ <statement>? [ ; <statement>? ]*
+ { $stmts = PAST::Stmts.new( :node($/) );
+ for @$<statement> { $stmts.push( $_ ); }
+ return $stmts;
+ }
+}
+rule program {
+ ^ <statement_list> [ $ | <die: parse error> ]
+ { return PAST::Block.new( :node($/), $<statement_list> ); }
+}
+rule pseudo_statement { limits | quit | warranty }
+## FIXME : still don't handle $<expression> as PAST
## create operator precedence parser
rule 'expression' is optable { ... }