干货-递归下降分析器 笔记(具体看Python Cookbook, 3rd edition 的2.19章节)
Posted on 2018-11-22 23:20 闪电龟龟 阅读(325) 评论(0) 编辑 收藏 举报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 """
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现