1.1 语言处理器
- 编译器和解释器的区别
编译器是把源程序的每一条语句都编译成机器语言,并保存成二进制文件,这样运行时计算机可以直接以机器语言来运行此程序,速度很快;而解释器则是只在执行程序时,才一条一条的解释成机器语言给计算机来执行,所以运行速度是不如编译后的程序运行的快的。
- Java语言处理器结合了编译和解释过程
一个Java程序先被编译成字节码(bytecode)的中间表示形式,然后由虚拟机对字节码加以解释执行
- 语言处理器的组成
1个语言处理器包含:预处理器->编译器->汇编器->链接器/加载器
1.2 一个编译器的结构
- 编译器把源程序映射为等价的目标程序,这个映射过程由两个部分组成:分析部分和综合部分
- 分析(analysis)部分把源程序分解成为多个组成要素,并在这些要素之上加上语法结构。然后,它使用这个结构来创建该源程序的一个中间表示。如果分析部分检查出源程序没有按照正确的语法构成,或者语义上不一致,它就必须提供有用的信息,使得用户可以按此进行改正。分析部分还会收集有关源程序的信息,并把信息存放在一个称为符号表(symbol table)的数据结构中。符号表将和中间表示形式一起传送给综合部分;
- 综合(synthesis)部分根据中间表示和符号表中的信息来构造用户期待的目标程序。
分析部分经常被称为编译器的前端(front end),而综合部分称为后端(back end)
- 编译器包含的各个步骤:词法分析->语法分析->语义分析->中间代码生成器->机器无关代码优化器->代码生成器->机器代码相关优化器
1.2.1 词法分析
- 词法分析器读入组成源程序的字符流,并且将它们组织成为有意义的词素的序列
- 一个赋值语句的翻译
1.2.2 语法分析
- 语法分析器
语法分析器使用由词法分析器生成的各个词法单元的第一个分量来创建树形的中间表示。该中间表示给出了词法分析产生的词法单元流的语法结构。一个常用的表示方法是语法树(syntax tree),树中的每个内部结点表示一个运算,而该结点的子结点表示该运算的分量。
1.2.3 语义分析
- 语义分析器
语义分析器(semantic analyzer)使用语法树和符号表中的信息来检查源程序是否和语言定义的语义一致。它同时也收集类型信息,并把这些信息存放在语法树或符号表中,以便在随后的中间代码生成过程中使用。
- 类型检查
语义分析的一个重要部分是类型检查(type checking)。编译器检查每个运算符是否具有匹配的运算分量
- 自动类型转换
程序设计语言可能允许某些类型转换,这被称为自动类型转换(coercion)。比如,一个二元算术运算符可以应用于一对整数或者一对浮点数。如果这个运算符应用于一个浮点数和一个整数,那么编译器可以把该整数转换(或者说自动类型转换)成为一个浮点数。
1.2.4 中间代码生成
- 概念解释
在源程序的语法分析和语义分析完成之后,很多编译器生成一个明确的低级的或类机器语言的中间表示。我们可以把这个表示看作是某个抽象机器的程序。该中间表示应该具有两个重要的性质:它应该易于生成,且能够被轻松地翻译为目标机器上的语言。
- 三地址代码
三地址代码(three-address code)是一种中间表示形式。这种中间表示由一组类似于汇编语言的指令组成,每个指令具有三个运算分量。每个运算分量都像一个寄存器。
- 三地址代码的3个要点
- 首先,每个三地址赋值指令的右部最多只有一个运算符。因此这些指令确定了运算完成的顺序。比如乘法应该在加法之前完成。 <