[antlr-interest] Predicate hoisting pain

Sam Barnett-Cormack s.barnett-cormack at lancaster.ac.uk
Mon Apr 13 09:28:35 PDT 2009


Jim Idle wrote:
> Sam Barnett-Cormack wrote:
>> Jim Idle wrote:
>>> However, as you can obviously distinguish the cases at some point 
>>> higher up the rule chain, then if you wish to pursue this, then all 
>>> you need do is create a scope with your flag in it at a high enough 
>>> level, init it to the default case, then set/unset it as the rules 
>>> descend, then use it as the gated predicate in your rule above:
>>>
>>> highuprule
>>>     scope
>>>      { boolean os; }
>>>     @init { $highuprule::os = false; }
>>> : rule rule rule ... ;
>>>
>>> ...
>>>
>>> ruleX :  X  Y (Z { $highuprule::os = true; }  objectSetSpec)? // Z 
>>> present means flip the flag
>>> ;
>>>
>>> objectSetSpec
>>>    : {$highuprule:os}?=>additionalSetSpec
>>>    | something else
>>>    ;
>> It's more that it would have to be changed on the way down the parse 
>> tree, and changed back on the way back. So ruleX would be more like 
>> (if this would work):
>>
>> ruleX
>> @init {
>>   boolean os = $highuprule::os;
>> }
>>   : X Y ({$highuprule::os = true;} ruleZ {$highuprule::os = os;})?
>>   ;
>>
>> If that makes any sense at all.... 
> 
> Yes, but so long as your scope is high enough up then it is fine. Also, 
> don't forget that scopes stack so if you need to remember state, then 
> you coudl do it in ruleZ.

Good point. I forgot about shared scope stacks.

> Also, you should probably switch state in ruleZ and not in the caller, 
> using the @init and @after actions for ruleZ.
>> it needs to be able to change it for the duration of ruleZ (and stuff 
>> under ruleZ might change it as well for things under themselves) while 
>> changing it back to whatever it was on entering ruleX after it 
>> finishes with ruleZ. All assuming that X Y (ruleZ)? wouldn't be 
>> ambiguous, of course.
> This is why you should really merge it all into the one rule that know 
> everything, then reject the invalid constructs later, so long as they 
> are syntactically sound. Your parser is there only to verify syntactic 
> structure, not to check that it is the right structure for the right place.

The thing is, in this case "in the right place" isn't just a case of 
being the right type for what it's being assigned to, for instance - 
it's a case of there being two very different constructs that occur in 
very different places (except once, and that's a separate problem), 
inside different syntactic constructs - there's precisely one place that 
  both are allowed, and it's admittedly a pain in the but, but there's a 
few solutions I'm considering. On the other hand, trying to combine the 
two unambiguously would lead to an AST barely more useful than a flat 
token stream, and the treewalker isn't going to be in that much of a 
better position to handle semantics. The handling of the token stream 
would be left to the post-parse semantic stage, which is much less 
convenient for handling it (difference between hand-crafting parser in 
Java and using ANTLR, essentially). The only compromise I can see would 
be keeping in the specific rules and calling them as start rules on a 
synthetic token stream, once everything else is on to true semantic stuff.

Sam


More information about the antlr-interest mailing list