[antlr-interest] NoViableAltException

Gavin Lambert antlr at mirality.co.nz
Thu May 7 14:40:14 PDT 2009


At 09:13 8/05/2009, Bill Steer wrote:
 >REGISTER = avg(REGISTER, REGISTER, REGISTER);
 >
 >where REGISTER is just a multi-part identifier, with the parts
 >separated by an '!'.  The lexer seems to work ok, judging by
 >the Tokens it returns in another part of my code.  But, at
 >runtime, the parser gets a NoViableAltException on a statement
 >like that.
[...]
 >stat:	REGISTER EQUALS expr
[...]
 >atom returns [int value]
 >	:	CONSTANT {$value = Convert.ToInt32($CONSTANT.text);}
 >	|	REGISTER { Register reg = findRegisterByName($REGISTER.text);
[...]
 >fragment
 >INT		: (DIGIT)+ ;
 >FLOAT	:	INT
 >		| INT '.' INT
 >		| '.' INT
 >;
 >CONSTANT:	FLOAT
 >		|	FLOAT ('e' | 'E') ('+' | '-')? INT
 >;
[...]
 >IDENT	:	LETTER (LETTER | DIGIT)* ;
 >REGISTER:	IDENT ('!'IDENT)* ;

Haven't we already discussed this?  (I definitely remember seeing 
those FLOAT and CONSTANT rules before...)

INT/FLOAT/CONSTANT and IDENT/REGISTER can all match identical 
input, since each is just a superset of the other.  This can lead 
to problems because when faced with input like "14", your rules 
say that it is acceptable to generate ANY of INT, FLOAT, or 
CONSTANT.

It's not fatal to do this (though it's bad style); but if you do 
then you need to ensure that wherever your parser is expecting a 
CONSTANT (or a REGISTER) that it will tolerate receiving a FLOAT 
(or an IDENT) instead.

The better solution is to remove the ambiguity.  Probably the 
simplest way to do that in the above case is to make FLOAT and 
IDENT fragment rules (and ensure the parser doesn't refer to them).



More information about the antlr-interest mailing list