| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- 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)
|