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