-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathparser.py
92 lines (69 loc) · 2.04 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
import enum
import re
class TokenType(enum.Enum):
T_NUM = 0
T_PLUS = 1
T_MINUS = 2
T_MULT = 3
T_DIV = 4
T_LPAR = 5
T_RPAR = 6
T_END = 7
class Node:
def __init__(self, token_type, value=None):
self.token_type = token_type
self.value = value
self.children = []
def lexical_analysis(s):
mappings = {
'+': TokenType.T_PLUS,
'-': TokenType.T_MINUS,
'*': TokenType.T_MULT,
'/': TokenType.T_DIV,
'(': TokenType.T_LPAR,
')': TokenType.T_RPAR}
tokens = []
for c in s:
if c in mappings:
token_type = mappings[c]
token = Node(token_type, value=c)
elif re.match(r'\d', c):
token = Node(TokenType.T_NUM, value=int(c))
else:
raise Exception('Invalid token: {}'.format(c))
tokens.append(token)
tokens.append(Node(TokenType.T_END))
return tokens
def match(tokens, token):
if tokens[0].token_type == token:
return tokens.pop(0)
else:
raise Exception('Invalid syntax on token {}'.format(tokens[0].token_type))
def parse_e(tokens):
left_node = parse_e2(tokens)
while tokens[0].token_type in [TokenType.T_PLUS, TokenType.T_MINUS]:
node = tokens.pop(0)
node.children.append(left_node)
node.children.append(parse_e2(tokens))
left_node = node
return left_node
def parse_e2(tokens):
left_node = parse_e3(tokens)
while tokens[0].token_type in [TokenType.T_MULT, TokenType.T_DIV]:
node = tokens.pop(0)
node.children.append(left_node)
node.children.append(parse_e3(tokens))
left_node = node
return left_node
def parse_e3(tokens):
if tokens[0].token_type == TokenType.T_NUM:
return tokens.pop(0)
match(tokens, TokenType.T_LPAR)
expression = parse_e(tokens)
match(tokens, TokenType.T_RPAR)
return expression
def parse(inputstring):
tokens = lexical_analysis(inputstring)
ast = parse_e(tokens)
match(tokens, TokenType.T_END)
return ast