0
votes

I have a grammar that can parse expressions like 1+2-4 or 1+x-y, creating an appropriate structure on the fly which later, given a Map<String, Integer> with appropriate content, can be evaluated numerically (after parsing is complete, i.e. for x or y only known later).

Inside the grammar, there are also places where an expression that can be evaluated on the spot, i.e. does not contain variables, should occur. I figured I could parse these with the same logic, adding a boolean parameter variablesAllowed to the rule, like so:

grammar MiniExprParser;
INT : ('0'..'9')+;
ID : ('a'..'z'| 'A'..'Z')('a'..'z'| 'A'..'Z'| '0'..'9')*;
PLUS  : '+';
MINUS : '-';

numexpr returns [Double val]:
  expr[false] {$val = /* some evaluation code */ 0.;};

varexpr /*...*/:
  expr[true] {/*...*/};

expr[boolean varsAllowed] /*...*/:  
  e=atomNode[varsAllowed]  {/*...*/}
        (PLUS e2=atomNode[varsAllowed] {/*...*/}
        |MINUS e2=atomNode[varsAllowed] {/*...*/}
        )* ;

atomNode[boolean varsAllowed] /*...*/:
   (n=INT {/*...*/})
  |{varsAllowed}?=> ID {/*...*/}  
  ;

result: 
  (numexpr) => numexpr {System.out.println("Numeric result: " + $numexpr.val);}
 |varexpr {System.out.println("Variable expression: " + $varexpr.text);};

However, the generated Java code does not compile. In the part apparently responsible for the final rule's syntactic predicate, varsAllowed occurs even although the variable is never defined at this level.

        /* ... */
        else if ( (LA3_0==ID) && ((varsAllowed))) {
            int LA3_2 = input.LA(2);

            if ( ((synpred1_MiniExprParser()&&(varsAllowed))) ) {
                alt3=1;
            }
            else if ( ((varsAllowed)) ) {
                alt3=2;
            }
        /* ... */

Am I using it wrong? (I am using Eclipse' AntlrIDE 2.1.2 with Antlr 3.5.2.)

1
I'd recommend against writing actions. If you want to do optimizations, do an extra pass in the parse tree walker, maybe generating intermediate code. - Mephy

1 Answers

0
votes

This problem is part of the hoisting process the parser uses for prediction. I encountered the same problem and ended up with a member var (or static var for the C target) instead of a parameter.