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 { ... }
 

Reply via email to