I'm trying to create a simple expression parser with antlr 2.7.6 and am getting some nondeterminism warnings during compilation. The generated java source seems to work exactly as i want it, but I would like to know if its possible to suppress this warnings or if I'm doing something wrong in the grammar.
The parser is to be used in a project that already has a dependency on this old antlr version, so upgrading to 3.4 is probably not an option. The grammar itself look similar to the one in this answer.
Here is the output during compilation:
Using Antlr grammar: expr.g
ANTLR Parser Generator Version 2.7.6 (2005-12-22) 1989-2005
expr.g:15: warning:nondeterminism upon
expr.g:15: k==1:OR
expr.g:15: between alt 1 and exit branch of block
expr.g:19: warning:nondeterminism upon
expr.g:19: k==1:AND
expr.g:19: between alt 1 and exit branch of block
And here is the simplified grammar exhibiting the problem:
header {
package net.jhorstmann.i18n.tools;
import net.jhorstmann.i18n.tools.*;
import net.jhorstmann.i18n.tools.expr.*;
}
class ExprParser extends Parser;
expression returns [Expression r = null]
: r=or_expr
;
or_expr returns [Expression r = null] { Expression e = null; }
: r=and_expr (OR e=and_expr { r = new OrExpression(r, e); })*
;
and_expr returns [Expression r = null] { Expression e = null; }
: r=prim_expr (AND e=prim_expr { r = new AndExpression(r, e); })*
;
prim_expr returns [Expression r = null] { Expression e = null; }
: b:BOOL { r = new ConstantExpression(Integer.parseInt(b.getText())); }
| NOT e=expression { r = new NotExpression(e); }
| OPEN e=expression CLOSE { r = e; }
;
class ExprLexer extends Lexer;
options {
k=2;
}
WS : (' ' | '\t')+ { $setType(Token.SKIP); };
BOOL : '0' | '1';
NOT : '!';
OPEN : '(';
CLOSE : ')';
OR : '|' '|';
AND : '&' '&';
Odd, ANTLR 3 has no problems with such a grammar.
Because its warning about an "exit branch of block", try anchoring your entry rule with an end-of-file token (EOF
):
expression returns [Expression r = null]
: r=or_expr EOF
;
I'd include an unary negate-expression like this:
expression
: or_expr EOF
;
or_expr
: and_expr (OR and_expr)*
;
and_expr
: unary_expr (AND unary_expr)*
;
unary_expr
: NOT prim_expr
| prim_expr
;
prim_expr
: BOOL
| OPEN or_expr CLOSE
;