早上起来的时候我自顾自地想着:“为什么我们会发现学一门新的技能很困难呢?”
我认为这并不仅仅是因为辛苦的工作。我认为其中的一个原因可能是我们花了很多时间和辛苦的工作用在通过阅读文献和观看技术视频来获得知识,以致于没有足够的时间将这些知识通过实践来转化成技能。就拿游泳来说,你可以花大量的时间阅读成百上千本有关游泳的书籍,和有经验的游泳人员或者教练讨论数小时,观看可获取到的所有的教学视频,然而当你第一次跳下泳池的时候你还是会像块石头一样下沉。
底线在于:不管你认为你对这个目标知道的有多透彻——你一定要将这些知识用于实践并转化为技能。为了能够以实践方式来帮助你,我在这一系列中设置了 Part 1 和 Part 2 两个部分的练习。对了,我保证你还可以在今天的和以后的文章中看到更多的练习。
好了,让我们开始学习今天的资料,好吗? 到这为止,我们已经学习到了如何解释像"7 + 3"这样的加法算式和 "12 - 9“这样的减法算式了。 今天,我们将要讨论的是,如何解析(识别)出像"7 - 3 + 2 - 1"这样的任意加减法的数学表达式。 咱们在文章中讨论的数学表达式可以用下图这样的语法图来表达: 那么,什么是语法图呢? 语法图是对编程语言语法规则的图形化表达。 总的说来,语法图就是你可以直观的看出哪些语句是合法的语法,哪些不是。 语法图很容易阅读:只要沿着箭头指示的方向就可以了,有一些是分支的结构,有一些是循环结构。 你可以这样跟着我阅读上面的语法图:一个term,然后后面跟着任意多个『一个加减号跟着一个term』这样的结构。这样一个一个的画下来,就得到了上图。 你可能纳闷,term 是啥, 对于咱们文章里的情形,term 就是一整数(interger)了。 语法图主要为两个目的服务:
我们已经知道了,在一串标识符(token)中识别出短语(phrase)的过程叫做解析。而且解释器或者编译器的一部分就是解析器。解析也叫做『语法分析』,解析器也叫做——你猜对了——语法分析器。 参照上面的语法图,下面的数学表达式都是有效的。
因为算数表达式在不同的编程语言中都差不多一样, 我们可以用 Python 来『测试』一下我们的语法图。把你的 Python Shell 搞起来,然后输入:
没啥特别的。 『3 + 』作为一个算数表达式是不合法的。 因为根据语法图,一个减号后面必须跟着一个 term(也就是整数),否则解释器就会报错。不信你试试:
用 Python Shell 来做测试很爽,不过我们还是想自己用代码实现我们自己的解释器,对吧? 在前文(Part 1 和 Part 2)中 ,你已经知道了expr 方法就是我们的解释器和解析器工作的地方。也就是说,解析器仅识别出语法结构,确保语句符合规定,解释器在解析器工作完毕之后(也就是解析完了之后),将表达式计算出来。 下面是根据语法图写出来的解析器(parser)代码。语法图中的矩形在代码中变成了可以解析整数的 term 方法,expr 方法只负责跟随语法图:
你可以看到 expr 方法最先调用了 term 方法。然后 expr 方法进入到了一个可以执行任意多次的循环。在循环中,parser 通过 token(加号还是减号)来决定作出什么样的判断。 花点时间来证明上图的代码实现了可以解析算术表达式并遵照了上面的语法图。 解析器自己本身并不会解释任何东西:如果它识别出来一个合法的表达式它就不吱声了,如果表达式不合法,它就会抛出一个语法错误。 接下来我们修改一下 expr 方法,然后再加上解释器的代码。
因为解释器需要去计算表达式的值。我们修改了 term 方法,它现在返回了一个整数值。修改 expr 方法,现在它在恰当的位置执行加减法操作,并且整个解释的结果。尽管代码已经很直观了,我还是建议花时间好好研究一下。 好,我们继续,然后来看完整的解释器代码。 下面是你的计算器的新版代码,它可以处理包含任意多个加减法运算符的算术表达式。
把上面的代码存为 calc3.py 或者直接从 GitHub 上下载。试试看!它可以根据开始的时候我展示给你看的语法图来处理算术表达式。 下面是我用我自己的本本跑出来的结果:
记得,我在文章开始说的小练习吧? 现在我按照我说的兑现了承诺 :)。
看看你理解了多少 1、什么是语法图? 2、什么是语法分析? 3、什么是语法分析器? 你已经看到最后了,感谢阅读!别忘了做练习:) 过段时间我会带着新文章回来的,保持饥渴的求知心哦! PS. 翻译@OSC 以往文章导航: |