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

Kyle Ferrio kferrio at gmail.com
Wed Jan 11 20:20:50 PST 2012


Sam,

It's quite possible I missed part of your intent.  And with respect for
your clearly evident skill, I'm not sure I'd want to be creating factories
as an antlr user.  Factories are great for library writers but maybe less
so in the hands of mortals like me.  But perhaps you meant that this code
could be autogenerated by the antlr tool?  Oh wait, I just saw Ter's post
below.  Anyway, I'll hit "send" in case this leads someplace.

Kyle


On Wed, Jan 11, 2012 at 7:54 PM, Sam Harwell <sam at tunnelvisionlabs.com>wrote:

> To "dynamically add fields", add the following method for each rule foo:
>
> protected fooContext newContext_foo() { return new fooContext(); }
>
> 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
>


More information about the antlr-interest mailing list