Greetings!

On Wed, 2010-12-15 at 21:03 -0800, Daniel Gonzalez wrote:
> I'm trying to write a grammar capable of parsing something like the
> following:
> $sum = number_1 * number_2 / (number_3 + $temp);
> 
> 
> From this, I want to generate this AST:
> (ASSIGN 
>     $sum
>     (MUL_OP 
>          number_1
>          (DIV_OP 
>              number_2
>              (ADD_OP 
>                  number_3
>                  $temp))))
> 
> 
> This is (the relevant part of) what I currently have -
> 
> 
> statement : assignment_expression ';'!;
> 
> 
> assignment_expression : variable '=' expression -> ^(ASSIGN variable
> expression);
> 
> 
> expression
> : mul_expression (add_operator mul_expression)? -> ^(add_operator
> mul_expression mul_expression?);
> 
> 
> mul_expression : term (mul_operator term)* -> ^(mul_operator term
> term*);
> 
> 
> term : '('! expression ')'! | variable | constant;
> 
> 
> add_operator : '+' -> ADD_OP | '-' -> SUB_OP;
> mul_operator : '*' -> MUL_OP | '/' -> DIV_OP;
> 
> 
> It's obviously very wrong. :) The main things I can't figure out are
> how to have chained operations (eg. a * b / c) that create new child
> nodes for each new operator (eg. (MUL a (DIV b c))), or how to
> properly support parenthesis. All my attempts have given me a grammar
> with mutual left-recursion that I can't seem to solve. There must be a
> clean and clear way to do this. :)

use the '^' suffix meta-operator.

like this (off the top of my head, untested):

assignment : variable ASSIGN^ expression ';'! ;

expression : factor ( (MUL_OP^ | DIV_OP^) factor )* ;
factor : term ( (ADD_OP^ | SUB_OP^) term )* ;
term : primary ;
primary : variable | constant | '('! expression ')'! ;

ASSIGN : '=' ;
MUL_OP : '*' ;
DIV_OP : '/' ;
ADD_OP : '+' ;
SUB_OP : '-' ;

note that in your use of imaginary tokens, those tokens will not be
initialized with any source text position information. so subsequent
generation of error messages when walking the tree will be more
difficult. so if you insist on using imaginary tokens perhaps because
those characters have other meanings in your language that you want to
differentiate then do something like this:

factor : term ( adding_operator^ term )* ;
adding_operator
   : op='+' -> ADD_OP["ADD_OP", $op]
   | op='-' -> SUB_OP["SUB_OP", $op]
 ;


hope this helps...
   -jbb



_______________________________________________
antlr-dev mailing list
[email protected]
http://www.antlr.org/mailman/listinfo/antlr-dev

Reply via email to