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?
Some tips to make your grammar less ambiguous:
'.'
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;'.'
). 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 statement
s, but a single expression
;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