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

Sam Harwell sam at tunnelvisionlabs.com
Wed Jan 11 18:54:40 PST 2012


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



More information about the antlr-interest mailing list