[antlr-interest] Precedence problem

Todd O'Bryan toddobryan at gmail.com
Thu Oct 30 10:05:44 PDT 2008


I've assigned my high school programming students a symbolic algebra
project and provided them an ANTLR parser so they could translate
Strings to values easily. I used an AST, so the translation is pretty
easy. The basic idea is a mapping like this:

"sin(x ^ 2)" --> new Sin(new Exp(new Var(), new Number(2.0))

Everything was working great, until... I wanted exponentiation to have
higher precedence than unary operators, so

"~x^3" ---> new Neg(new Exp(new Var(), new Number(2.0)))
"sin x ^ 2" ---> new Sin(new Exp(new Var(), new Number(2.0)))

But a student tried this:

"sin(x) ^ 2"

Clearly this SHOULD be new Exp(new Sin(new Var()), new Number(2.0)),
but since ^ has higher precedence than sin, it doesn't work.

I can't figure out how to fix it, however, because sin(...) should
have the same precedence as a parenthesized expression (higher than
^), but sin ... should have lower precedence. I tried a syntactic
predicate, but since the sin rule is in two rules, I can't get rid of
the ambiguity. Here's my grammar that doesn't work. Can anybody help?

grammar Expression;
options {
  output = AST;
  ASTLabelType=CommonTree;
}

expr : addExpr EOF!
  ;

addExpr : multExpr (('+'^|'-'^) multExpr)*
  ;

multExpr : unaryExpr (('*'^|'/'^) unaryExpr)*
  ;

unaryExpr : ('sin'^|'cos'^|'ln'^|'~'^) expExpr
  | expExpr
  ;

expExpr : atom ('^'^ atom)*
  ;

parenExpr : ('sin'^|'cos'^|'ln'^|'~'^)? '('! addExpr ')'!
  ;

atom : parenExpr
  | NUMBER
  | VAR
  ;

NUMBER : '-'? '0'..'9'+ ('.' '0'..'9'*)? ;
VAR : 'x' ;
WHITESPACE : (' '|'\t'|'\n'|'\r')+ { skip(); } ;


More information about the antlr-interest mailing list