编译的学习和实践日志三[国庆节中的左递归]

今天,哦不,昨天是国庆节的说。大家都很高兴,我也很高兴,就高兴得忘记写日志了。跟大家一样,
看了国庆的阅兵式和群众游行,不知道央视的技术是不是变差劲了,没有99年看的时候那么震撼,不过
仍然很激动,尤其是唱国歌的时候,大家一起唱,那种气势,振奋人心。有个有趣的现象大家发现了没
。就是在阅兵现场,有好多大屏幕,放映的是当前摄像机拍摄的内容,然后呢,有的时候摄像机会对上
大屏幕,这样大屏幕里面会有一个摄像机拍摄的大屏幕里面还有摄像机拍摄的大屏幕中的摄像机拍摄的
大屏幕…这个递归貌似是会死掉的,正如文法(上下文无关法)中的左递归。
左递归,就是刚刚看的内容。文法是个很强大的东东,可以用来描述一门语言(故这种被称为元语言)
。强大到用目前的编程体系(更大的讲叫计算机体系)无法处理它的某些部分,其中就有左递归。For
Example:

代码:expr -> expr rest | number
rest -> + number | – number |空
number -> 0 |…|9

这些生成式可准配表达个位数的加减法规则。但是如果要转化为编程语言来处理的话,你会发现第一个

式子右部(->符号后面的统称右部,反之为左部)第一个expr无法正常处理,因为它跟生成式的左部是一

样的,一旦去匹配的时候,这个式子又从左侧开始了,这样就陷入了一个死循环,文法上称此现象为左

递归。

问题出来了,解决办法肯定有的,既然没有新的体系来处理,那么咱们就把式子变形为当前可处理的形

式,最简单的把number和expr一换变成这样:

代码:expr -> number rest
rest -> + expr | -expr| 空
number -> 0 |…|9

这样看起来似乎就OK了。但事实远没有这么简单,我们在翻译运算式子到编程语言可处理的方式时,往往要采用后缀表达式来解决运算符的优先级问题,后缀表达式的运算符号要在每个子式子的最后处理。如

9+5-2 –〉95+2-

而刚才的式子是右个递归,由于递归,符号并不会在当前式子跳入下个递归前处理,而是运算完下个递归后再处理,这样就导致所有的符号都在最后

9+5-2 –> 952-+

这的确很糟糕,于是我又得用新的办法来解决它,只要在跳入下个递归前把符号处理掉就可以了,但是我们的rest产生式子在处理expr时就陷入递归了。所以我们要把处理符号和递归拆开,like this

代码:expr -> number rest
rest -> + term rest | – term rest| 空
number -> 0 |…|9

这 样就可以在rest跳入递归前在term后面就可以把符号处理完毕了。呵呵是不是很头大,我们不得不承认那些计算机科学家/工作者具有多么高的智慧和付出 了多少多少劳动才能换来今天我们一点编译运行就能生成程序的方便,向那些先驱者们致敬,我们会站在前辈的肩膀上,把这个世界变得更美好的。

祖国与我们同在

计算机与我们同在

davelv

2009-10-02

This entry was posted in 编译与语言 and tagged . Bookmark the permalink.

One Response to 编译的学习和实践日志三[国庆节中的左递归]

  1. ghbst says:

    [e03]好家伙,阁下已经站得很高 了

回复 ghbst 取消回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注