1class NodeVisitor(object): 2 def visit(self, node): 3 # This is ugly as hell, but we don't have multimethods and 4 # they aren't trivial to fake without access to the class 5 # object from the class body 6 func = getattr(self, "visit_%s" % (node.__class__.__name__)) 7 return func(node) 8 9 10class Node(object): 11 def __init__(self, data=None): 12 self.data = data 13 self.parent = None 14 self.children = [] 15 16 def append(self, other): 17 other.parent = self 18 self.children.append(other) 19 20 def remove(self): 21 self.parent.children.remove(self) 22 23 def __repr__(self): 24 return "<%s %s>" % (self.__class__.__name__, self.data) 25 26 def __str__(self): 27 rv = [repr(self)] 28 for item in self.children: 29 rv.extend(" %s" % line for line in str(item).split("\n")) 30 return "\n".join(rv) 31 32 def __eq__(self, other): 33 if not (self.__class__ == other.__class__ and 34 self.data == other.data and 35 len(self.children) == len(other.children)): 36 return False 37 for child, other_child in zip(self.children, other.children): 38 if not child == other_child: 39 return False 40 return True 41 42 def copy(self): 43 new = self.__class__(self.data) 44 for item in self.children: 45 new.append(item.copy()) 46 return new 47 48 49class DataNode(Node): 50 def append(self, other): 51 # Append that retains the invariant that child data nodes 52 # come after child nodes of other types 53 other.parent = self 54 if isinstance(other, DataNode): 55 self.children.append(other) 56 else: 57 index = len(self.children) 58 while index > 0 and isinstance(self.children[index - 1], DataNode): 59 index -= 1 60 for i in xrange(index): 61 assert other.data != self.children[i].data 62 self.children.insert(index, other) 63 64 65class KeyValueNode(Node): 66 def append(self, other): 67 # Append that retains the invariant that conditional nodes 68 # come before unconditional nodes 69 other.parent = self 70 if isinstance(other, ValueNode): 71 if self.children: 72 assert not isinstance(self.children[-1], ValueNode) 73 self.children.append(other) 74 else: 75 if self.children and isinstance(self.children[-1], ValueNode): 76 self.children.insert(len(self.children) - 1, other) 77 else: 78 self.children.append(other) 79 80 81class ListNode(Node): 82 def append(self, other): 83 other.parent = self 84 self.children.append(other) 85 86 87class ValueNode(Node): 88 def append(self, other): 89 raise TypeError 90 91 92class AtomNode(ValueNode): 93 pass 94 95 96class ConditionalNode(Node): 97 pass 98 99 100class UnaryExpressionNode(Node): 101 def __init__(self, operator, operand): 102 Node.__init__(self) 103 self.append(operator) 104 self.append(operand) 105 106 def append(self, other): 107 Node.append(self, other) 108 assert len(self.children) <= 2 109 110 def copy(self): 111 new = self.__class__(self.children[0].copy(), 112 self.children[1].copy()) 113 return new 114 115 116class BinaryExpressionNode(Node): 117 def __init__(self, operator, operand_0, operand_1): 118 Node.__init__(self) 119 self.append(operator) 120 self.append(operand_0) 121 self.append(operand_1) 122 123 def append(self, other): 124 Node.append(self, other) 125 assert len(self.children) <= 3 126 127 def copy(self): 128 new = self.__class__(self.children[0].copy(), 129 self.children[1].copy(), 130 self.children[2].copy()) 131 return new 132 133 134class UnaryOperatorNode(Node): 135 def append(self, other): 136 raise TypeError 137 138 139class BinaryOperatorNode(Node): 140 def append(self, other): 141 raise TypeError 142 143 144class IndexNode(Node): 145 pass 146 147 148class VariableNode(Node): 149 pass 150 151 152class StringNode(Node): 153 pass 154 155 156class NumberNode(ValueNode): 157 pass 158