My grammar is
grammar Interpreter;
conditionalOrExpression : relationalRestriction ( OR relationalRestriction )* ;
relationalRestriction : primary ( orRestriction )* ;
orRestriction : singleRestriction (OR annotation? singleRestriction)* ;
singleRestriction : operator primary ;
operator : EQUALS
| { _input.LT(1).getText().equals("customOperator") }? ID // check custom operators using java util method
;
primary : INT
| ID
| '(' ID ')'
| ID '(' ID ')'
;
annotation : AT ID ;
OR : '||';
ID : [a-zA-Z]+;
INT : '0'..'9'+;
EQUALS : '==';
AT : '@';
WS : [ trn]+ -> skip;
(Sorry that the rules are not intuitive and not simplified well, but it required to reproduce the issue. The whole example is https://github.com/tkobayas/antlr-semantic-predicate-recovery)
Input is a == 5 || notCustomOperator(b) == 6
. I expect that notCustomOperator
results in false
in the semantic predicate in operator
rule, so it creates relationalRestriction a == 5
and relationalRestriction notCustomOperator(b) == 6
connected by OR ||
under conditionalOrExpression.
However, it results in line 1:10 no viable alternative at input 'notCustomOperator'
and it doesn’t take the alternative I expect above.
I read The prediction process also can't see through token references. Token references have the side effect of advancing the input one symbol. A predicate that tested the current input symbol would find itself out of sync if the parser shifted it over the token reference.
in https://github.com/antlr/antlr4/blob/master/doc/predicates.md#finding-visible-predicates (and read other similar SO threads), but with a debugger, I actually see that the semantic predicate (operator_sempred()
) is executed in ParserATNSimulator.adaptivePredict()
in InterpreterParser.orRestriction()
. The semantic predicate expectedly returns false and throws NoViableAltException, then it goes to DefaultErrorStrategy.recover()
. I expect that it continues to look for alternatives, but a problem is that _input.p
is not rewound to ||
, so the current token is notCustomOperator
, so it cannot match the expected alternative.
That said… probably my expectation was wrong and I have to rewrite the grammar. But I want to confirm if this is a designed behavior (= we cannot rely on semantic predicate for prediction in this case), because the semantic predicate is executed in contradiction to the documentation.