[antlr-interest] Managing more than one node as root exceptions

Andreas Stefik stefika at gmail.com
Fri Jul 2 19:39:41 PDT 2010


Hi again all,

And of course, in classic ME form, after spending 10 hours making this
problem much more difficult than it really is, I figure out the
solution 10 minutes after forever making my misunderstandings public.
So, the solution is trivial:

atom 	:
	qualified_name -> ^(QUALIFIED_SOLO_EXPRESSION qualified_name)
	|	qualified_name LEFT_SQR_BRACE expression RIGHT_SQR_BRACE ->
			^(ARRAY_EXPRESSION qualified_name LEFT_SQR_BRACE expression RIGHT_SQR_BRACE)
	|	qualified_name (COLON ID)? LEFT_PAREN (expression (COMMA
expression)*)? RIGHT_PAREN ->
			^(FUNCTION_CALL qualified_name (COLON ID)? LEFT_PAREN (expression
(COMMA expression)*)? RIGHT_PAREN)
	| (MINUS)? INT
	| BOOLEAN
	| (MINUS)? DECIMAL
	| STRING
	| NULL
	| LIBRARY_CALL LEFT_PAREN expression COMMA expression COMMA
expression RIGHT_PAREN
	| INPUT LEFT_PAREN expression RIGHT_PAREN
	| LEFT_PAREN expression RIGHT_PAREN -> ^(expression)
	;

I guess I wrote the rule the other way thinking I would avoid left
recursion (a typically sensible practice for LL), but when you write
it that way, you can't write rewrite rules (or I couldn't figure out
how), where there are two alternatives ^( this | that), with imaginary
roots. I'm still not sure I completely grasp why the alternative threw
multiple root exceptions, though. My best "guess" is that
qualified_name rule can have multiple tokens (roots), so it doesn't
necessarily qualify as a single root. However, why that would work
fine normally, but not when nested inside the LEFT_PAREN expression
RIGHT_PAREN rule still isn't obvious to me.

Anyway, sorry to bother everyone, and thanks for the potential help,

Stefik

On Fri, Jul 2, 2010 at 8:37 PM, Andreas Stefik <stefika at gmail.com> wrote:
> Hi folks,
>
> I have a relatively simple grammar, which works well under most
> conditions, but in one case it has issues. Here is a snippet of the
> grammar:
>
> expression :    or      ;
> or      :       and (OR ^ and)*         ;
> and     :       equality (AND ^ equality)*      ;
> equality:       comparison ((EQUALITY ^ | NOTEQUALS ^) comparison)*     ;
> comparison:     add ((GREATER ^| GREATER_EQUAL ^| LESS ^| LESS_EQUAL^) add)*    ;
> add     :       multiply ((PLUS ^| MINUS^) multiply)*   ;
> multiply:       combo_expression ((MULTIPLY ^| DIVIDE ^|MODULO^) combo_expression)*     ;
> combo_expression
>        :       atom
>        |       NOT atom
>        |       CAST LEFT_PAREN assignment_declaration COMMA expression RIGHT_PAREN
>        ;
> atom    : qualified_name
>        (
>                LEFT_SQR_BRACE expression RIGHT_SQR_BRACE //this condition breaks
>        |       (COLON ID)? LEFT_PAREN (expression (COMMA expression)*)?
> RIGHT_PAREN //so does this one
>        )?
>        | (MINUS)? INT
>        | BOOLEAN
>        | (MINUS)? DECIMAL
>        | STRING
>        | NULL
>        | LIBRARY_CALL LEFT_PAREN expression COMMA expression COMMA
> expression RIGHT_PAREN
>        | INPUT LEFT_PAREN expression RIGHT_PAREN
>        | LEFT_PAREN expression RIGHT_PAREN -> ^(expression) ;
>
> So far as I can tell from testing, this works fine, except in the case
> where you have an expression with surrounding parentheses and the item
> inside of it is a qualified_name, with either square braces or the
> part of the rule after it. In this particular case, the following
> exception is thrown:
>
> java.lang.RuntimeException: more than one node as root (TODO: make
> exception hierarchy)
>        at org.antlr.runtime.tree.BaseTreeAdaptor.becomeRoot(BaseTreeAdaptor.java:150)
>        at org.sonify.vm.hop.parser.HopParser.atom(HopParser.java:4954)
> //notice it is in the parser, not the tree grammar
>        at org.sonify.vm.hop.parser.HopParser.combo_expression(HopParser.java:4403)
>
> To give an example of what would break in the language (not all rules
> shown), this would work fine:
>
> boolean array a
> a[0] = 10
> a[1] = a[0]
>
> and this would throw the above exception
>
> boolean array a
> a[0] = 10
> a[1] = (a[0])
>
> I've tried everything obvious (to me) that I can think of (e.g.,
> pulling out the rules one by one), but am perplexed as to why that
> rule throws a double root exception.
> I'm pretty sure the problem is relative to this portion of the
> grammar, but just in case, here is the full grammar:
>
> https://sourceforge.net/apps/trac/sodbeans/browser/trunk/sodbeans/Compiler/src/org/sonify/vm/hop/parser/Hop.g
> and the full tree grammar:
> https://sourceforge.net/apps/trac/sodbeans/browser/trunk/sodbeans/Compiler/src/org/sonify/vm/hop/parser/HopSymbolTableWalker.g
>
> When I run the code in the ANTLRWorks interpreter, it generates the
> trees just fine. One final clue is that my tree grammar is showing UP
> and DOWN tokens, which I know means there is a mismatch somewhere ---
> where, however, and how to fix, I'm not quite sure about, and this
> error seems to be coming from the parser anyway, so I don't "suspect"
> that that is the cause for this immediate problem.
>
> Any help would be greatly appreciated, as the error is driving me a bit crazy,
>
> Stefik
>


More information about the antlr-interest mailing list