rubysolo / dentaku

math and logic formula parser and evaluator
MIT License
875 stars 161 forks source link

Support visitor pattern for AST #151

Open kaelumania opened 6 years ago

kaelumania commented 6 years ago

It might be quiet useful to support a visitor pattern for traversing the AST.

rubysolo commented 6 years ago

I pushed an initial implementation of this to the visitor branch.

kaelumania commented 6 years ago

@rubysolo it looks already pretty nice. However, I can imagine a few improvements:

  1. Don't force a visitor to implement all visit_type methods, check for respond_to??
  2. Add a general visit callback. Thus, if the visitor responds to it, it might filter on type by its own
  3. Generate default implementations for visit_negation like send("visit_#{self.class.name.demodulize}", ...)
  4. PrintVisitor, I find a bit strage that the PrintVisitor calls accept on some nodes. Because the AST should decide which nodes are visited an in which order and the visitor should only react on it.

What do you think?

rubysolo commented 6 years ago

Yes, these are good suggestions.

Regarding PrintVisitor calling accept -- my thought was that the visitor needs to control the order of evaluation (e.g. a visitor might want to print out in prefix notation). Is there a better way to handle that?

kaelumania commented 6 years ago

Hmm, here are my thoughts:

  1. We could add more parameters to the accept methods, that can indicate traversal order (by a flag or rich object, e.g. Traversal::PreOrder, Traversal::PostOrder). This looks to me a bit like a composite visitor, one visitor controls the traversal ordering and another the "real" logic.
  2. The visitor is responsible for traversal and we provide base implementations that define the traversal and call some kind of process method (template method). Similar to 1. but baked into 1 concept StackOverflow
  3. Provide more context while traversing by using visitEnter, visitExit. This way one could collect the visits instead of printing them directly, and whenever an Exit marker is reached, the collected visits can be combined. Fowler
  4. Define an overall default ordering that fits our needs, like the print ordering
rubysolo commented 6 years ago

I think I like the first idea best -- when I have some time I'll work on this a bit more.