从1+2说起
编译原理让人好奇的地方是如何将一个文本串交给机器去分析,执行,从最简单的情形来说,如何让文本串变成可执行的代码,一开始就理解一个完整的编译器是比较困难的。可以先从一个简单的情形入手。接下来就从一个最简单的表达式计算说起。
如果有一个表达式字符串“1+2”,想对这个字符串进行求值,我们该怎么办呢。实际上我们可以凭我们的经验一眼看出答案为3,可是要让计算机来做个工作又该怎么办呢。我们都知道,计算机有计算能力,如果你让计算机执行指令
mov ax,1
add ax,2
可能有的朋友会对上面这两个代码感到不理解,其实这是两条很容易理解的汇编语言,mov ax,1 是将数字1放入到寄存器ax,不理解寄存器也没有关系,只要知道这是计算机内部存放值的地方,代号叫做ax,就像我们家里存放衣服的柜子一样。
mov 衣柜,红毛衣 ,就表明要将红毛衣放入到衣柜中
mov是英文代词move的简写,移到的意思。
add 的含义是做加法运算。add AX,2 的含义是将寄存器ax中存放的值与2相加,结果又放到ax中。
原本ax中存放的是1,现在加上2,变成了3,再将3放入寄存器ax。
给出这两条汇编指令,只是让我们了解计算机的计算能力,如果对汇编语言感兴趣的读者可以去专门学习一下这门课程。这门课其实很有趣,学完之后就可以完整地理解为什么计算机会具有强大的计算能力。
回到我们的主题,学习编译原理,其实并不需要掌握汇编语言,因为有更高级的语言可以使用,比如C语言,php语言,python语言等。这些高级语言最终会将源代码变成机器可以执行的指令。学习编译原理的目的就是要弄清楚这些高级语言该如何制作出来。我们在开发新的语言是就以这些已经存在的高级语言来编写我们自己的编译器,比如php语言是用C语言开发出来的。
c语言如何求解1+2
接着说表达式字符串“1+2”的求值问题。如果读者学过C语言,要解决这个问题很容易,可以这样写一条语句
int x=1+2;
对于没有学过C语言的读者,做一个简单的说明:int是英文integer的简写。int x表示有一个叫做x的整形变量,和上面说的寄存器类似,变量x只是一个存放值的容器。x=1+2表示将1+2的结果放入容器x. 容器x中现在存放的就是3。
看到这里,有的朋友可能会感到奇怪x=1+2与字符串“1+2”没有什么不一样呢? 仔细看一下,“1+2”是一个完整的字符串,x=1+2中的1是独立的整数值,+是独立的操作符,2也是一个独立的整数值。
编译器的要完成的第一个工作是将字符串“1+2”拆分成独立的三个部分:整数1,操作符+,整数2。这个工作的专门术语叫做“词法分析”。
对于字符串“1+2”来说,读者凭肉眼就可以完成词法分析工作。更复杂的词法分析器留在后面讨论。下面说一下完成词法分析后,接下来要做的工作是要完成计算工作,那么整数1,操作符+,整数2合在一起叫做什么呢,叫做表达式,识别出表达式的工作称作“语法分析”
判断1+2是一个合法的算术表达式,这是语法分析的工作,1*2也是一个合法的算术表达式,1++2不是一个合法的表达式。这都是由语法分析器完成的。补充说明一下,如果需要,也可以将1++2定义为一个合法的表达式,后面讨论语法分析器时再做详细的研究
得到一个合法的表达式后接下来的工作是求值。也就是翻译成机器可以执行的指令的过程。这一个工作可以有很多种不同的实现方法,常见的有两种
一种叫解释执行basic语言是代表,一种叫编译执行,C语言是代表。现在还有将这两种办法结合起来的做法,叫做中间代码法,java语言是代表
如果是解释执行,碰到+号时就调用执行,得到结果。如果是编译执行,就要先编译成要执行的语言,为了简单起见,可以假定就编译成前面提到的汇编语言的形式:
mov ax,1
add ax,2
实际上,汇编语言的指令与机器指令是一一对应的,所以我们这里就用汇编语言代替机器语言来说明问题。
未完待续