I'm creating a grammar for a subset of Java, and seem to be running into an issue in which my grammar is considered ambiguous by ANTLR (or well, I think that's the reasoning behind the error at least).
Here is the relevant portion of my grammar:
expr : (op=MINUS | op=NOT) expr exprPrime -> ^(Expr $op expr exprPrime)
| NEW ID OPEN_PAREN CLOSE_PAREN exprPrime -> ^(Expr NEW ID OPEN_PAREN CLOSE_PAREN exprPrime)
| ID exprPrime -> ^(Expr ID exprPrime)
| THIS exprPrime -> ^(Expr THIS exprPrime)
| INTEGER exprPrime -> ^(Expr INTEGER exprPrime)
| NULL exprPrime -> ^(Expr NULL exprPrime)
| TRUE exprPrime -> ^(Expr TRUE exprPrime)
| FALSE exprPrime -> ^(Expr FALSE exprPrime)
| OPEN_PAREN expr CLOSE_PAREN exprPrime -> ^(Expr OPEN_PAREN expr CLOSE_PAREN exprPrime)
;
// remove left recursion via exprPrime
exprPrime : (op=PLUS | op=MINUS | op=MULT | op=DIV | op=LT | op=LEQ | op=GT | op=GEQ | op=EQ | op=NEQ | op=AND | op=OR | op=NOT) expr exprPrime
-> ^(ExprPrime $op expr exprPrime)
| DOT ID OPEN_PAREN (expr (COMMA expr)*)? CLOSE_PAREN exprPrime
-> ^(ExprPrime DOT ID OPEN_PAREN (expr (COMMA expr)*)? CLOSE_PAREN exprPrime)
|
-> ^(Epsilon)
;
/*------------------------------------------------------------------
* LEXER RULES
*------------------------------------------------------------------*/
CLASS : 'class' ;
PUBLIC : 'public' ;
STATIC : 'static' ;
EXTENDS : 'extends' ;
NEW : 'new' ;
THIS : 'this' ;
NULL : 'null' ;
IF : 'if' ;
ELSE : 'else' ;
WHILE : 'while' ;
MAIN : 'main' ;
TRUE : 'true' ;
FALSE : 'false' ;
RETURN : 'return' ;
SYSO : 'System.out.println' ;
OPEN_BRACKET : '{' ;
CLOSE_BRACKET : '}' ;
OPEN_SQUARE : '[' ;
CLOSE_SQUARE : ']' ;
OPEN_PAREN : '(' ;
CLOSE_PAREN : ')' ;
ASSIGN : '=' ;
COMMA : ',' ;
DOT : '.' ;
SEMICOLON : ';' ;
STRING_TYPE : 'String' ;
INTEGER_TYPE : 'int' ;
VOID_TYPE : 'void' ;
BOOLEAN_TYPE : 'boolean' ;
PLUS : '+' ;
MINUS : '-' ;
MULT : '*' ;
DIV : '/' ;
LT : '<' ;
LEQ : '<=' ;
GT : '>' ;
GEQ : '>=' ;
EQ : '==' ;
NEQ : '!=' ;
AND : '&&' ;
OR : '||' ;
NOT : '!' ;
ID : LETTER (LETTER | DIGIT)* ;
INTEGER : (NON_ZERO_DIGIT DIGIT*) | ZERO ;
WHITESPACE : ('\t' | ' ' | '\r' | '\n'| '\u000C')+ { $channel = HIDDEN; } ;
COMMENT : (('/*' .* '*/') | ('//' .* '\n')) { $channel = HIDDEN; } ;
fragment ZERO : '0' ;
fragment DIGIT : '0'..'9' ;
fragment NON_ZERO_DIGIT : '1'..'9' ;
fragment LETTER : 'a'..'z' | 'A'..'Z' ;
And here is the error I get when creating my grammar:
warning(200): MiniJava.g:101:11: Decision can match input such as "NEQ" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "EQ" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "MULT" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "DIV" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "GEQ" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "NOT" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "LT" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "LEQ" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "DOT" using multiple alternatives: 2, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "OR" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "PLUS" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "AND" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "MINUS" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
warning(200): MiniJava.g:101:11: Decision can match input such as "GT" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input
The line numbers all point to the line with exprPrime's definition (I left out most of the gramar above it for brevity, let me know if I need to post more of it). The exprPrime itself was created to avoid left recursion in 'expr'.
Any idea how I can change my grammar to remove the ambiguities? I'm not sure I even understand what the ambiguities are.
