编译器的构造

Up to this point we have treated a compiler as a single box that maps a source program into a semantically equivalent target program. If we open up this box a little, we see that there are two parts to this mapping: analysis and synthesis.

我们将编译器想象成一个加工机器,原料是源代码,通过加工机器后可以获得目标程序。如果我们将编译器这台加工机器拆开,我们会发现这台加工机器里由两个部件组成,一个是分析器,一个是合成器。

分析器的作用是将源代码拆分成若干个小模块,并且勾勒出它们的语法结构。这些语法结构将被用于生成中间码,用以代表原本的源代码。在分析器的执行过程中,若分析器发现源代码中的一些语法格式或语义上的错误,则可以展示给用户具体的错误信息,以便于用户通过错误信息修改相应的代码。分析器的另一部分工作,将关于源代码的信息收集起来,存储在一个叫做符号表之中。

合成器的作用是通过分析器得来的中间码以及符号表中的数据,去构造目标程序。

通常,我们将分析器称为编译器的前端,合成器称为编译器的后端。

对于编译器来说,将每一个过程细节展开,我们会发现编译器是分层级的,每一层都是对源代码的一种表述。

character stream -> {Lexical Analyzer} -> token stream -> {Syntax Analyzer} -> syntax tree -> {Semantic Analyzer} -> syntax tree -> {Intermediate Code Generator} -> intermediate representation -> {Machine-Independent Code Optimizer} -> intermediate representation -> {Code Generator} -> target-machine code -> {Machine-Dependent Code Optimizer} -> target-machine code ->

一些编译器在前后端之间存在一个machine-independent(机器无关)的可选层。

词法分析

编译器的第一层叫做词法分析扫描器。词法分析器从字符流读取和标记源代码,使之成为可被编译器识别的有意义的词汇单元。对于每个词汇单元来说,词法分析器将输出一个标记,其格式为:

<token-name, attribute-value>

语法分析

编译器的第二层叫做语法分析解析器。解析器通过扫描器获得的标记,来构造能够描述语法结构的树,称为语法树。语法树种的每一个分支节点都代表一种操作,其子节点为这一操作的参数。

语义分析

语义分析凭借语言的特性,根据语法数与符号表中的信息来分析获知源代码的具体语义。
在语义分析部分有一个很重要的部分叫做类型检查,其作用为编译器检查每一个操作对应的算元是否匹配。
编程语言中有一个特殊的情况,即强制类型转换,在语义分析阶段需要额外注意。

中间语言生成

该过程是将源程序翻译到目标代码之中,一个编译器可能构造一种或多种中间码表示形式。语法树就是一种中间语言的代表形式,它通常被用于在语法和语义分析期间。在对源代码语法和语义分析之后,许多编译器生成一种低级的或类似于机器码的中间码,这种中间码我们可以将它理解为一种抽象机的机器码。因此,中间码就需要有两个重要的属性:

  1. 它应该容易被产生
  2. 他应该容易被翻译成目标机器的机器码

代码优化

该过程是尝试改善中间码来获取最优的目标码。通常来说,最优就意味着最快,但是并不是说最优就是最快,还有其他方面的标准可以依从,譬如目标码最短即最优、或者是目标码所消耗的资源最低即最优等等。

代码生成

代码生成器的作用便是将代表源代码的中间码映射到目标语言中。如果目标语言是机器码的话,每一个变量将会在程序中选择寄存器或某一内存空间作为代表。然后,这些中间指令将会转换成为机器指令 。代码生成的一个很重要的方面就是决定分配哪个寄存器来承载变量。

posted @ 2016-10-07 17:38  Ant°  阅读(194)  评论(0)    收藏  举报