-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.py
121 lines (99 loc) · 2.69 KB
/
parser.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
def prod(rules, proc = lambda a,s: a):
return {
"rules": rules,
"proc": proc
}
def add(t, s):
a = s.pop()
b = s.pop()
s.append(b + a)
def minus(t, s):
a = s.pop()
b = s.pop()
s.append(b - a)
def multiply(t, s):
a = s.pop()
b = s.pop()
s.append(b * a)
def divide(t, s):
a = s.pop()
b = s.pop()
s.append(b / a)
def power(t, s):
a = s.pop()
b = s.pop()
s.append(b ** a)
lang = {
"S": [prod(["E"])],
"E": [prod(["T", "D"])],
"D": [
prod(["+", "T", "D"], add),
prod(["-", "T", "D"], minus),
prod([])
],
"T": [prod(["P", "R"])],
"R": [
prod(["*", "P", "R"], multiply),
prod(["/", "P", "R"], divide),
prod([])
],
"P": [prod(["F", "Q"])],
"Q": [
prod(["^", "F", "Q"], power),
prod([])
],
"F": [
prod(["(", "E", ")"]),
prod(["C"])
],
"C": [prod(["."], lambda a,s: s.append(a[0]))]
}
def parse(message, lang):
message = message.replace(' ', '')
stack = []
done, tree, idx = make_tree("S", 0, stack, message, lang)
if not done or idx < len(message)-1:
raise Exception("syntax error")
else:
return stack[0]
def is_terminal(token, lang):
return token not in lang.keys()
def make_tree(non_terminal, index, stack, message, lang):
if is_terminal(non_terminal, lang):
raise Exception(f'{non_terminal} is not a non-terminal')
for production in lang[non_terminal]:
done, tree, idx = try_production(
production['rules'],
index,
stack,
message,
lang
)
if done:
production['proc'](tree, stack)
return True, tree, idx
return False, None, None
def try_production(production, index, stack, message, lang):
childs = []
for term in production:
if is_terminal(term, lang):
if index >= len(message):
return False, None, None
elif term == message[index]:
childs.append(message[index])
index += 1
elif term == '.':
childs.append(int(message[index]))
index += 1
else:
return False, None, None
else:
done, tree, idx = make_tree(term, index, stack, message, lang)
if not done: return False, None, None
if type(tree) is not list: childs.append(tree)
elif len(tree) == 1: childs.append(tree[0])
elif len(tree) > 0: childs.append(tree)
index = idx
return True, childs, index
message = input()
print(parse(message, lang))