[antlr-interest] A lost label?

Jim Idle jimi at temporal-wave.com
Sat Jan 24 18:37:30 PST 2009


Markus Stoeger wrote:
> I ran into a nasty "ArgumentNullException" problem with the following 
> rule today:
>
> label returns [string name]
>     : x=unsignedInt {$name = $x.text;}
>     | x=identifier {$name = $x.text;}
>     ;
>
> The generated code (CSharp2) for this rule is below. For some reason 
> ANTLR doesn't assign the label x in the first alternative which results 
> in "name" being null all the time:
>
> case 1 : {
>         unsignedInt(); // missing assignment to label x!
>         name =  ((x != null) ? 
> input.ToString((IToken)(x.Start),(IToken)(x.Stop)) : null);
>         break;
>     }
> case 2 : {
>         x = identifier();
>         name =  ((x != null) ? 
> input.ToString((IToken)(x.Start),(IToken)(x.Stop)) : null);
>         break;
>     }
>
> If I call one label x and the other one y it works fine (both get assigned).
>
> Shouldn't it be possible to use the x label for both assignments, since 
> they are assigned in two different alternatives? 

You cannot do this because the object that is returned from 
'unsignedInt' may or may not be exactly equivalent to the object 
returned from 'identifier', but even if they are, they will be different 
type, derived from the generic rule_return class. Consider:

unsignedInt returns [int x, int y] ...

identifier returns [string name]...

Unless you are generating an AST, the analysis will determine that the 
identifier rule returns a single value and so the generated method will 
just return String. However the unsignedInt rule will return a reference 
to an object that contains two ints, x and y. You cannot create your x 
label declared as two different things simultaneously, and that's why 
you cannot reuse the label unless the label is to be assigned from 
exactly the same rule. At some point the error messages about this stuff 
will improve ;-)

You could however, do this:

: x = identOrUint { $name = $x.text; }

And then have your identOrUint assign accordingly, but at some level, 
you will run in to the same thing. I suppose that when you are asking 
for the text reference it coudl be worked out that x is a String in both 
cases, but there are probably more useful things to work on just yet.

So, your proposed workaround is what you need to do.

Jim


> The book (page 124) 
> says "variables are visible to the immediately surrounding alternative, 
> but not other alternatives". 
I think that this really means that if you have:

: y=rule1
| x=rule2

That you cannot write:

| x=rule2 { $name = $y.text; }
> If I understand this right, each 
> alternative has its own scope so reusing the variable name in another 
> scope should be possible? Or maybe ANTLR could display an error while 
> generating the parser in such a case? That would be better than silently 
> discarding the assignment... :-)
>   
It would indeed and I am sure that this will happen at some point. The 
devil is in the details of all the code generation and so on.

Jim
> Max
>
>
> List: http://www.antlr.org/mailman/listinfo/antlr-interest
> Unsubscribe: http://www.antlr.org/mailman/options/antlr-interest/your-email-address
>   



More information about the antlr-interest mailing list