senleft
senleft

Reputation: 511

ANTLR 4: no viable alternative if predicate used

input

(001)

grammar G;

message
    : '(' seqnum ')'
    ;

seqnum
locals [int i = 0;]
    : ( {$i == 3}? DIGIT {$i++;} )+
    ;

DIGIT
    : [0-9]
    ;

Rule message produce no viable alternative:

[@0,0:0='(',<2>,1:0]
[@1,1:1='0',<3>,1:1]
[@2,2:2='0',<3>,1:2]
[@3,3:3='1',<3>,1:3]
[@4,4:4=')',<1>,1:4]
[@5,5:4='<EOF>',<-1>,1:5]
line 1:1 no viable alternative at input '0'

If rewrite rule 'message' as

message
    : '(' DIGIT DIGIT DIGIT ')'
    ;

It solves the problem. Why I get the error in the first case?

Upvotes: 0

Views: 343

Answers (1)

Sam Harwell
Sam Harwell

Reputation: 100039

Your predicate says "only match the following if i is exactly 3". Since i is initially 0, the predicate means no DIGIT will ever be matched.

A general rule in ANTLR is to only use predicates when absolutely necessary, as they can impose significant performance overhead and are difficult to debug when something goes wrong.

Edit: Your predicate is the equivalent of the following in Java:

for (int i = 0; i == 3; i++) {
    // do this 3 times
}

Upvotes: 2

Related Questions