在进入主题之前我们首先要弄清楚到底什么时编译器,它在计算机世界中起着什么作用,以及它的工作原理及流程。需要注意的是在整个系列中我们将会实现一个简单的类C语言的编译器,它是C语言的一个子集,我们称为Cb语言。
编译器的定义
根据维基百科的定义,编译器是一种计算机程序,它会将某种编程语言写成的源代码转换成另一种编程语言。它的主要目的是将便于人编写、阅读、维护的高级计算机语言所写的源代码程序,翻译为计算机能解读、运行的低阶及其语言的程序。
简单的说编译器就象是现实生活中的翻译,就像翻译员把中文翻译为英文一样,编译器将我们使用的易于理解的高级语言如C,JAVA,C++等翻译成计算机能够读懂和运行的由0,1组成的机器语言。
编译器的作用
编译器的出现将程序员从繁琐的代码编写工作中解放了出来,使用更加底层的汇编语言编写代码已经让人很头痛了,如果用机器语言进行代码开发简直就是一场噩梦!编译器的出现使得代码更加抽象,开发效率更加高效,降低了程序开发的难度,同时也有利于程序的移植。可以说编译器就是现代计算机领域的重要基石之一!
编译器的工作原理
我们以GCC为例对编译器的工作原理进行讲解,广义的编译器有以下几个组成部分:
- 预处理器:对C语言代码中的#include和#define进行处理,将其在程序代码中进行展开和替换,插入到代码中。其结果就是得到另外一个C程序,
- 狭义的编译器
- 链接:生成的目标文件本身还不能使用,无论是直接运行还是作为程序库都不可以,需要通过连接器对调用的相关函数和库进行加载后输出可执行文件才可以执行。
这几部分中我们重点讲解下侠义的编译器,它是整个广义编译器里的重中之重。其工作流程大致可以分为以下四个阶段:
- 语法分析阶段:该部分又可细分为词法分析和语法分析两个阶段,词法分析的作用是对代码进行解析,将其分割为一个个单词。语法分析阶段将对词法分析产生的单词进行处理生成语法树。
- 语义分析阶段:对生成的语法树进行解析,除去多余的部分,并对剩余部分添加必要的信息,生成抽象语法树。该阶段包括以下这些处理:
- 区分变量为局部变量还是全局变量
- 解析变量的声明和引用
- 变量和表达式的类型检查
- 检查在引用变量之前是否进行了初始化
- 检查函数是否按照定义返回了结果
- 生成中间代码:生成抽象语法树之后,接着将抽象语法树转化为直在内部使用的中间代码。
- 代码生成:最后把中间代码转化为对应平台的汇编代码。
- 优化:在编译过程中还涉及到代码优化的问题,编译器可以对源程序的代码进行优化,从而使得生成的机器代码有着更高的执行效率。优化可以发生在狭义的编译器的各个环节中,可以对生成的抽象语法树进行优化,也可以对中间代码进行优化,甚至还可以对转换后的机器语言进行优化。
通过上述部分,我们就对编译器的工作流程有了一个大致的了解,接下来我们就要进入正题,开始开发属于我们自己的Cb语言的编译器。