Search code examples
antlrantlrworks

Why is this grammar giving me a "non LL(*) decision" error?


I am trying to add support for expressions in my grammar. I am following the example given by Scott Stanchfield's Antlr Tutorial. For some reason the add rule is causing an error. It is causing a non-LL(*) error saying, "Decision can match input such as "'+'..'-' IDENT" using multiple alternatives"

Simple input like:

a.b.c + 4

causes the error. I am using the AntlrWorks Interpreter to test my grammar as I go. There seems to be a problem with how the tree is built for the unary +/- and the add rule. I don't understand why there are two possible parses.

Here's the grammar:

path    :   (IDENT)('.'IDENT)* //(NAME | LCSTNAME)('.'(NAME | LCSTNAME))*
    ;

term    :   path
    |   '(' expression ')'
    |   NUMBER
    ;

negation 
    :   '!'* term
    ;

unary   :   ('+' | '-')* negation

    ;

mult    :   unary (('*' | '/' | '%') unary)*
    ;

add     :   mult (( '+' | '-' ) mult)*
    ;

relation 
    :   add (('==' | '!=' | '<' | '>' | '>=' | '<=') add)*
    ;

expression
    :   relation (('&&' | '||') relation)*
    ;

multiFunc   
    :   IDENT expression+
    ;

NUMBER  :   DIGIT+ ('.'DIGIT+)?
    ;

IDENT   :   (LCLETTER|UCLETTER)(LCLETTER|UCLETTER|DIGIT|'_')*
    ;

COMMENT
        :       '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    |       '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
        ;

WS  :   (' ' | '\t' | '\r' | '\n' | '\f')+ {$channel = HIDDEN;}
    ;

fragment
LCLETTER 
    :   'a'..'z'
    ;

fragment
UCLETTER:   'A'..'Z'
    ;   

fragment
DIGIT   :   '0'..'9'
    ;

I need an extra set of eyes. What am I missing?


Solution

  • The fact that you let one or more expressions match in:

    multiFunc   
     : IDENT expression+
     ;
    

    makes your grammar ambiguous. Let's say you're trying to match "a 1 - - 2" using the multiFunc rule. The parser now has 2 possible ways to parse this: a is matched by IDENT, but the 2 minus signs 1 - - 2 cause trouble for expression+. The following 2 parses are possible:

    parse 1

    enter image description here

    parse 2

    enter image description here