Visit subtrees in Visitor Pattern

127 views
Skip to first unread message

Alireza Rezaei Mahdiraji

unread,
Jan 19, 2015, 9:15:42 AM1/19/15
to antlr-di...@googlegroups.com

Hi All,

I am using the visitor pattern for my grammar. The grammar contains three main clauses let say
clause 1, clause 2, and clause 3 such that clause 1 contains information which are used by
clause 2 and 3 and clause 2 contains information used by clause 3. Each node implement
an abstract class IParseTreeNode containing an abstract method evaluate(). I need to
execute all evaluate() methods under the clause 1 first, then all the methods under
clause 2, and finally all the methods under clause 3. How can I do such a customized visit
of the tree?

Thanks,
Best,
Alireza

David Whitten

unread,
Jan 19, 2015, 5:12:27 PM1/19/15
to antlr-di...@googlegroups.com
Just so I understand, you have a grammar rule

Start :- Clause1 Clause2 Clause3

or do you just want to call the visitor method for Clause2 from the
visitor code for Clause1, and then
call the visitor method for Clause3 from the visitor code for Clause2 ?

Or do you just want to have some master visitor code that calls each
of the visitor code in order ?

David
> --
> You received this message because you are subscribed to the Google Groups
> "antlr-discussion" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to antlr-discussi...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Alireza Rezaei Mahdiraji

unread,
Jan 20, 2015, 4:54:09 AM1/20/15
to antlr-di...@googlegroups.com

Hi David,

The start rule is as you said:

Start :- Clause1 Clause2 Clause3

and I would like to first visit the subtree of Clause1, then the subtree of Clause2 and finally
the subtree of Clause3.

Normal call of the visit method on the parse tree will execute
the deeper nodes first. That node might be in Clause2 or Clause3. However, in my case,
there is a dependency between the clauses, e.g., Clause1 defines some variables which
will be used in Clause2 and Clause3.

Thanks,
Best,
Alireza   

Alireza Rezaei Mahdiraji

unread,
Jan 26, 2015, 5:32:49 AM1/26/15
to antlr-di...@googlegroups.com

Hi All,

Could anybody help me with this? Any idea?

Thanks,
Alireza

David Whitten

unread,
Jan 26, 2015, 7:12:08 AM1/26/15
to antlr-di...@googlegroups.com
One obvious way is to traverse the tree two times. on the first time,
just do the
action on the top nodes, and the second time allow the subtrees to do
their actions.

So you run the Visitor code both times, but it has an IF inside that knows which
traversal it is, and does something different based on which traversal
count value.

On Mon, Jan 26, 2015 at 5:32 AM, Alireza Rezaei Mahdiraji

Alireza Rezaei Mahdiraji

unread,
Jan 26, 2015, 7:33:33 AM1/26/15
to antlr-di...@googlegroups.com

I need to run the whole Clause1 before anything else. This means to run the whole subtree
of Clause1. For instance Clause1 could be something like "For v in F()", this means I need to
evaluate F() first and then bind v to it. After this I am done with Clause1 and I can
start by running Caluse2 and then Clause3.

You said first run of the tree just visit top nodes. that does not sound to work in my case
(explained above).

Thanks,
Alireza

Eric Vergnaud

unread,
Jan 26, 2015, 9:27:30 AM1/26/15
to antlr-di...@googlegroups.com
a key aspect here is whether or not your grammar enforces clause sequence i.e. clause 3 always comes after clause 2 which always comes after clause 1.
If so, a simple visitor is I believe guaranteed to visit the clauses in sequence.
If not, then I would recommend implementing 3 visitors, one for each clause. Visitor2 uses the outcome of visitor1 of course.

David Whitten

unread,
Jan 26, 2015, 9:43:01 AM1/26/15
to antlr-di...@googlegroups.com
lets say you have rules:

forloop :- FOR expr IN expr ;
expr :- num
| name ;

As I undestand it, given the input FOR A IN 7
the visitor pattern already
processes in the order
forloop.visitor
expr.vistor
name.visitor
expr.visitor
num.visitor.

If this is what you want to do, why are you confused ?
Doesn't the system already do it in the order you want?

David Whitten

On Mon, Jan 26, 2015 at 7:33 AM, Alireza Rezaei Mahdiraji

Alireza Rezaei M

unread,
Jan 26, 2015, 9:51:54 AM1/26/15
to antlr-di...@googlegroups.com
When I call execution on the root of the parse tree, first the leave node
with the deepest distance from it will be executed and then their parents and so on.
If that is a true statement, then these deep nodes in the query might belong to
Clause2 or Clause3 and that makes the query processing wrong because
all the variables binding suppose to happen in Caluse1. Please correct me
if I am wrong.

Thanks,
Best,
Alireza  

You received this message because you are subscribed to a topic in the Google Groups "antlr-discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/antlr-discussion/ScZYO6XN5Q4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to antlr-discussi...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Best Regards

Alireza Rezaei Mahdiraji

Alireza Rezaei M

unread,
Jan 26, 2015, 9:54:30 AM1/26/15
to antlr-di...@googlegroups.com
Yes, it does enforce sequence. Do you mean if I have
query:- ForClause WhereClause ReturnClause then the visitor
executes all the elements in the subtree of ForClause first?

Could you explain a bit more about how to use the three visitor together?  
Do you know any example?

Alireza

--
You received this message because you are subscribed to a topic in the Google Groups "antlr-discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/antlr-discussion/ScZYO6XN5Q4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to antlr-discussi...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--

Mike Cargal

unread,
Jan 27, 2015, 6:50:47 AM1/27/15
to antlr-di...@googlegroups.com
With Vistors, you're in complete control of the order of visiting child nodes (even to the point of deciding not to visit child nodes).  Listeners take care of node navigation for you and you can decide which node to listen in on (either upon enter or exit, as the listener code navigates the tree for you.  This make listeners simpler to use if you only interested in doing something on selected nodes (or even if you just don't want the responsibility of navigating the tree.  Visitors are much more flexible, but you accept responsibility for how to navigate the parse tree..

The behavior you describe is certainly not my experience with visitors.  The base class will generally provide default methods for each node type that do nothing beyond just delegating that their children accept the visitor in order, but ,in your visitor, you override that method, you decide how you want to navigate that node.  If you have overridden the visitor for the top node then you decide how, and in what order to visit the children (and each of those children makes a similar decision about which (and in what order) to visit it's children.  If you override the method, you control the navigation.  

The only way I can imagine the deepest leaf node being "executed" first would be if you were using a listener and only overriding the exit* methods.  Then you'd get control as the tree navigation unwinds back to the top.

Try overriding your top level node visitor. It'll be called before any of the children are visited.  In fact, the children won't be visited at all if you don't explicitly make a call for them to accept the visitor. 
Reply all
Reply to author
Forward
0 new messages