编译器阶段示例:编译过程和步骤

编译器设计分为哪些阶段?

编译器 编译器分为多个阶段,每个阶段将源程序从一种表示形式转换为另一种表示形式。每个阶段都从其前一阶段获取输入,并将其输出提供给编译器的下一阶段。
编译器有 6 个阶段。每个阶段都有助于将高级语言转换为机器代码。编译器的阶段包括:

  1. 词法分析
  2. 语法分析
  3. 语义分析
  4. 中间代码生成器
  5. 代码优化器
  6. 代码生成器
编译器的各个阶段
编译器的各个阶段

所有这些阶段都通过将源代码划分为标记、创建解析树以及通过不同阶段优化源代码来转换源代码。

第一阶段:词汇分析

词法分析是编译器扫描源代码的第一个阶段。这个过程可以从左到右,逐个字符地进行,并将这些字符分组为 token。
在这里,通过识别标记,将源程序中的字符流分组为有意义的序列。它将相应的标签输入到符号表中,并将该标记传递到下一阶段。
此阶段的主要功能是:

  • 识别源代码中的词汇单元
  • 将词汇单位分类为常量、保留字等类别,并将它们输入到不同的表中。它将忽略源程序中的注释
  • 识别不属于语言的标记

例如::
x = y + 10

令牌

X 识别码
= 赋值运算符
Y 识别码
+ 加法运算符
10 联系电话

第二阶段:语法分析

语法分析就是发现代码中的结构。它确定文本是否遵循预期的格式。此阶段的主要目的是确保程序员编写的源代码是否正确。
语法分析是基于特定编程语言的规则,通过标记构建解析树。它还确定源语言的结构以及语言的语法或句法。
以下是此阶段执行的任务列表:

  • 从词法分析器获取 token
  • 检查表达式的语法是否正确
  • 报告所有语法错误
  • 构建一个层次结构,即解析树

例如:

任何标识符/数字都是一个表达式
如果 x 是标识符而 y+10 是表达式,则 x= y+10 是语句。
考虑以下示例的解析树

(a+b)*c

语法分析示例

在解析树中

  • 内部节点:记录一个操作员文件和两个子文件
  • 叶子:具有 2 个或更多字段的记录;一个用于标记,另一个用于有关标记的其他信息
  • 确保项目各部分有意义地结合在一起
  • 收集类型信息并检查类型兼容性
  • 检查操作数是否被源语言允许

第三阶段:语义分析

语义分析检查代码的语义一致性。它使用前一阶段的语法树以及符号表来验证给定的源代码在语义上是否一致。它还检查代码是否传达了适当的含义。
语义分析器将检查类型不匹配、不兼容的操作数、使用不当参数调用的函数、未声明的变量等。
语义分析阶段的功能包括:

  • 帮助您存储收集的类型信息并将其保存在符号表或语法树中
  • 允许您执行类型检查
  • 在类型不匹配的情况下,如果没有满足所需操作的精确类型校正规则,则会出现语义错误
  • 收集类型信息并检查类型兼容性
  • 检查源语言是否允许操作数

例如:

float x = 20.2;
float y = x*30;

在上面的代码中,语义分析器会在乘法之前将整数 30 转换为浮点数 30.0

阶段 4:中间代码生成

一旦语义分析阶段结束,编译器就会为目标机器生成中间代码。它代表某个抽象机器的程序。
中间代码介于高级语言和机器语言之间。这种中间代码需要以一种易于将其转换为目标机器代码的方式生成。
中间代码生成函数:

  • 它应该从源程序的语义表示生成
  • 保存翻译过程中计算的值
  • 帮助您将中间代码翻译成目标语言
  • 允许您保持源语言的优先顺序
  • 它保存了指令的正确操作数

例如:

例如,

total = count + rate * 5

利用地址码法得到的中间码为:

 
t1 := int_to_float(5) 
t2 := rate * t1 
t3 := count + t2
total := t3

第五阶段:代码优化

下一个阶段是代码优化或中间代码。此阶段删除不必要的代码行并安排语句序列以加快程序的执行速度而不浪费资源。此阶段的主要目标是改进中间代码以生成运行速度更快且占用空间更少的代码。
此阶段的主要功能是:

  • 它可以帮助您在执行速度和编译速度之间建立权衡
  • 提高目标程序的运行时间
  • 生成仍处于中间表示形式的精简代码
  • 删除无法访问的代码并清除未使用的变量
  • 从循环中删除未改变的语句

计费示例:
考虑以下代码

a = intofloat(10)
b = c * a
d = e + b
f = d

可以变成

b =c * 10.0
f = e+b

阶段 6:代码生成

代码生成是编译器的最后一个阶段。它从代码优化阶段获取输入,并生成页面代码或目标代码。此阶段的目标是分配存储并生成可重定位的机器代码。
它还为变量分配内存位置。中间代码中的指令被转换成机器指令。此阶段将优化或中间代码转换为目标语言。
目标语言是机器代码。因此,在此阶段还选择并分配所有内存位置和寄存器。执行此阶段生成的代码以获取输入并生成预期输出。

例如:

a = b + 60.0
可能会被翻译成寄存器。

MOVF a, R1
MULF #60.0, R2
ADDF R1, R2

符号表管理

符号表包含每个标识符的记录,其中包含标识符属性的字段。此组件使编译器更容易搜索标识符记录并快速检索它。符号表还可以帮助您进行范围管理。符号表和错误处理程序与所有阶段交互,符号表会相应地更新。

错误处理例程

在编译器设计过程中,以下所有阶段都可能出现错误:

  • 词法分析器:拼写错误的标记
  • 语法分析器:缺少括号
  • 中间代码生成器:运算符的操作数不匹配
  • 代码优化器:当语句无法到达时
  • 代码 Generator:当内存已满或未分配适当的寄存器时
  • 符号表:多个声明标识符的错误

最常见的错误是扫描中的无效字符序列、类型中的无效标记序列、范围错误和语义分析中的解析。
错误可能发生在以上任何一个阶段。发现错误后,该阶段需要处理错误才能继续编译过程。这些错误需要报告给处理错误的错误处理程序才能继续编译过程。通常,错误以消息的形式报告。

结语

  • 编译器分为多个阶段运行,每个阶段将源程序从一种表示形式转换为另一种表示形式
  • 六个阶段 编译器设计 是1)词法分析2)语法分析3)语义分析4)中间代码生成器5)代码优化器6)代码 Generator
  • 词法分析是编译器扫描源代码的第一个阶段
  • 语法分析就是发现文本中的结构
  • 语义分析检查代码的语义一致性
  • 语义分析阶段结束后,编译器为目标机器生成中间代码
  • 代码优化阶段删除不必要的代码行并安排语句顺序
  • 代码生成阶段从代码优化阶段获取输入,并生成页面代码或目标代码
  • 符号表包含每个标识符的记录,其中包含标识符属性的字段
  • 错误处理程序处理多个阶段的错误和报告