-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathj_一个简单的递归下降解析器.py
83 lines (70 loc) · 2.21 KB
/
j_一个简单的递归下降解析器.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
import re
import collections
"""定义符号替换"""
NUM = r'(?P<NUM>\d+)'
PLUS = r'(?P<PLUS>\+)'
MINUS = r'(?P<MINUS>-)'
TIMES = r'(?P<TIMES>\*)'
DIVIDE = r'(?P<DIVIDE>/)'
LPAREN = r'(?P<LPAREN>\()'
RPAREN = r'(?P<RPAREN>\))'
WS = r'(?P<WS>\s+)'
master_pat = re.compile('|'.join([NUM, PLUS, MINUS, TIMES, DIVIDE, LPAREN, RPAREN]))
Token = collections.namedtuple('Token', ['type', 'value'])
def generate_tokens(text):
scanner = master_pat.scanner(text)
for m in iter(scanner.match, None):
tok = Token(m.lastgroup, m.group())
if tok.type != WS:
yield tok
class ExpressionEvaluater():
def parse(self, text):
self.Token = generate_tokens(text)
self.tok = None
self.nexttok = None
self._advance()
return self.expr()
def _advance(self):
self.tok, self.nexttok = self.nexttok, next(self.Token, None)
def _accept(self, toktype):
if self.nexttok and self.nexttok.type == toktype:
self._advance()
return True
else:
return False
def _expect(self, toktype):
if not self._accept(toktype):
raise SyntaxError('Excepted '+ toktype)
def expr(self):
exprval = self.term()
while self._accept('PLUS') or self._accept('MINUS'):
op = self.tok.type
right = self.term()
if op == 'PLUS':
exprval += right
elif op == 'MINUS':
exprval -= right
return exprval
def term(self):
termval = self.facter()
while self._accept('TIMES') or self._accept('DIVIDE'):
op = self.tok.type
right = self.facter()
if op == 'TIMES':
termval *= right
elif op == 'DIVIDE':
termval /= right
return termval
def facter(self):
if self._accept('NUM'):
return int(self.tok.value)
elif self._accept('LPAREN'):
exprval = self.expr()
self._expect('RPAREN')
return exprval
else:
raise SyntaxError('Expect NUM or LPAREN')
if __name__ == '__main__':
e = ExpressionEvaluater()
result = e.parse('2+(9-3)*8')
print(result)