上一篇文章中,我们一起实现了计算器的加法功能。

并且,在文末给大家留下了一些练习:

让解释器支持减法运算;

让解释器支持多位整数的运算,例如:12+36;

添加一个方法,让解释器能够处理用户所输入表达式中的空格。

我建议大家先独自尝试完成这些练习,再继续本篇文章的学习。

当然,如果你如果已经尽力,但是没能够完成练习,那么,这篇文章将会给你带来很大的收获。

在开始这篇文章的主体内容之前,我先引用原文中的一个小故事。

这个故事它所包含的哲理适用于各行各业。

《高效思考的5个要素》的作者 Burger 和 Starbird 在书中分享了一个关于他们观看国际知名小号演奏家 Tony Plog 为多才多艺的小号演奏者举办大师课的故事。学生们首先演奏了复杂的音乐章节,他们表演的都很棒。但是,随后他们被要求表演非常基础、简单的音符。当他们演奏那些音符时,比起之前演奏的复杂乐章显得有些稚嫩。当他们完成演奏之后,大师也演奏了相同的音符。但大师演奏这些音符时听起来并不稚嫩,差异非常明显。Tony 解释道:掌握简单音符的演奏,让演奏者可以更完美地掌握复杂的乐章。

这个故事的结论:要想成为真正的艺术家,你必须集中精力掌握简单、基础的概念。

再精密的仪器也都是由简单的一个一个零件巧妙的组合而成。

在任何一个领域,你必须先掌握这些简单基础的概念,再通过灵活的运用才能够成为这个领域的高手。

接下来,我们再继续依靠我们所学过的Python3基础知识,来为我们的计算器或者说算术表达式的解释器添加更多的功能。

根据之前的练习要求,我们逐步来完成这些任务。

一、增加保存当前字符的变量

因为我们是逐个获取字符进行验证,一个多位数字需要多次获取才能够组成完整的数字生成记号,那么在记号生成之前,我们需要先使用一个变量保存字符,进行验证。

示例代码:(class Interpreter)

def __init__(self, text):

...省略其它代码...

self.current_char = self.text[self.position] # 设置当前字符为指定位置的字符

二、增加获取下一个字符的方法

因为新增加的功能中表达式中字符的数量不再是3个,而是无法固定的数量。

数字部分可能是多位数字,并且表达式中可能包含任意数量的空格。

这样的话,我们需要对字符进行循环验证,会经常用到获取下一个字符的方法。

那么,经常用到的重复的方法,我们把它抽象成一个独立的方法。

示例代码:

def advance(self): # 定义获取下一个字符的方法

self.position += 1 # 获取字符的位置自增

if self.position >= len(self.text): # 如果位置到达字符串的末尾

self.current_char = None # 设置当前字符为None值

else: # 否则

self.current_char = self.text[self.position] # 设置当前字符为指定位置的字符

三、增加跳过空格的方法

如果遇到空格,无论是单个还是连续多个,我们都应该将其跳过。

示例代码:

def skip_whitespace(self): # 定义跳过空格的方法

while self.current_char is not None and self.current_char.isspace(): # 如果当前字符不是None值并且当前字符是空格

self.advance() # 获取下一个字符

四、增加获取多位数字的方法

如果获取到的字符是数字,无论是单个还是连续多个,我们都将它们连接起来,转为整数类型后返回。

示例代码:

def long_integer(self): # 获取多位数字

result = ''

while self.current_char is not None and self.current_char.isdigit(): # 如果当前字符不是None值并且当前字符是数字

result += self.current_char # 连接数字

self.advance() # 获取下一个字符

return int(result) # 返回数字

五、修改词法分析器的代码

在新版本的词法分析器中,我们只需要根据当前字符的类型进行不同的处理。

示例代码:

def get_next_token(self):

while self.current_char is not None: # 如果当前字符不是None值

if self.current_char.isspace(): # 如果当前字符是空格

self.skip_whitespace() # 跳过所有空格

continue

if self.current_char.isdigit(): # 如果当前字符是整数

return Token(INTEGER, self.long_integer()) # 获取完整的数字创建记号对象并返回

if self.current_char == '+': # 如果当前字符是加号

self.advance() # 跳到下一字符

return Token(PLUS, self.current_char) # 创建记号对象并返回

if self.current_char == '-': # 如果当前字符是减号

self.advance() # 跳到下一字符

return Token(MINUS, self.current_char) # 创建记号对象并返回

self.error() # 如果以上都不是,则抛出异常。

return Token(EOF, None) # 遍历结束返回结束标识创建的记号对象

这一次,词法分析器的代码更加清晰。

六、修改表达式计算方法

这里我们添加减法的支持。

def expr(self):

self.current_token = self.get_next_token()

left = self.current_token

self.eat(INTEGER)

operator = self.current_token

if operator.value_type == PLUS: # 如果运算符的类型是加法

self.eat(PLUS) # 验证加法运算符

else: # 否则

self.eat(MINUS) # 验证减法运算符

right = self.current_token

self.eat(INTEGER)

if operator.value_type == PLUS: # 如果运算符的类型是加法

result = left.value + right.value # 进行加法运算

else: # 否则

result = left.value - right.value # 进行减法运算

return result

上方代码中,添加注释的部分是更新的内容。

到这里,我们就完成了所有目标功能。

最后,我们仍然需要掌握一些概念。

在上一篇文章中,我们了解了在两个重要的概念: Token(记号) 和 Lexical Analyzer(词法分析器)。

这一篇文章中,我们来简单了解一下 lexeme(词位)、parsing(语法分析)和 parser(语法分析器)。

1、 lexeme(词位)

词位的中文解释是语言词汇的基本单位。

在这里,lexeme就是组成 token 的字符序列。

以当前的案例来说,词位就是数字、加号和减号:

记号

词位

INTEGER

1,12,666,69,8,0,3568

PLUS

+

MINUS

2、parsing(语法分析)和 parser(语法分析器)。

我们所编写的代码中,“ expr()”方法是真正的对一个算术表达式进行解释的地方。

但是,在对一个算术表达式进行解释之前,我们需要先识别短语的类型,比如是加法表达式还是减法表达式。

“ expr()”方法本质上就是:先从“ get_next_token()” 方法获取token流,找到token流中的特定的结构,或者说识别出特定的短语,然后,解释识别出的短语,生成算术表达式的结果。

找到token流中特定结构的过程,或者说,识别token 流中特定短语的过程称之为Parsing(语法分析)。

解释器或编译器中完成语法分析的部分,叫做Parser(语法分析器)。

现在我们知道“ expr()”方法是解释器中既做了 Parsing(语法分析),又做了Interpreting(解释)的部分。

“ expr()”方法首先尝试识别(Parsing)token流中的[INTEGER>>PLUS>>INTEGER]结构或者[INTEGER>>MINUS>>INTEGER] 结构的短语,成功识别其中一种短语后,对短语进行解释,并将两整数相加或相减的结果返回。

以上就是《一起来写一个简单的解释器》系列文章的第二篇内容。

在这篇内容的基础上,大家可以尝试进行以下功能的扩展:

让解释器支持乘法运算;

让解释器支持除法运算;

让解释器支持任意多加法和减法运算,例如:3+7-4-2+8。

而且,当学习完这篇文章,请大家自我检查一下,是否了解了以下内容:

什么是 Lexeme(词位)?

找出Token流中特定结构的过程叫什么?或者说,从 Token流中识别出特定短语的过程叫什么?

解释器或编译器中做 parsing(语法分析)部分的叫什么?

项目源代码下载:【点此下载】

python输入两个数字的成语_一起来写个简单的解释器(2)相关推荐

  1. python输入两个数字的成语_请用 Python 语言编写一个简易的猜数字游戏程序。

    import random answer = random.randint(1,10) print('猜数游戏 ') num=input('请输入你猜测的数字 n') guess=int(num) n ...

  2. python输入两个数字、输出和差积商_C语言程序设计:输入两个整数,计算并输出它们的和、积、差、商和余数各是多少?...

    展开全部 #include void main(){ int a,b; printf("请输入两个数字"); scanf("%d",&a); scanf ...

  3. python读取文本两个数字的成语_【十分钟Python知识点】让文本数据更加生动——词云工具推荐...

    stylecloud 是一个 Python 包,它基于流行的 word_cloud 包,并添加了一些有用的功能,从而创建出独特的词云.stylecloud 具备以下特点:为词云提供(任意大小)的图标形 ...

  4. python读取文本两个数字的成语_只要2步!将搜狗词库(scel)转为Python可读的文本...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 将搜狗词库(scel)转化为python可读的文本(text)的方法方法 1. 利用R语言(方法简单) ① 载入词库(R语言) library(Rword ...

  5. python输入10个数字排序案例_介绍十个Python小案例,新手入门就在这里

    今天给大家分享十个Python入门级别的小案例. 案例一:排列组合 要求: 将4个数字可能组成的所有互不相同且无重复数字的排列组合列出. 分析: 排列就好了 代码: 案例二:阶梯求和 要求: 企业实行 ...

  6. python输入两个坐标求距离_计算python中*多组*地理坐标之间的距离

    编辑: here's a simple notebook example 一般方法,假设您有一个包含点的DataFrame列,并且您想要计算所有这些列之间的距离(例如,如果您有单独的列,则首先将它们组 ...

  7. python 使用input函数输入两个数字,比较两个数字的大小,并输出较大的数

    # python 使用input函数输入两个数字,比较两个数字的大小,并输出较大的数 """ 任务 1.定义变量x和y,用于存放输入的两个数值 2.判断x与y是否相等,相 ...

  8. Python如何计算两个数字之和是多少?

    python是一门非常受欢迎的编程语言,具有多种优势,简单易学.用途广泛.免费开源.易读易维护.可移植,且具有丰富的库,在诸多领域都得到了广泛的应用.而在python中,求两个数的和是非常常见的需求, ...

  9. Python---编写一个函数,提示输入两个数字a,b,并进行a与b的除法运算。

    题目: 编写一个函数,提示输入两个数字 a,b ,并进行 a 与 b 的除法运算,把运算结果打印出来.要求对输入和程序进行检测,可以排除所有的错误. 源代码: def devision():try:a ...

最新文章

  1. k-d tree树 近邻算法
  2. 求链式线性表的倒数第K项(堆栈解法)
  3. 3种骚操作,教你查看 Java 字节码!
  4. 从“不务正业”到“回归本行”,“中年”雅戈尔的偶然与必然
  5. [译]多线程网络服务模型
  6. MySQL之命令mysql -- MySQL服务器的客户端工具
  7. C++程序设计基础(7)位运算
  8. border做三角形
  9. 手贱拆笔记本清灰记录
  10. C++--第24课 - 专题四经典问题解析
  11. C++数据库编程 ODBC连接SQL Server数据库
  12. Linux如何安装iperf软件,【iperf】iperfforLinux-最笨下载
  13. Nginx-负载均衡部署
  14. C#开发工控上位机编程 csdn_5种将死的编程语言
  15. c语言json使用,cJSON使用(二)
  16. android iccid获取不完整,Android调用getSimSerialNumber获取iccid不完整
  17. CSS中id选择器和类选择器的区别
  18. 一些前端入门者可能需要的网站
  19. H5常见问题 微信踩过得坑
  20. 分位数Quantiles

热门文章

  1. 三相电压型整流器的设计与仿真
  2. repo:.repo/manifest/default.xml详解
  3. 用OpenCV的SVM实现简单的手势识别(切水果)[附源码]
  4. 【python】准点跑路人必备小程序~ 不信你用不到
  5. kaggle住房预测项目——第1部分
  6. Sovit3D钢铁厂三维可视化 智慧钢铁厂的转型升级
  7. 门窗软件测试自学,Revit 系列讲座第一季-路文虎
  8. c++版MC(我的世界)
  9. 如何在移动端app中应用字体图标icon fonts
  10. 视觉里程计--视觉slam7.1/相机运动估计视觉算法