Selaa lähdekoodia

Added basic version of tree-to-text generator.

Sander Mathijs van Veen 14 vuotta sitten
vanhempi
sitoutus
37ecd10bdd
1 muutettua tiedostoa jossa 77 lisäystä ja 0 poistoa
  1. 77 0
      line.py

+ 77 - 0
line.py

@@ -0,0 +1,77 @@
+def generate_line(root, node_type):
+    """
+    Print an expression tree in a single text line. Where needed, add
+    parentheses.
+
+    >>> from node import Node, Leaf
+    >>> #from graph import generate_graph
+    >>> l0, l1 = Leaf(1), Leaf(2)
+    >>> n0 = Node('+', l0, l1)
+    >>> print generate_line(n0, Node)
+    1 + 2
+    >>> n1 = Node('+', l0, l1)
+    >>> n2 = Node('*', n0, n1)
+    >>> print generate_line(n2, Node)
+    (1 + 2) * (1 + 2)
+    >>> l2 = Leaf(3)
+    >>> n3 = Node('-', l2)
+    >>> n4 = Node('*', n1, n3)
+    >>> print generate_line(n4, Node)
+    (1 + 2) * -3
+    >>> #integral = Node('int', n0, n1)
+    """
+
+    operators = [
+            ('+', '-'),
+            ('*', '/'),
+            ('^', )
+            ]
+    max_assoc = len(operators)
+
+    def assoc(node):
+        """
+        Get the associativity of an operator node.
+        """
+        if isinstance(node, node_type) and len(node) > 1:
+            op = node.title()
+
+            for i, group in enumerate(operators):
+                if op in group:
+                    return i
+
+        return max_assoc
+
+    def traverse(node):
+        """
+        The expression tree is traversed using preorder traversal:
+        1. Visit the root
+        2. Traverse the left subtree
+        3. Traverse the right subtree
+        """
+        s = node.title()
+
+        if not isinstance(node, node_type):
+            return s
+
+        arity = len(node)
+
+        if arity == 1:
+            # Unary expression
+            s += traverse(node[0])
+        elif arity == 2:
+            # Binary expression
+            left, right = map(traverse, node)
+
+            # Check if there is an assiociativity conflict on either side. If
+            # so, add parentheses
+            if assoc(node[0]) < assoc(node):
+                left = '(' + left + ')'
+
+            if assoc(node[1]) < assoc(node):
+                right = '(' + right + ')'
+
+            s = left + ' ' + s + ' ' + right
+
+        return s
+
+    return traverse(root)