Best way to resolve ambiguity

162 views
Skip to first unread message

Федор Усов

unread,
Jul 20, 2019, 7:03:34 AM7/20/19
to antlr-discussion
I have an ambiguous grammar
chain
   
: chainBase memberAccess* ('?' | '!' | '.' Yield)?
   
;

memberAccess
   
: '&'? '.' (identifier | keyword) ('?' | '!' | '=')? functionCallInsideMember? squareExpression*?
   
;

 which can recognize 
a(b).(c)
as either chain or anotherRule. But I want chain only match "a(b).", because there is no dot after last parenthesis. What I assume can do is 
1) Make a twin of memberAccess which is not matching a dot, if we consumed it inside of functionCallInsideMember(which returns a boolean value like isDotMatched). In that case I would like to make one rule from them looks like
chain
locals [boolean isDotMatched]
@init {
    $isDotMatched
= false;
}
   
: chainBase {$isDotMatched = $chainBase.matchedDot;} ( memberAccess[!$isDotMatched] {$isDotMatched = $memberAccess.matchedDot;} )* ('?' | '!' | '.' Yield)?
   
;

memberAccess[boolean matchDot] returns [boolean matchedDot]
@init {
    $matchedDot
= false;
}
   
: '&'? optionalDot[$matchDot] (identifier | keyword) ('?' | '!' | '=')? (functionCallInsideMember {$matchedDot = true;})? squareExpression*?
   
;

optionalDot[boolean matchDot]
   
: {$matchDot}? '.' | {!$matchDot}?;

But then antlr's "
adaptivePredict" matches empty optionalDot anyway, then checking predicate and if it fails, antlr reports a NoViableAltException.
I know I can catch it, but how to fail a rule matching properly then? I tried "_errHandler.recover" but it just makes antlr match incorrect input like "p a.b(0)" as my "chain" rule, which would be matched later on a some lower precedence rule.
2) Make a predicate inside of functionCallInsideMember looks like
functionCallInsideMember
    : {getCurrentToken().getType() == OpenRoundBracket && getTokenAfterMatchingParen(getCurrentToken()) == Dot}?
      '(' actualArguments? CloseRoundBracket ;
but antlr can't handle token references. I don't know why though, because by parse time lexer already 
gave us all the tokens(not really I guess, but we can assume that because antlr's philosophy is to separate lexer and parser). Why is antlr at the prediction time not shifting current tokenStream? And how can I overcome it?
3) Make custom tokens which store information about next token after matching parenthesis if token is a paren itself. It would just require an array of opened parenthesis token references I guess, but it seems unnecessary for such a simple task.

P.S. Sorry for my English, and possibly for question formatting as I didn't figure out how to preview my topic here
Message has been deleted

Федор Усов

unread,
Jul 24, 2019, 3:57:29 AM7/24/19
to antlr-discussion
What? It actually is "the google discussion group"

Martin Mirchev

unread,
Sep 30, 2020, 10:58:13 AM9/30/20
to antlr-discussion
Hi, Can I see the other rule? if you can possibly make the example not contain information which is not needed to understand as I am having a hard time following the problem.
Reply all
Reply to author
Forward
0 new messages