编译器介绍
编译器的实质是一个程序。其核心功能是将源代码翻译成目标
- 源代码: C/C++, Java, ....
- 目标代码:x86, ARM, ...
输入源代码通过编译器输出得到的是可执行程序。通过解释器得到的直接就是一个结果。
相对来说,编译器是一种离线的模式,解释器是一种在线的模式
编译器结构
编译器具有非常模块化的高层结构
由于编译器实现的是将源代码转化为目标代码的功能。所以对于编译器的结构可以大致分为前端和后端两部分,前段处理输入源程序,后端处理输出目标代码
因此,编译器可以看成是一个由多个阶段构成的流水线结构
如下,给出的是一种没有优化的编译器结构
我们可以看见,最开始的输入是一个字符序列,也就是没有处理过的程序代码。之后进行词法分析,得到一个记号序列。语法分析接着检查程序的语法是否合法,在内存中建立一个抽象语法树的数据结构。之后,进行语义分析,判断语法树的合法性,变量是否已经提前声明,函数是否已经定义......生成中间代码。最终通过代码生产得到目标代码
举个例子:
如何实现连续的加法操作:1+2+3+1+2+...
对于栈式计算机(Stack),我们可以用如下的两条指令来实现:
- push n
- add
实现 3 + 4 + 5 + 6
// 先全部压栈
push 3
push 4
push 5
push 6
add {
x = pop();
y = pop();
z = x + y;
push z;
}
再举个例子:
编译程序 1+2+3 到栈式计算机
从此,我们看出,编译器构造与具体的编译器目标相关,在本例中输入先进行前端语法分析然后得到语法树的中间表示,进入后端做代码生成,生成 Stack 的代码
如果,我们对其需要对其进行优化的话,就可以直接在上图第一颗语法树后添加一个优化的阶段和第二颗优化后的语法树,这样之后再进入后端