简体   繁体   中英

Antlr4 - Best way to switch between Listener and Visitor modes?

I'm currently in the process of planning out the structure of a language interpreter and I am realizing that I do not like the idea of exclusively using a Visitor or Listener tree traversal method.

Since both tree traversal methods have their merits, Ideally, I would like to use a mix of both:

  • Using a listener makes the most sense when traversing arbitrary language block definitions (function/class definitions, struct/enum-like definitions) especially when they can be nested.
  • Visitors seem to naturally lend themselves to situations such as expression evaluation, where the context is far more predictable, and result values can be returned back up the chain.

What is the most "correct" method to switch between the two traversal methods?

So far, my ideas are as follows:

Switch from Listener to Visitor for a portion of a parse tree

Say that, when the listener reaches the node "Foo", I want to handle its children more explicitly using a Visitor. One way I can think of doing this is:

  • Parse Tree walker calls enterFoo(ctx)
    • Create an instance of myFooVisitor
    • Explicitly visit children, store result, etc.
    • Set ctx.children = [] (or equivalent)
  • When enterFoo() returns, the parse tree walker sees that there are no more children for this node, and does not needlessly walk though all of Foo's children

Switch from Visitor to Listener for a portion of a parse tree

This is a little more obvious to me. Since tree traversal is explicitly controlled when using Visitors, switching over seems trivial.

  • visitFoo() gets called
    • Create an instance of a new parse tree walker and myFooListener
    • Start the walker using the listener as usual.

You seem to have gotten an idea where listeners and visitors are modes, kinda states you can switch. This is wrong.

Both listener and visitor are classes that allow you act on rule traversal. The listener does this by getting called from the parser during the parse process when a rule is "entered" or "left". There's no parse tree involved.

The visitor however uses a parse tree to walk over every node and call methods for them. You can override any of these methods to do any associated work. That doesn't necessary have to do with the evaluation result. You can use that independently.

ANTLR4 generates method bodies for each of your rule (both in listeners and visitors), which makes it easy for you to only implement those rules you are interested in.

Now that you know that listeners are used during parsing while visitors are used after parsing, it should be obvious that you cannot switch between them. And in fact switching wouldn't help much, since both classes do essentially the same (call methods for encountered rules).

I could probably give you more information if your question would actually contain what you want to achieve, not how .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM