什么是编译器设计?类型、构造工具、示例
编译器设计分为哪些阶段?
A 编译器 编译器分多个阶段运行,每个阶段都将源程序从一种表示形式转换为另一种表示形式。每个阶段都从前一阶段接收输入,并将其输出传递给编译器的下一阶段。编译器共有六个阶段。每个阶段都有助于将高级语言转换为机器代码。编译器的六个阶段是:
- 词法分析
- 语法分析
- 语义分析
- 中间代码生成器
- Code 优化
- Code 发电机
编译器的各个阶段
所有这些阶段都将源代码分割成标记,创建解析树,并通过不同的阶段优化源代码,从而转换源代码。
第一阶段:词汇分析
词法分析是第一阶段,编译器会扫描源代码。这个过程可以从左到右,逐个字符地进行,并将这些字符分组为词法单元(token)。
在此,源程序的字符流通过识别标记被分组为有意义的序列。它将相应的标记添加到符号表中,并将该标记传递给下一阶段。
此阶段的主要功能是:
- 识别源代码中的词法单元。
- 将词法单元分类,例如常量、保留字,并将它们输入到不同的表格中。程序将忽略源程序中的注释。
- 找出不属于该语言的词素。
计费示例: x = y + 10
| Token | 类型 |
|---|---|
| X | 识别码 |
| = | 赋值运算符 |
| Y | 识别码 |
| + | 加法运算符 |
| 10 | 联系电话 |
第二阶段:语法分析
语法分析旨在发现代码的结构,判断文本是否符合预期格式。此阶段的主要目的是确保程序员编写的源代码正确无误。
语法分析基于特定编程语言的规则,通过借助词法单元构建语法分析树。它还能确定源语言的结构以及该语言的语法或句法。
以下是此阶段执行的任务列表:
- 从词法分析器获取词元。
- 检查表达式的语法是否正确。
- 请报告所有语法错误。
- 构建一个称为解析树的层次结构。
例如:
任何标识符/数字都是一个表达式。如果 x 是一个标识符,y+10 是一个表达式,那么 x = y+10 就是一个语句。请看以下示例的语法分析树:
(a+b)*c
在解析树中:
- 内部节点:包含一个操作符字段和两个子字段的记录。
- 叶子节点:包含 2 个或多个字段的记录;一个字段用于存储令牌,另一个字段用于存储与令牌相关的其他信息。
- 确保项目的各个组成部分能够有效衔接。
- 收集类型信息并检查类型兼容性。
- 检查操作数是否为源语言允许。
第三阶段:语义分析
语义分析检查代码的语义一致性。它使用前一阶段的语法树以及符号表来验证给定的源代码在语义上是否一致。它还检查代码是否传达了适当的含义。
语义分析器将检查类型不匹配、不兼容的操作数、使用不正确的参数调用的函数、未声明的变量等。
语义分析阶段的功能包括:
- 帮助您存储收集到的类型信息,并将其保存到符号表或语法树中。
- 允许您执行类型检查。
- 如果类型不匹配,没有满足所需操作的精确类型更正规则,则会显示语义错误。
- 收集类型信息并检查类型兼容性。
- 检查源语言是否允许这些操作数。
例如:
float x = 20.2; float y = x*30;
在上面的代码中,语义分析器会在乘法运算之前将整数 30 强制转换为浮点数 30.0。
第四阶段:中级 Code 信号生成
语义分析阶段结束后,编译器会为目标机器生成中间代码。它代表一个针对特定目标机器的程序。tract 机器。
中间代码介于高级语言和机器语言之间。这种中间代码的生成方式必须便于将其翻译成目标机器代码。
中间功能 Code 一代:
- 它应该根据源程序的语义表示生成。
- 保存翻译过程中计算出的值。
- 帮助您将中间代码翻译成目标语言。
- 允许您保持源语言的优先级顺序。
- 它包含指令的正确操作数数量。
例如:
例如:
total = count + rate * 5
利用地址码方法得到的中间代码为:
t1 := int_to_float(5)
t2 := rate * t1
t3 := count + t2
total := t3
阶段5: Code 优化
下一阶段是对中间代码进行优化。此阶段会移除不必要的代码行,并重新排列语句顺序,以在不浪费资源的前提下加快程序执行速度。此阶段的主要目标是改进中间代码,生成运行速度更快、占用空间更小的代码。
此阶段的主要功能是:
- 它可以帮助您在执行速度和编译速度之间找到平衡点。
- 提高目标程序的运行速度。
- 生成仍保持中间表示形式的精简代码。
- 删除无法执行的代码并清除未使用的变量。
- 从循环中移除未修改的语句。
计费示例: 考虑以下代码:
a = intofloat(10)
b = c * a
d = e + b
f = d
可以变成:
b = c * 10.0
f = e + b
阶段6: Code 信号生成
Code 生成是编译器的最后一个阶段。它从代码优化阶段获取输入,并生成页面代码或目标代码。此阶段的目标是分配存储空间并生成可重定位的机器代码。
它还会为变量分配内存位置。中间代码中的指令会被转换成机器指令。此阶段会将优化后的中间代码转换成目标语言。
目标语言是机器代码。因此,所有内存位置和寄存器也在此阶段进行选择和分配。此阶段生成的代码将被执行,以接收输入并生成预期输出。
例如:
a = b + 60.0 可以转换成寄存器表达式:
MOVF a, R1 MULF #60.0, R2 ADDF R1, R2
符号表管理
符号表包含每个标识符的记录,记录中包含标识符属性的字段。该组件使编译器能够更轻松地搜索和快速检索标识符记录。符号表还有助于作用域管理。符号表和错误处理程序与所有阶段交互,符号表也会相应地更新。
错误处理例程
在编译器设计过程中,以下所有阶段都可能出现错误:
- 词汇分析器: 拼写错误的标记。
- 语法分析器: 缺少括号。
- 中间代码生成器: 运算符的操作数不匹配。
- Code 优化器: 当语句无法访问时。
- Code Generator: 当内存已满或未分配合适的寄存器时。
- 符号表: 声明了多个标识符,出现错误。
最常见的错误是扫描中的无效字符序列、类型中的无效标记序列、作用域错误以及语义分析中的解析错误。
上述任何阶段都可能出现错误。发现错误后,该阶段需要处理这些错误才能继续编译过程。这些错误需要报告给错误处理程序,由其处理错误以继续执行编译过程。通常,错误以消息的形式报告。



