Search code examples
antlrantlr3antlrworks

Decision can match input such as "ID" using multiple alternatives: 1, 2


I am trying to define a simple functional language grammar, I am almost done with my definitions, but I can't get past the following ambiguities.

[14:43:53] warning(200): mygrammar.g:14:11: Decision can match input such as "ATOM" using multiple alternatives: 1, 2 As a result, alternative(s) 2 were disabled for that input 

[14:43:53] warning(200): mygrammar.g:14:11: Decision can match input such as "ID" using multiple alternatives: 1, 2 As a result, alternative(s) 2 were disabled for that input

here are what I think are the relevant rules the drawing is almost identical for ATOM and ID:

program : (statement'.')* ;

statement : assignment
          | expression;

assignment : func '->' statement ((','statement)=> ',' statement)*
           | ID '->' expression
           | ATOM '->' ( string | number ); 

func : (ID '(' args ')')=> ID '(' args ')'; 

term : func
     | '(' expression ')'  
     | number
     | string
     | ID
     | ATOM ;

ATOM : ('A'..'Z'|'_')+;

ID : ('a'..'z'|'_')('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;

here is the syntax tree from ANTLRWorks

id alternatives http://www.vertigrated.com/images/id_alternatives.png

Here is a rough straw man of what I am trying to support parsing.

hypotenuse(a,b) -> 
  sqr(x) -> x * x,
  sqr(sqr(a) + sqr(b)). 

print(hypotnenuse(2,3)).

so I need to be able to support nesting statements inside of functions

where -> is my assignment operator, this is a single assignment language

where . is my statement end marker

Is this even possible to parse with ANTLR3?


Solution

  • Some tips to make your grammar less ambiguous:

    1. remove the '.' as an end-of-statement char. Replace it with, say, a ';'. Both are just one character, and a ';' does not conflict with the '.' inside a float;
    2. create a lexer rule that matches a float;
    3. a function is followed by one or more statements, but has no obvious end (except for the "main" function which now ends with a '.'). You must either tell your parser where a function ends (not just the "main" function), or must introduce a rule that matches an "inner" function that does not have multiple trailing statements, but a single expression;
    4. do you really need a expression in your statement rule? Both can be a function (makein it, again, ambiguous).

    These are just a few of the problems with the way you've defined your language. If I were you, I wouldn't continue this way: you might fix some things with predicates, but altering something on another place will open yet another can of worms. I advise you redesign your language drastically.

    If you don't want to redesign it, simply remove all predicates from your grammar and put the following line in your options {...} section:

    backtrack=true;
    

    which will (seemingly) magically remove all warnings regarding ambiguous rules, but this is not a recommended fix. That way, ANTLR will choose parse trees for you when it encounters an ambiguity, (highly) possibly resulting in unexpected behavior, and for large input, it results in longer parse times. Again, this is not what I'd go for! See the Wiki for more info regarding global backtracking: http://www.antlr.org/wiki/display/ANTLR3/How+to+remove+global+backtracking+from+your+grammar