summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/harness/wptrunner/wptmanifest/node.py
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/harness/wptrunner/wptmanifest/node.py')
-rw-r--r--testing/web-platform/harness/wptrunner/wptmanifest/node.py161
1 files changed, 161 insertions, 0 deletions
diff --git a/testing/web-platform/harness/wptrunner/wptmanifest/node.py b/testing/web-platform/harness/wptrunner/wptmanifest/node.py
new file mode 100644
index 000000000..e260eeaf7
--- /dev/null
+++ b/testing/web-platform/harness/wptrunner/wptmanifest/node.py
@@ -0,0 +1,161 @@
+# 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