Mslxl

Integrate Life

编译原理:绪论 —— 语义分析

Posted at # Compiler

语义分析

语义分析的任务

语义分析是编译过程的第三个阶段,高级语言中的语句大多数分为两类,一类是声明语句,一类是可执行语句,在声明语句中会声明一些数据对象或过程,并且为他们分别起一个名字 标识符 (id),对于声明语句来说,语义分析的主要任务就是收集标识符的属性信息,一般有这些属性信息

对声明语句语义分析的任务

  1. 种属 (Kind) : 它说明了这个标识符对应的是简单变量,还是一个复合变量(数组、记录、…),还是过程、…
  2. 类型 (Type) : 这个我相信都不用说了把
  3. 储存位置、长度 : 比如说我们写了一个对象或过程,我们都要在内存中给他分配一段空间,这样存储位置和所占用的空间的大小(长度)就成为标识符重要的属性
  4. 作用域
关于 3 举个例子:
begin
real x[8]
integer i,j;
...
end

首先声明了一个实型数组x ,因此 x 的相对地址就是 0。我们假设一个实型变量占用 8 个字节,因为这个实型数组包含 8 个元素,因此他就占用了 64 个字节,所以接下来声明的变量 i 的相对地址就是 64,我们再假设一个整形变量占用 4 个字节,那么接下来声明的变量 j 的相对地址就是 64 + 4 = 68 ,以此类推。

名字相对地址
x0
i64
j68

|:-:|:-:| |0|x[0]| |8|x[1]| | | | | |…| |56|x[7]| |64|i| |68|j|

对过程语义分析的任务

对于过程来说,作用有 0. 参数和返回值信息 : 包含了参数个数、参数类型、参数传递方式、返回值类型等等

符号表 (Symbol Table)

NAMETYPEKINDVALADDR
SIMPLE简变
SYMBLE数组
TABLE字符常数
.....

语义分析中收集的标识符的信息都会存放在符号表里,每一个标识符都对应着一条记录,每个字段对应着一个属性,比如说 类型 (TYPE)种属 (KIND)值 (VALUE)地址 (ADDRESS)等等。

符号表中通常带有一个字符串表,用来存放程序中标识符的名称和字符常数,这样的话 NAME 字段就会被分割成两个部分,一个用来存放标识符在字符串表中的起始位置,另一个存放标识符的长度,这里由于 Markdown 的限制不能将其表现出来。符号表中设计字符串表的作用是节省内存空间。

语义分析的另一个任务:语义检查

常见的语义错误有:

  1. 变量或过程未经声明就使用
  2. 变量或过程名重复声明
  3. 运算分量类型不匹配:其中需要判断是否运算无意义(比如将一个数组与数字相加)和是否需要隐式转换
  4. 操作符操作数之间类型不匹配
    • 数组下标 不是整数
    • 非数组变量使用数组访问操作符
    • 非过程名使用过程调用操作符
    • 过程调用的参数类型或数目不匹配
    • 函数返回类型有误

graph TD
	Start-- 字符流 -->词法分析器
	词法分析器-- 词法字节流 -->语法分析器
	语法分析器-- 语法树 -->语义分析器
	语义分析器-- 语法树 -->中间代码生成器
	中间代码生成器-- 中间表示形式 -->机器无关代码优化器
	机器无关代码优化器-- 中间表示形式 -->目标代码生成器
	目标代码生成器-- 目标机器语言 -->机器相关代码优化器
	机器相关代码优化器-- 目标机器语言 -->Fin
moe-counter

统计自 2024 年 9 月