文章目录
绪论
00. 高级语言、汇编语言、机器语言的特点
-
机器语言(
Machine Language)的特点- 可以被计算机直接理解
- 与人类表达习惯相去甚远
- 难记忆
- 难编写、难阅读
- 易写错
-
汇编语言(
Assembly Language)的特点- 引入助记符
- 依赖于特定机器, 非计算机专业人员使用受限制
- 编写效率依然很低
-
高级语言 (
High Level Language)特点- 类似于数学定义或自然语言的简洁形式
- 接近人类表达习惯
- 不依赖于特定机器
- 编写效率高
01. 关于概念
- 汇编指令:用符号表示的指令被称为汇编指令
- 汇编语言:汇编指令的集合称为汇编语言
-
转换(也被称为预处理):高级语言之间的翻译,如
FORTRAN到ADA的转换 - 编译:高级语言直接翻译成机器语言或者汇编语言,这两个翻译过程称为编译
- 汇编:从汇编语言到机器语言的翻译被称为汇编
- 反汇编:把机器语言翻译成汇编语言
- 反编译:把汇编语言翻译成高级语言
02. 编译器在语言处理系统中的位置
- 从源程序到目标机器代码的过程
- 预处理器
(Preprocessor):把存储在不同文件中的源程序聚合在一起,把被称为宏的缩写语句转换为原始语句 - 可重定位
(Relocatable): 在内存中存放的起始位置L不是固定的 - 加载器: 修改可重定位地址; 将修改后的指令和数据放到内存中适当的位置
- 起始位置 +相对地址=绝对地址
- 链接器:将多个可重定位的机器代码文件(包括库文件) 连接到一起,解决外部内存地址问题
03. 编译器的结构
- 分析部分/前端(
front end)与源语言相关- 词法分析器
- 语法分析器
- 语义分析器
- 中间代码生成器
- 综合部分/后端(
back end):与目标语言相关- 目标代码生成器
- 机器相关代码优化器
04. 词法分析/扫描(Scanning)
- 词法分析的主要任务
- 从左向右逐行扫描源程序的字符,识别出各个单词,确定单词的类型。 将识别出的单词转换成统一的机内表示——词法单元
(token)形式token:< 种别码,属性值 >
| 编号 | 单词类型 | 种别 | 种别码 |
|---|---|---|---|
| 1 | 关键字 |
program、if、else、then、… |
一词一码 |
| 2 | 标识符 | 变量名、数组名、记录名、过程名、… | 多词一码 |
| 3 | 常量 | 整型、浮点型、字符型、布尔型、… | 一型一码 |
| 4 | 运算符 | 算术( + - * / ++ -- )关系 ( > < == != >= <= )逻辑 ( & | ~ )
|
一词一码 或 一型一码 |
| 5 | 界限符 | ( ) = { } … |
一词一码 |
05. 词法分析后得到的token序列
- 输入:
while(value!=100){num++;} - 输出的
token序列
-
while< WHILE , - > -
(< SLP , - > -
value< IDN , value > -
!=< NE , - > -
100< CONST , 100 > -
)< SRP , - > -
{< LP , - > -
num< IDN , num > -
++< INC , - > -
;< SEMI , - > -
}< RP , - >
06. 语法分析 ( parsing)
- 语法分析器
parser从词法分析器输出的token序列中 识别出各类短语,并构造语法分析树parse tree - 语法分析树描述了句子的语法结构
- 赋值语句的分析树
- 变量声明语句的分析树
- 输入:
int a , b , c ; - 文法:
<D> -> <T> <IDS>;-
<T>->int | real | char | bool <IDS> -> id | <IDS>, id
- 图示:
- 输入:
07. 语义分析
-
语义分析的主要任务:
-
收集标识符的属性信息
-
种属
(Kind)- 简单变量、复合变量(数组、记录、…)、过程、…
-
类型
(Type)- 整型、实型、字符型、布尔型、指针型、…
-
存储位置、长度
-
值
-
作用域
-
参数和返回值信息
- 参数个数、参数类型、参数传递方式、返回值类型、…
-
-
语义检查
- 变量或过程未经声明就使用
- 变量或过程名重复声明
- 运算分量类型不匹配
- 操作符与操作数之间的类型不匹配
- 数组下标不是整数
- 对非数组变量使用数组访问操作符
- 对非过程名使用过程调用操作符
- 过程调用的参数类型或数目不匹配
- 函数返回类型有误
08. 中间代码生成
8.1 常用的中间表示形式
- 三地址码
(Three-address Code)- 三地址码由类似于汇编语言的指令序列组成, 每个指令最多有三个操作数
(operand)
- 三地址码由类似于汇编语言的指令序列组成, 每个指令最多有三个操作数
- 语法结构树/语法树
(Syntax Trees)
8.2 三地址指令
- 常用的三地址指令:
- 地址可以具有如下形式之一
- 源程序中的名字
(name ) - 常量
(constant) - 编译器生成的临时变量
(temporary )
- 源程序中的名字
- 三地址指令的表示
- 四元式
(Quadruples)- (op, y, z, x)
- 三元式
(Triples) - 间接三元式
(Indirect triples)
- 四元式
8.3 三地址指令的四元式表示
8.4 中间代码生成的例子
8.5 编译器的结构
- 目标代码生成以源程序的中间表示形式作为输入,并把它映射到目标语言
- 目标代码生成的一个重要任务 是为程序中使用的变量合理分配寄存器
- 代码优化
- 为改进代码所进行的等价程序变换,使其运行得更快一些、占用空间更少一 些,或者二者兼顾
- 代码优化:
- 机器无关代码优化
- 机器相关代码优化
09. 编译器与解释器
- 语言翻译的两种基本形态
- 编译器
- 解释器
- 解释器与编译器的主要区别:运行目标程序时的控制权在解释器而不在目标程序.
- 编译器与解释器各自的特点
- 编译器:工作效率高,即时间快、空间省;交互性与动态性差,可移植性差
- 解释器:工作效率低,即时间慢、空间费;交互性与动态性好,可移植性好
- 共同点
- 均完成对源程序的翻译.
- 差异
- 编译器采用先翻译后执行,解释器采用边翻译边执行
10.编译器的工作原理与基本组成
- 通用程序设计语言的主要成份 声明+操作=完整定义
- 以过程为基本结构的程序设计语言的组成
- 声明性语句:提供操作对象的性质,如数据类型、值、作用域等;
- 操作性语句:确定操作的计算次序,完成实际操作。
- 过程定义 = 过程头+过程体
- 以阶段划分编译器
注:符号表管理器和出错处理贯穿编译器工作的各个阶段
- 编译器各阶段工作
1> 词法分析:词法分析的输入是源程序,输出是识别出的记号流.目的是识别单词. 至少分以下几类:关键字(保留字)、标识符、字面量、特殊符号
2> 语法分析: 输入是词法分析器返回的记号流,输出是语法树.目的是得到语言结构并以树的形式表示.对于声明性语句,进行符号表的查填,对于可执行语句,检查结构合理的表达式运算是否有意义.
3> 语义分析:根据语义规则对语法树中的语法单元进行静态语义检查,如类型检查和转换等,目的在于保证语法正确的结构在语义分析上也是合法的.
4> 中间代码生成(可选):生成一种既接近目标语言,又与具体机器无关的表示,便于代码优化与代码生成.
(到目前为止,编译器与解释器可以一致)
5> 中间代码优化(可选):局部优化、循环优化、全局优化等;优化实际上是一个等价变换,变换前后的指令序列完成同样的功能,但在占用的空间上和程序执行的时间上都更省、更有效
6> 目标代码生成:不同形式的目标代码 — 汇编语言形式、可重定位二进制代码形式、内存形式Load-and-Go
7> 符号表管理:合理组织符号,便于各阶段查找填写等.
8> 出错处理:
- 动态错误:源程序中的逻辑错误,发生在程序运行的时候。也称为动态语义错误
-
静态错误:静态错误分为语法错误和静态语义错误.
-
语法错误:有关语言结构上的错误,如单词拼写错误、表达式缺少操作数、
begin和end不匹配 - 静态语义错误:分析源程序时可以发现的语言意义上的错误,如加法的两个操作数一个是整形变量,另一个是数组名
-
语法错误:有关语言结构上的错误,如单词拼写错误、表达式缺少操作数、
- 编译器的分析 - 综合模式
- 逻辑上把编译器分为分析(前端)部分和综合(后端)部分.
- 分析(前端):语言结构和意义的分析; 从词法分析到中间代码生成各阶段的工作
- 综合(后端):语言意义处理;从中间代码生成到目标代码生成的各阶段的工作
- 编译器和解释器的区别往往是在形成中间代码之后开始的.
11. 编译器扫描的遍数
- 每个阶段将程序完整分析一遍的工作模式称为一遍扫描。
- 将源程序或源程序的某种形式的中间表示完整分析一遍,亦称作一遍扫描