碎碎念
为什么这本书叫做 龙书(Dragon book)
?
这本书很有意思,它的书名是 《Compilers: Principles, Techniques, and Tools》
,也就是编译器的原则、技术和工具。但它却画出了一个恐龙和骑士,恐龙身上写的是 Complexity of Compiler Design
,也就是复杂的编译器设计
,骑士的盾上写的是 Syntax Directed Granslation
,也就是语法翻译。骑士的剑上看的不是很清楚,我猜测应该是优秀的编译器的意思。这是征服复杂性的隐喻。优秀的编译器会直接征服复杂的编译,复杂的编译设计永远无法攻破语法翻译。
什么是编译原理
计算机是只认识二进制的,但是我们平常开发中根本不会使用二进制进行开发,我们使用的都是 Java、C 这类的高级语言,每种语言都会经过一系列的转换才能被计算机识别,那么到底是谁做的这项工作呢?一个被称为 编译器(compiler)
的大佬出场了。
语言处理器
首先考虑一下一个例子,你如何才能和老外对话?你是不是需要学英语?我们有一些同学可能认为英语难学,经常会在英语书上做一些汉语标记方便理解。
那么,谁做了由英语到方便记忆
的英语之间的转换呢?答案是你的大脑。所以,我们可以归纳一下这个过程。
因为我们懂汉语(自己的一套语法规则),我们把英语(需要学习的语言)转换为我们便于理解的汉语(大脑翻译规则),我们才能学会英语和老外对话(转换为目标语言)。
这里我说一点:昨天晚上外出遛狗有个老黑和中国女生对话,中国女生竟然讲英文??????这可是中国本土好么,为什么外国人来到中国不讲汉语偏要中国人讲英文???你去外国旅游你会讲中文吗???这是一个基本认知问题,别怪我偏执。我认为外国人要来我们国家最基本的一点就是:你要学中文,千万不要抱着英语为上的心态,汉语不输任何语言。
回到正题,我们上面举出的这个学英语的例子,其实就是一个由原程序经过某种机制转换,把它变成目标语言的过程。也就是
编译器就是一个翻译官的角色,它负责把源程序的语法翻译成目标程序能够理解的语法。
回到计算机中,我们肯定需要目标程序来做一些事情的。
也就是,我们通过某个渠道获得的输入信息,会经过编译器的转换,变为输出信息进行展示。
除了编译器之外,还有一种称为 解释器(interpreter)
的语言处理器,它不是做翻译工作的,而是把用户提供的输入执行源程序中指定的操作。
我们熟知的 Java 语言,就结合了编译和解释的过程,我们写的 Java 源文件首先被编译成 字节码(bytecode)
,字节码是一种中间码,它通常被看成是可执行的二进制文件。然后再由 Java 虚拟机对字节码解释执行。这样,在一台机器上编译的字节码就能够在其他机器上解释执行,这种体现了 Java 语言的平台无关性
。
为了提高编译速度,Java 中有一种 just-in-time,JIT
即时编译器会一边编译一边执行。
一个源文件程序可能被划分为多个模块,并存放在多个文件中,还需要把文件链接在一起,所以,除了编译器之外,还需要一种能链接文件的部件参与,预处理器(preprossor)
是做这件事情的。如下图所示
预处理器经过预处理后会作为输入传递给编译器,编译器对源程序进行编译,编译完成后生成汇编代码,作为汇编器的输入传递给汇编器,汇编器进行汇编处理转换为机器代码,注意这个时候还不是目标代码,还要经过链接器与系统库函数进行链接,最后由加载器把目标代码加载到内存中执行
编译器的结构
我们上面大概了解了一下语言的处理过程,下面我们就来了解一下编译器的内部结构,编译器内部其实具有两种结构:分析(analysis)
部分和 整合(synthesis)
部分。
分析过程相当于是把源程序分成多个结构,每个结构都有特定的语法格式进行校验,在经由每个校验后,如果不满足指定的语法格式则进行提醒,使用户进行修改。分析部分还会收集有关源程序的信息,会把收集到的信息存放在一个被称为 符号表(symbol table)
的数据结构中。符号表和中间表示形式一起传给整合
部分。
整合过程是根据分析过程传递的信息来构造用户期待的目标程序。分析和整合统称为 前端(front end)
和 后端(back end)
,哈哈哈哈。
这里你需要知道符号表(Symbol Table)
的概念:符号表是编译器使用和维护的数据结构,由标识符和类型组成。符号表的主要作用是帮助编译器快速定位。