parallel class structures for AST-based objects
sajmikins at gmail.com
Sun Nov 22 16:55:08 CET 2009
On Sun, Nov 22, 2009 at 4:50 AM, Diez B. Roggisch <deets at nospam.web.de> wrote:
> Steve Howell schrieb:
>> On Nov 21, 4:07 pm, MRAB <pyt... at mrabarnett.plus.com> wrote:
>>> I don't see the point of EvalNode and PrettyPrintNode. Why don't you
>>> just give Integer, Sum and Product 'eval' and 'pprint' methods?
>> That's a good question, and it's the crux of my design dilemma. If
>> ALL I ever wanted to to with Integer/Sum/Product was to eval() and
>> pprint(), then I would just add those methods to Integer, Sum, and
>> Product, and be done with it, as you suggest. But what happens when
>> somebody wants to extend capability? Should every future software
>> developer that wants to use Integer/Sum/Product extend those classes
>> to get work done? What if they want to store additional state for
> What's usually done is to create visitors/matchers. Those traverse the AST,
> and either only visit, or return transformed versions of it (think e.g.
> algebraic optimization)
> A visitor will roughly look like this:
> class ASTVisitor(object):
> def visit(self, node):
> name = node.__class__.__name__.lower()
> if hasattr(self, "visit_%s" % name):
> getattr(self, "visit_%s" % name)(node)
> for child in node:
> You can of course chose another type of dispatch, using e.g. a generic
> Then you create Visitors for specific tasks - pretty-printing, evaluation,
> rewriting. Those don't have the overhead of your current design with all
> those factory-mapping stuff, and yet you aren't forced to put logic into AST
> you don't want there.
FWIW I often use John Aycock's SPARK (Scanning, Parsing, and Rewriting
Kit) for this sort of thing. It has a GenericASTTraversal which "is a
Visitor pattern according to Design Patterns."
It's apparently distributed with the python source, but it's not in
the standard library, more's the pity IMO.
There's a bit of a learning curve but it's well worth it.
More information about the Python-list