1. import re
  2. import collections
  3. # 写将要匹配的正则
  4. NUM = r'(?P<NUM>\d+)'
  5. PLUS = r'(?P<PLUS>\+)'
  6. MINUS = r'(?P<MINUS>-)'
  7. TIMES = r'(?P<TIMES>\*)'
  8. DIVIDE = r'(?P<DIVIDE>/)'
  9. LPAREN = r'(?P<LPAREN>\()'
  10. RPAREN = r'(?P<RPAREN>\))'
  11. WS = r'(?P<WS>\s+)'
  12. # 构建compile()对象
  13. master_pat = re.compile('|'.join([NUM, PLUS, MINUS, TIMES, DIVIDE, LPAREN, RPAREN, WS]))
  14.  
  15. # 构建一个生成器
  16. def gennerate_tokens(text):
  17. Token = collections.namedtuple('Token', ['type', 'value']) # 构建一个元组
  18. scanner = master_pat.scanner(text) # 创建scanner()对象
  19. # 进行扫描
  20. for m in iter(scanner.match, None):
  21. tok = Token(m.lastgroup, m.group()) # 添加元组
  22. if tok.type != 'WS':
  23. yield tok
  24.  
  25. class ExpressionEvaluator(object):
  26. def parse(self, text):
  27. self.tokens = gennerate_tokens(text)
  28. self.tok = None
  29. self.nexttok = None
  30. self._advance()
  31. return self.expr()
  32. def _advance(self):
  33. # 进行往下移动
  34. self.tok, self.nexttok = self.nexttok, next(self.tokens, None)
  35. def _accept(self, toktype):
  36. # 判断下一个节点的类型是否正确
  37. if self.nexttok and self.nexttok.type == toktype:
  38. self._advance() # 如果节点类型正确,那么就往下一个节点
  39. return True
  40. else:
  41. return False
  42. def _except(self, toktype):
  43. # 用来判断是否是理想环境(如括号是否封闭)
  44. if not self._accept(toktype):
  45. raise SyntaxError('Excepted' + toktype)
  46. def expr(self):
  47. """ 进行加减操作 """
  48. exprval = self.term()
  49. while self._accept('PLUS') or self._accept('MINUS'):
  50. op = self.tok.type # 获取当前操作类型
  51. right = self.term() # 先计算右边部分
  52. if op == 'PLUS':
  53. exprval += right
  54. elif op == 'MINUS':
  55. exprval -= right
  56. return exprval
  57. def term(self):
  58. """ 进行乘除操作 """
  59. termval = self.factor()
  60. while self._accept('TIMES') or self._accept('DIVIDE'):
  61. op = self.tok.type # 获取当前操作
  62. right = self.factor() # 计算右边部分
  63. if op == 'TIMES':
  64. termval *= right
  65. elif op == 'DIVIDE':
  66. termval /= right
  67. return termval
  68. def factor(self):
  69. if self._accept('NUM'):
  70. return int(self.tok.value)
  71. elif self._accept('LPAREN'):
  72. exprval = self.expr()
  73. self._except('RPAREN')
  74. return exprval
  75. else:
  76. raise SyntaxError("Excepted NUMBER or LPAREN...")
  77.  
  78. def descent_parser():
  79. e = ExpressionEvaluator()
  80. print(e.parse(''))
  81. print(e.parse('2 + 3'))
  82. print(e.parse('2 - 3'))
  83. print(e.parse('2 + 3 * 5'))
  84. print(e.parse('4 - 6 / 2'))
  85. print(e.parse('2 + (3 + 1)/2'))
  86.  
  87. # 入口函数
  88. if __name__ == "__main__":
  89. descent_parser()
  90. """
  91. D:\笔记\python电子书\Python3>python index.py
  92. 2
  93. 5
  94. -1
  95. 17
  96. 1.0
  97. 4.0
  98. """

干货-递归下降分析器 笔记(具体看Python Cookbook, 3rd edition 的2.19章节)的更多相关文章

  1. 入门python有什么好的书籍推荐?纯干货推荐,你值得一看 python基础,爬虫,数据分析

    Python入门书籍不用看太多,看一本就够.重要的是你要学习Python的哪个方向,或者说你对什么方向感兴趣,因为Python这门语言的应用领域比较广泛,比如说可以用来做数据分析.机器学习,也可以用来 ...

  2. python cookbook 小结

    最近一直在看python cookbook.这本书主要讲的是python 语言的一些编程素材.正如它的名字一样,烹饪书.就好像再讲如何处理食材(各种类型的数据),然后再煮菜(算法).打个比方,煮菜随便 ...

  3. Python实现JSON生成器和递归下降解释器

    Python实现JSON生成器和递归下降解释器 github地址:https://github.com/EStormLynn/Python-JSON-Parser 目标 从零开始写一个JSON的解析器 ...

  4. Python技法:实现简单的递归下降Parser

    1. 算术运算表达式求值 在上一篇博文<Python技法:用re模块实现简易tokenizer>中,我们介绍了用正则表达式来匹配对应的模式,以实现简单的分词器.然而,正则表达式不是万能的, ...

  5. Atitit 表达式原理 语法分析 原理与实践 解析java的dsl  递归下降是现阶段主流的语法分析方法

    Atitit 表达式原理 语法分析 原理与实践 解析java的dsl  递归下降是现阶段主流的语法分析方法 于是我们可以把上面的语法改写成如下形式:1 合并前缀1 语法分析有自上而下和自下而上两种分析 ...

  6. TINY语言采用递归下降分析法编写语法分析程序

    目录 自顶向下分析方法 TINY文法 消左提左.构造first follow 基本思想 python构造源码 运行结果 参考来源:聊聊编译原理(二) - 语法分析 自顶向下分析方法 自顶向下分析方法: ...

  7. 【Python五篇慢慢弹】数据结构看python

    数据结构看python 作者:白宁超 2016年10月9日14:04:47 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给出的pythondoc ...

  8. 《Python cookbook》 “定义一个属性可由用户修改的装饰器” 笔记

    看<Python cookbook>的时候,第9.5部分,"定义一个属性可由用户修改的装饰器",有个装饰器理解起来花了一些时间,做个笔记免得二刷这本书的时候忘了 完整代 ...

  9. 递归下降和LL(1)语法分析

    什么是自顶向下分析法 在语法分析过程中一般有两种语法分析方法,自顶向下和自底向上,递归下降分析和LL(1)都属于是自顶向下的语法分析 自顶向下分析法的过程就像从第一个非终结符作为根节点开始根据产生式进 ...

随机推荐

  1. FMX取得屏分辨率

    procedure Tfrm_Main.FormCreate(Sender: TObject); var ScreenSvc: IFMXScreenService; Size: TPointF; be ...

  2. Eclipse 通过JPA自动生成注解实体

    hibernate是JPA最常用的实现之一,而且hiberante自身也对注释语法进行了支持.现在再不用去看那一堆堆的XML映射了.而且eclipse还提供了从数据库直接生成Entity Class的 ...

  3. sublime text3 key

    Sublime Text 3 3126 注册码 第一个测试通过 —– BEGIN LICENSE —– Michael Barnes Single User License EA7E-821385 8 ...

  4. 安装 aconda 后Linux的终端界面前部出现(base)字样

    aconda 是做什么用的这里就不说了,一般玩Python的都知道这东西,最早接触这东西是因为它把NVIDIA中cuda计算和Python互连的一个库拿下了,是买下来了还是专业,还是唯一合作的也就记不 ...

  5. tmux学习

    1.基本命令: http://blog.chinaunix.net/uid-26285146-id-3252286.html (重要) http://blog.csdn.net/longxibendi ...

  6. VMware网络连接IP设置

    网络配置(仅主机模式) 一.改变虚拟机IP地址达到联网目的 仅主机模式,第一步,打开我的电脑属性,查看VMt1网卡IP设置,设置一个区段:192.168.xx.aa       xx.aa自由设置,简 ...

  7. tshark CAN协议分析初试

    /********************************************************************************* * tshark CAN协议分析初 ...

  8. 【leetcode】290. Word Pattern

    problem 290. Word Pattern 多理解理解题意!!! 不过博主还是不理解,应该比较的是单词的首字母和pattern的顺序是否一致.疑惑!知道的可以分享一下下哈- 之前理解有误,应该 ...

  9. 【leetcode】234. Palindrome Linked List

    234. Palindrome Linked List 1. 使用快慢指针找中点的原理是fast和slow两个指针,每次快指针走两步,慢指针走一步,等快指针走完时,慢指针的位置就是中点.如果是偶数个数 ...

  10. pytorch实现rnn并且对mnist进行分类

    1.RNN简介 rnn,相比很多人都已经听腻,但是真正用代码操练起来,其中还是有很多细节值得琢磨. 虽然大家都在说,我还是要强调一次,rnn实际上是处理的是序列问题,与之形成对比的是cnn,cnn不能 ...