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+)' # 构建compile()对象 master_pat = re.compile('|'.join([NUM, PLUS, MINUS, TIMES, DIVIDE, LPAREN, RPAREN, WS])) # 构建一个生成器 def gennerate_tokens(text): Token = collections.namedtuple('Token', ['type', 'value']) # 构建一个元组 scanner = master_pat.scanner(text) # 创建scanner()对象 # 进行扫描 for m in iter(scanner.match, None): tok = Token(m.lastgroup, m.group()) # 添加元组 if tok.type != 'WS': yield tok class ExpressionEvaluator(object): def parse(self, text): self.tokens = gennerate_tokens(text) self.tok = None self.nexttok = None self._advance() return self.expr() def _advance(self): # 进行往下移动 self.tok, self.nexttok = self.nexttok, next(self.tokens, None) def _accept(self, toktype): # 判断下一个节点的类型是否正确 if self.nexttok and self.nexttok.type == toktype: self._advance() # 如果节点类型正确,那么就往下一个节点 return True else: return False def _except(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.factor() while self._accept('TIMES') or self._accept('DIVIDE'): op = self.tok.type # 获取当前操作 right = self.factor() # 计算右边部分 if op == 'TIMES': termval *= right elif op == 'DIVIDE': termval /= right return termval def factor(self): if self._accept('NUM'): return int(self.tok.value) elif self._accept('LPAREN'): exprval = self.expr() self._except('RPAREN') return exprval else: raise SyntaxError("Excepted NUMBER or LPAREN...") def descent_parser(): e = ExpressionEvaluator() print(e.parse('2')) print(e.parse('2 + 3')) print(e.parse('2 - 3')) print(e.parse('2 + 3 * 5')) print(e.parse('4 - 6 / 2')) print(e.parse('2 + (3 + 1)/2')) # 入口函数 if __name__ == "__main__": descent_parser() """ D:笔记python电子书Python3>python index.py 2 5 -1 17 1.0 4.0 """