paul@488 | 1 | class Expr: |
paul@488 | 2 | |
paul@488 | 3 | "An expression." |
paul@488 | 4 | |
paul@488 | 5 | def __init__(self, ops): |
paul@488 | 6 | self.ops = ops |
paul@488 | 7 | |
paul@488 | 8 | def children(self): |
paul@488 | 9 | return self.ops |
paul@488 | 10 | |
paul@488 | 11 | class Binary: |
paul@488 | 12 | |
paul@488 | 13 | "A binary operator." |
paul@488 | 14 | |
paul@488 | 15 | def __init__(self, left, op, right): |
paul@488 | 16 | self.left = left |
paul@488 | 17 | self.op = op |
paul@488 | 18 | self.right = right |
paul@488 | 19 | |
paul@488 | 20 | def children(self): |
paul@488 | 21 | return self.left, self.right |
paul@488 | 22 | |
paul@488 | 23 | class Unary: |
paul@488 | 24 | |
paul@488 | 25 | "A unary operator." |
paul@488 | 26 | |
paul@488 | 27 | def __init__(self, op, operand): |
paul@488 | 28 | self.op = op |
paul@488 | 29 | self.operand = operand |
paul@488 | 30 | |
paul@488 | 31 | def children(self): |
paul@488 | 32 | return self.operand, |
paul@488 | 33 | |
paul@488 | 34 | class Value: |
paul@488 | 35 | |
paul@488 | 36 | "A general value." |
paul@488 | 37 | |
paul@488 | 38 | def __init__(self, value): |
paul@488 | 39 | self.value = value |
paul@488 | 40 | |
paul@488 | 41 | def children(self): |
paul@488 | 42 | return () |
paul@488 | 43 | |
paul@488 | 44 | class Visitor: |
paul@488 | 45 | |
paul@488 | 46 | "Visit nodes in an expression tree." |
paul@488 | 47 | |
paul@488 | 48 | def __init__(self): |
paul@488 | 49 | self.indent = 0 |
paul@488 | 50 | |
paul@488 | 51 | def visit(self, node): |
paul@488 | 52 | |
paul@488 | 53 | # Obtain the method for the node name. |
paul@488 | 54 | |
paul@489 | 55 | fn = getattr(self, node.__name__) |
paul@488 | 56 | |
paul@488 | 57 | # Call the method. |
paul@488 | 58 | |
paul@488 | 59 | fn(node) |
paul@488 | 60 | |
paul@488 | 61 | # Visit the node's children. |
paul@488 | 62 | |
paul@488 | 63 | self.visitChildren(node) |
paul@488 | 64 | |
paul@488 | 65 | def visitChildren(self, node): |
paul@488 | 66 | self.indent += 1 |
paul@488 | 67 | for n in node.children(): |
paul@488 | 68 | self.visit(n) |
paul@488 | 69 | self.indent -= 1 |
paul@488 | 70 | |
paul@488 | 71 | def writeIndent(self): |
paul@488 | 72 | i = 0 |
paul@488 | 73 | while i < self.indent: |
paul@488 | 74 | print "", |
paul@488 | 75 | i += 1 |
paul@488 | 76 | |
paul@488 | 77 | def Expr(self, node): |
paul@488 | 78 | self.writeIndent() |
paul@488 | 79 | print "Expression..." |
paul@488 | 80 | |
paul@488 | 81 | def Binary(self, node): |
paul@488 | 82 | self.writeIndent() |
paul@488 | 83 | print "Binary operation", node.op |
paul@488 | 84 | |
paul@488 | 85 | def Unary(self, node): |
paul@488 | 86 | self.writeIndent() |
paul@488 | 87 | print "Unary operation", node.op |
paul@488 | 88 | |
paul@488 | 89 | def Value(self, node): |
paul@488 | 90 | self.writeIndent() |
paul@488 | 91 | print "Value", node.value |
paul@488 | 92 | |
paul@488 | 93 | # Test the visitor with an example expression. |
paul@488 | 94 | |
paul@488 | 95 | expr = Expr([Binary(Value(1), "+", Binary(Unary("-", Value(2)), "*", Value(3)))]) |
paul@488 | 96 | Visitor().visit(expr) |