[antlr-interest] Newbie: NoViableAltException

Andrew Lentvorski bsder at allcaps.org
Tue Jul 24 18:14:53 PDT 2007


Buck, Robert wrote:
> I have no clue what you just said below. So let me start from the
> beginning...
> 
> All I want to do is define a simple recursive grammar for a set-tuple
> syntax that has input streams like:
> 
> (tuple@{(attr1=value1),(attr2=value2)}={(nestedtuple1=value3),(nestedtup
> le2=value4)})

You are slamming into the same problem I slammed into a couple days ago.
A simplified version--given the input:

(a1=(a2=v2))

How do we handle this is a grammar?  Well, it's annoying.  First try:

grammar test;
tuple	:	'(' .+ '=' .+ ')';
ANY	:	.;

Well, that gives me a single tuple with tokens:

'(','a','1','=','(','a','2','=','v','2',')',')'

Hrm.  Not what we want.  Could deal with the tokens, but it's only a 
single tuple.  (Side note: Is there a way to stuff things back through 
the grammar again?  That would probably do what I want?)

Move further backward into the lexer.  Second try:

grammar test;
tuple	:	TUPLE;
TUPLE	:	'(' .+ '=' .+ ')';

Well, that gives a single TUPLE with the token:

"(a1=(a2=v2))"

Still, not really what we want.  Third try:

grammar test;
tuple	:	'(' TUPLET '=' (tuple | ANY+) ')';
TUPLET	:	~('(' | '=')+;
ANY	:	.;

Explanation: We know that things on the left side of the '=' should not 
have '(' or '=' as both of those signal specific things (newtuple or 
valuekey).

Upon trying that grammar, we get a pair of nested tuples (YAY!) and a 
NoViableAltException (boo--this is your problem).  Why?

Well, because the input tokenizes like this:

'(', TUPLET "a1", '=', '(', TUPLET "a2", '=', TUPLET "v2))"

Note that "v2" is a TUPLET, not ANY.  That fails to match any grammar 
rule as the right hand side expected ANY but got a TUPLET.  Fourth try:

grammar test;
tuple	:	'(' TUPLET '=' (tuple | TUPLET) ')';
TUPLET	:	~('(' | '=')+;

Still two nested tuples, but a MismatchedTokenException-huh?

Looking at the token stream:

'(', TUPLET "a1", '=', '(', TUPLET "a2", '=', TUPLET "v2))"

The problem is that TUPLET vacuumed up the two ')' and used them to make 
a TUPLET token.  Fifth try:

grammar test;
tuple	:	'(' TUPLET '=' (tuple | TUPLET) ')';
TUPLET	:	~('(' | '=' | ')')+;


The following token stream goes into the parser:

'(', TUPLET "a1", '=', '(', TUPLET "a2", '=', TUPLET "v2", ')', ')'

This seems to do what we want.  We get two nested tuples exactly like we 
want them.

Hope this helps,
-a


More information about the antlr-interest mailing list