filipp vahituli
filipp vahituli

Reputation: 1

Ambiguous ANTLR grammar

I'm trying to make a parser for a language where . could be concatenation or accessing dictionary value by key e.g.
"a"."b" - concatenation of two strings
foo."some text" - concatenation of "foo" variable's value and "some text"
myDict.myKey - getting value from dictionary "myDict" by key "myKey"
myDict.(myKey) - concatenation of two variables with names "myDict" and "myKey"

Below is a sample grammar for concatenation and getting dictionary values:

grammar Test;

expr:
                expr DOT NAME           #DictFieldExpr
            |   expr DOT expr           #Concatenation
            |   L_PAREN expr R_PAREN    #WrappedExpr
            |   string                  #StringExpr
            |   NAME                    #VariableExpr
;

string:         QUOTE .*? QUOTE;

NAME:           [a-zA-Z]+;
L_PAREN:        '(';
R_PAREN:        ')';
DOT:            '.';
QUOTE:          '"';

As I know #DictFieldExpr should have higher priority than #Concatenation because it was defined earlier. But for input like outerDict.innerDict.key parser returns

expr:Concatenation----expr:VariableExpr----NAME:"outerDict"
                  \
                   \
              expr:DictFieldExpr----expr:VariableExpr----NAME:"innerDict"
                            \
                             \NAME:"key"
                                 

(both nodes should be DictFieldExpr, but the first node is taken for Concatenation for some reason)
How to handle such ambiguous grammars in ANTLR4?

Upvotes: 0

Views: 414

Answers (1)

Mike Cargal
Mike Cargal

Reputation: 6785

(Revised based upon comments)

This seems to work for all of your sample input. The resulting parse tree is "awkward", but then, so, apparently, is the language syntax :)

(I backed out the changes re: the string rule based upon your comment.)

grammar Test
    ;
expr
    : expr dictSuffix   # DictFieldExpr
    | expr concatSuffix # Concatenation
    | '(' expr ')'      # WrappedExpr
    | string            # StringExpr
    | NAME              # VariableExpr
    ;

dictSuffix: ('.' NAME)+;
concatSuffix: '.' expr;

string: QUOTE .*? QUOTE;

NAME:    [a-zA-Z]+;
L_PAREN: '(';
R_PAREN: ')';
DOT:     '.';
QUOTE:   '"';

Upvotes: 1

Related Questions