-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlab_4 (without IF).py
95 lines (85 loc) · 3.08 KB
/
lab_4 (without IF).py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import re
import operator as op
class AST:
def __init__(self, expression=""):
self.expression = expression
self.root = None
def __repr__(self):
return "[ {} ] = {}".format(self.expression, self.evaluate()) if self.expression else "Missing expression"
def build(self):
if not self.expression: return None
queue = list(filter(lambda x: x, re.split(r"(\+|-|\*|/|\^|=|\(|\))", re.sub(r"(--)+", "--", self.expression.replace(" ", "")))))
i = 0
while i < len(queue):
if queue[i] == "-" and (i == 0 or queue[i-1] in list(ops) + ["("]):
if i > 0 and queue[i-1] == "(":
queue[i:i+1] = ["-1", "*"]
else:
if queue[i+1] == "(":
j = find_pair(i+1, queue)
queue[j:j+1] = [")", ")"]
else:
queue[i+1:i+2] = [queue[i+1], ")"]
queue[i:i+1] = ["(", "-1", "*"]
i += 1
depth = 0
prev = None
for item in queue:
if item in "()":
depth += 4 * [-1, 1][item in "("]
continue
p = prec.get(item, float("inf")) + depth * 4
node = Node(item, p)
if not prev:
pass
elif item not in ops:
prev.right = node
node.parent = prev
elif not prev.parent:
prev.parent = node
node.left = prev
else:
while prev.precedence >= p:
if prev.parent:
prev = prev.parent
else: break
else:
node.left = prev.right
prev.right.parent = node
prev.right = node
node.parent = prev
prev = node
continue
prev.parent = node
node.left = prev
prev = node
while prev.parent: prev = prev.parent
return prev
def evaluate(self):
self.root = self.build()
return self.root.evaluate() if self.root else None
class Node:
def __init__(self, item, precedence=0):
self.item = item
self.precedence = precedence
self.parent = self.left = self.right = None
def evaluate(self):
try:
try: return float(var.get(self.item, self.item))
except: return float(ops[self.item](self.left.evaluate(), self.right.evaluate()))
except:
return self.item
def find_pair(x, a):
s = 0
for i in range(x, len(a)):
if a[i] == "(": s += 1
if a[i] == ")": s -= 1
if not s: return i
def memorize(a, b):
var[a] = var.get(b, float(b))
return var[a]
var = {}
prec = {"+":1, "-":1, "*":2, "/":2, "^":3, "=":4}
ops = {"+":op.add, "-":op.sub, "*":op.mul, "/":op.truediv, "^":op.pow, "=":memorize}
ast = AST("6 * x = (-y = 3)^3")
print(ast)