mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-10-22 02:25:05 +00:00
162 lines
4.2 KiB
Python
162 lines
4.2 KiB
Python
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
class NodeVisitor(object):
|
|
def visit(self, node):
|
|
# This is ugly as hell, but we don't have multimethods and
|
|
# they aren't trivial to fake without access to the class
|
|
# object from the class body
|
|
func = getattr(self, "visit_%s" % (node.__class__.__name__))
|
|
return func(node)
|
|
|
|
|
|
class Node(object):
|
|
def __init__(self, data=None):
|
|
self.data = data
|
|
self.parent = None
|
|
self.children = []
|
|
|
|
def append(self, other):
|
|
other.parent = self
|
|
self.children.append(other)
|
|
|
|
def remove(self):
|
|
self.parent.children.remove(self)
|
|
|
|
def __repr__(self):
|
|
return "<%s %s>" % (self.__class__.__name__, self.data)
|
|
|
|
def __str__(self):
|
|
rv = [repr(self)]
|
|
for item in self.children:
|
|
rv.extend(" %s" % line for line in str(item).split("\n"))
|
|
return "\n".join(rv)
|
|
|
|
def __eq__(self, other):
|
|
if not (self.__class__ == other.__class__ and
|
|
self.data == other.data and
|
|
len(self.children) == len(other.children)):
|
|
return False
|
|
for child, other_child in zip(self.children, other.children):
|
|
if not child == other_child:
|
|
return False
|
|
return True
|
|
|
|
def copy(self):
|
|
new = self.__class__(self.data)
|
|
for item in self.children:
|
|
new.append(item.copy())
|
|
return new
|
|
|
|
|
|
class DataNode(Node):
|
|
def append(self, other):
|
|
# Append that retains the invariant that child data nodes
|
|
# come after child nodes of other types
|
|
other.parent = self
|
|
if isinstance(other, DataNode):
|
|
self.children.append(other)
|
|
else:
|
|
index = len(self.children)
|
|
while index > 0 and isinstance(self.children[index - 1], DataNode):
|
|
index -= 1
|
|
for i in xrange(index):
|
|
assert other.data != self.children[i].data
|
|
self.children.insert(index, other)
|
|
|
|
|
|
class KeyValueNode(Node):
|
|
def append(self, other):
|
|
# Append that retains the invariant that conditional nodes
|
|
# come before unconditional nodes
|
|
other.parent = self
|
|
if isinstance(other, ValueNode):
|
|
if self.children:
|
|
assert not isinstance(self.children[-1], ValueNode)
|
|
self.children.append(other)
|
|
else:
|
|
if self.children and isinstance(self.children[-1], ValueNode):
|
|
self.children.insert(len(self.children) - 1, other)
|
|
else:
|
|
self.children.append(other)
|
|
|
|
|
|
class ListNode(Node):
|
|
def append(self, other):
|
|
other.parent = self
|
|
self.children.append(other)
|
|
|
|
|
|
class ValueNode(Node):
|
|
def append(self, other):
|
|
raise TypeError
|
|
|
|
|
|
class AtomNode(ValueNode):
|
|
pass
|
|
|
|
|
|
class ConditionalNode(Node):
|
|
pass
|
|
|
|
|
|
class UnaryExpressionNode(Node):
|
|
def __init__(self, operator, operand):
|
|
Node.__init__(self)
|
|
self.append(operator)
|
|
self.append(operand)
|
|
|
|
def append(self, other):
|
|
Node.append(self, other)
|
|
assert len(self.children) <= 2
|
|
|
|
def copy(self):
|
|
new = self.__class__(self.children[0].copy(),
|
|
self.children[1].copy())
|
|
return new
|
|
|
|
|
|
class BinaryExpressionNode(Node):
|
|
def __init__(self, operator, operand_0, operand_1):
|
|
Node.__init__(self)
|
|
self.append(operator)
|
|
self.append(operand_0)
|
|
self.append(operand_1)
|
|
|
|
def append(self, other):
|
|
Node.append(self, other)
|
|
assert len(self.children) <= 3
|
|
|
|
def copy(self):
|
|
new = self.__class__(self.children[0].copy(),
|
|
self.children[1].copy(),
|
|
self.children[2].copy())
|
|
return new
|
|
|
|
|
|
class UnaryOperatorNode(Node):
|
|
def append(self, other):
|
|
raise TypeError
|
|
|
|
|
|
class BinaryOperatorNode(Node):
|
|
def append(self, other):
|
|
raise TypeError
|
|
|
|
|
|
class IndexNode(Node):
|
|
pass
|
|
|
|
|
|
class VariableNode(Node):
|
|
pass
|
|
|
|
|
|
class StringNode(Node):
|
|
pass
|
|
|
|
|
|
class NumberNode(ValueNode):
|
|
pass
|