Postfix (Polish Notation) 后缀表达式的转换

我的编译器之旅 (1):

写在最前面:

研究编译原理纯粹是我的个人爱好。

大概1年半前的1个暑假,闲着在家没事做,读了1部分龙书,然后自己写了个Regular Expression(正则表达式)的分析器,有点类似Lex,根据定义的Regular Expression在内存中构建相对应的DFA。C++写的,今天看来那个时候的代码很幼稚。不过这对复习和巩固了词法分析起了很大帮助,由于自己动手写过,所以很多东西现在想来还可以很容易的推导出来。还好词法分析东西不多,最近一直在做语法分析器,也是自己的兴趣所好,感觉比较复杂。Biason和Yacc都是很不错的语法生成器。 编译器的Front-end主要就是这2部分,Back-end比较复杂。在MS的Training上也被我偶尔听到,VC++的back-end差不多已经10年没有修改过了。MS的Pheonix(凤凰)计划也正在推进中。很多学校加入了研究,如果这个成功那MS的地位将更加不可动摇了。好了不说那么多了,回忆开始。。。。。。

今天的主题是Post-order(后缀国内应该这样称呼吧)。先回顾一下Tree(树),遍历树的顺序一般有3种: Pre-order, In-order, Post-order国内应该分别称为:前缀,中缀,后缀。以二叉树为例, 对应它们的访问顺序分别为:VLR, LVR, LRV, 如果L代表左子树,V代表节点,R代表右子树的话。所以很容易看出一个表达式的正常顺序为LVR也就是中缀。如果我们以后缀的方式遍历树,那么我们最后得到的便是Post-order 也称 Polish Notation (波兰表达式).

算法 (1):

 输入中缀表达式

 输出后缀表达式

操作符Stack

如果字符是操作符(比如:+ - * /)则推入Stack。

(1)如果字符为 '( ' 左括号,那么把它压入Stack

(2)如果字符为 ')'右括号,开始弹出Stack知道弹出一个'('左括号为止。同时删除右括号和左括号两个字符。

(3)如果Stack顶部的操作符要比当前的操作副优先等级低的话,推入当前的操作符到Stack。比如: *的优先级要比+的高,所以*压入Stack。

剩下的状态不停的POP,知道Stack为空为止。

举例:

5+4*1

Operator Stack    

* +                          541

合并之后的Postfix为:541*+。

根据这个后缀表达式,很容易被转换成汇编代码为:

PUSH 5

PUSH 4

PUSH 1

POP reg1

POP reg2

MUL reg1 reg2

PUSH reg1 //4被压入Stack

POP reg1

POP reg2

ADD reg1 reg2  //9存在reg中。

最后的结果存在reg1 中。

应用这个算法,源程序中的一些数学表达式,很容易的可以被装换至汇编代码。

至此,总算向编译器迈出了勇敢的第一步。

注:算法不是我发明,很早就已经被实现了,但是编译器中涉及很多经典高效的算法,如果能够理解作者的出发点和设计思路,对自身能力将有很大的一个提高。

 

你可能感兴趣的:(计算机科学之编译器)