1
+ import linked_binary_tree as LBT
2
+
3
+ class ExpressionTree (LBT .LinkedBinaryTree ):
4
+ """An arithmetic expression tree."""
5
+
6
+ def __init__ (self , token , left = None , right = None ):
7
+ """
8
+ Create an expression tree.
9
+
10
+ In a single parameter form, token should be a leaf value,
11
+ and the expression tree will have that value at an isolated node.
12
+
13
+ In a three-parameter version, token should be an operator,
14
+ and left and right should be existing ExpressionTree instances
15
+ that become the operand for binary oprator.
16
+ """
17
+ super ().__init__ ()
18
+ if not isinstance (token , str ):
19
+ raise TypeError ('Token must be a string' )
20
+ self ._add_root (token )
21
+ if left is not None :
22
+ if token not in '+-/*x' :
23
+ raise ValueError ('token must be valid operator' )
24
+ self ._attach (self .root (), left , right )
25
+
26
+ def __str__ (self ):
27
+ """Return string representation of expression"""
28
+ pieces = []
29
+ self ._paranthesize_recur (self .root (), pieces )
30
+ return '' .join (pieces )
31
+
32
+ def _paranthesize_recur (self , p , result ):
33
+ """Append piecewise representation of p's subtree to resulting list."""
34
+ if self .is_leaf (p ):
35
+ result .append (str (p .element ()))
36
+ else :
37
+ result .append ('(' )
38
+ self ._paranthesize_recur (self .left (p ), result )
39
+ result .append (p .element ())
40
+ self ._paranthesize_recur (self .right (p ), result )
41
+ result .append (')' )
42
+
43
+ def _evaluate (self ):
44
+ """Return the numeric result of expression."""
45
+ return self ._evaluate_recur (self .root ())
46
+
47
+ def _evaluate_recur (self , p ):
48
+ """Return the numeric result of subtree rooted at p"""
49
+ if self .is_leaf (p ):
50
+ return float (p .element ())
51
+ else :
52
+ op = p .element ()
53
+ left_val = self ._evaluate_recur (self .left (p ))
54
+ right_val = self ._evaluate_recur (self .right (p ))
55
+ if op == '+' : return left_val + right_val
56
+ elif op == '-' : return left_val - right_val
57
+ elif op == '/' : return left_val / right_val
58
+ else : return left_val * right_val
59
+
60
+
61
+ def build_expression_tree (tokens ):
62
+ """Returns an ExpressionTree based upon by a tokenized expression."""
63
+
64
+ S = []
65
+ for t in tokens :
66
+ if t in '+-/*x' :
67
+ S .append (t )
68
+ elif t not in '()' :
69
+ S .append (ExpressionTree (t ))
70
+ elif t == ')' :
71
+ right = S .pop ()
72
+ op = S .pop ()
73
+ left = S .pop ()
74
+ S .append (ExpressionTree (op , left , right ))
75
+
76
+ return S .pop ()
77
+
78
+ if __name__ == "__main__" :
79
+ expr = build_expression_tree (['(' , '(' , '(' , '3' , '+' ,'1' ,')' ,'x' ,'4' ,')' ,'/' ,'(' ,'(' ,'9' ,'-' ,'5' ,')' ,'+' ,'2' ,')' ,')' ])
80
+ print (expr )
81
+ print (expr ._evaluate ())
0 commit comments