[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