[antlr-interest] Extending contexts in code (was "Appropriate use of honey badger listeners")

Terence Parr parrt at cs.usfca.edu
Wed Jan 11 19:05:44 PST 2012


Actually, parse tree is already created when we walk it. can't change the objects at that point.
Ter
On Jan 11, 2012, at 6:56 PM, Terence Parr wrote:

> 
> On Jan 11, 2012, at 6:54 PM, Sam Harwell wrote:
> 
>> To "dynamically add fields", add the following method for each rule foo:
>> 
>> protected fooContext newContext_foo() { return new fooContext(); }
> 
> so then these are "factories" and we subclass parser to alter?  What if we need multiple kinds of fooContext for different passes?
> 
> Ter
>> 
>> If you keep the same implementation of labels, also add the following for a
>> label #mult inside rule foo:
>> 
>> protected multContext newContext_mult(fooContext originalContext) {
>>   multContext result = new multContext();
>>   result.copyFrom(originalContext);
>>   return result;
>> }
>> 
>> Now you can extend any context you want in code only. :)
>> 
>> --
>> Sam Harwell
>> Owner, Lead Developer
>> http://tunnelvisionlabs.com
>> 
>> 
>> -----Original Message-----
>> From: Terence Parr [mailto:parrt at cs.usfca.edu] 
>> Sent: Wednesday, January 11, 2012 6:40 PM
>> To: ANTLR Interest Mailing List
>> Subject: [antlr-interest] Appropriate use of honey badger listeners
>> 
>> hi Kyle,
>> 
>> I have 2 questions about the current listener mechanism:
>> 
>> 1. How do we return values from listener methods so that we can do
>> computations?
>> 2. How do we alter a parse tree?
>> 
>> For 2, I think we return a new tree as a return value and the parse tree
>> walker will incorporate that into the tree if it sees a different tree come
>> back. In other words, it will do something like this in the walker:
>> 
>> newtree = listener.someEvent(oldtree);
>> if ( newtree!=oldtree ) replace-oldtree-with-newtree;
>> 
>> For 1, I don't have a great answer. To make this more concrete, imagine we
>> have an expression rule and we want to use listener events to compute the
>> value of an expression. So, instead of having actions in the grammar  like:
>> 
>> e returns [int v]
>>     : a=e '*' b=e {$v = $a.v * $b.v;}
>> 
>> we would simply match it
>> 
>> e : e '*' e -> mult .
>> 
>> and then have listener events compute values. but where does of the listener
>> object store the intermediate results of a subtree computation? Certainly we
>> don't want to have to add "returns [int v]" to the grammar for every
>> different paths we make over the parse tree. Without a return value from a
>> listener event (which I want to use for tree rewriting), how do we get a
>> value up the tree in a computation?  We can't really use temporary fields of
>> the listener object because it's hard to tell which value gets associated
>> with which listener method. we would need a temporary fields to hold result
>> values from each listener. actually, I'm not even sure that would work. We
>> need to associate result values with sub tree roots (i.e. contexts). In
>> other words, we need a way to dynamically add fields to contexts for the
>> specific purpose of a particular parse tree walk. One can imagine that I
>> have a pass for computing the type of expression and another pass for
>> computing the value. In both cases, I need result values for each subtree
>> (type and then value).
>> 
>> Maybe that is just a hash table from ctx node to value;
>> Map<ParserRuleContext, Object>. maybe. That presents a few issues for me
>> because I use hashCode/equals in a weird way for use with grammar analysis,
>> but that would be the idea.
>> 
>> class MyGListener extends BlankGListener {
>> 	Map<ParserRuleContext, Integer> results = .;
>> 
>> 	public void exitRule(AParser.multContext ctx) { results.put(ctx,
>> results.get(ctx.a) * results.get(ctx.b)); }
>> 	public void exitRule(AParser.addContext ctx) { results.put(ctx,
>> results.get(ctx.a) + results.get(ctx.b)); } }
>> 
>> not very pretty in Java. Python would look better:
>> 
>> results[ctx] = results[ctx.a] * results[ctx.b];
>> 
>> This way we can associate any values we need to for any node, in effect,
>> decorating the parse tree as needed.
>> 
>> What do people think about the solution? is there a way I can automate some
>> of this? I think that Python and Ruby would make short work of that because
>> they allow dynamically adding fields (normally a horrible thing to do) ;) Is
>> there a better way to do decorations in Java?
>> 
>> Ter
>> 
>> On Jan 11, 2012, at 1:49 PM, Kyle Ferrio wrote:
>> 
>>> Excellent, congratulations and thank you.
>>> 
>>> I just spent about half an hour playing with variations on A.g4 (since 
>>> it worked right out of the box I had to keep going...)  and this is 
>>> really nice.  This is the first time I've looked at the new-in-antlr 
>>> listener paradigm.  I will need a while to fully appreciate the doors this
>> opens.
>>> Honey Badger makes things easy, so I want to stay on his (?) good side.
>>> 
>>> Q: how do you tell a boy Honey Badger from a girl Honey Badger?
>>> 
>>> A: you don't.  they're both bad-ass.
>> 
>> nice!
>> 
>> Ter
>> 
>> List: http://www.antlr.org/mailman/listinfo/antlr-interest
>> Unsubscribe:
>> http://www.antlr.org/mailman/options/antlr-interest/your-email-address
>> 
>> 
>> List: http://www.antlr.org/mailman/listinfo/antlr-interest
>> Unsubscribe: http://www.antlr.org/mailman/options/antlr-interest/your-email-address
> 
> 
> 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