第111集:语义分析是什么?
核心知识点讲解
语义分析的任务
语义分析是编译器前端的重要组成部分,它的主要任务是:
- 理解程序的含义:在语法正确的基础上,分析程序的语义是否正确
- 类型检查:确保变量和表达式的类型使用正确
- 作用域分析:处理变量的可见性和绑定
- 语义错误检测:发现逻辑错误,如类型不匹配、未声明变量等
- 生成中间表示:为后续的代码生成做准备
语法 vs 语义
| 特性 | 语法 | 语义 |
|---|---|---|
| 定义 | 程序的结构和形式 | 程序的含义和行为 |
| 示例 | 变量声明的格式 | 变量的类型是否正确 |
| 错误 | 缺少分号、括号不匹配 | 类型不匹配、除零错误 |
| 检查时机 | 语法分析阶段 | 语义分析阶段 |
静态语义 vs 动态语义
静态语义:在编译时可以检查的语义规则
- 类型检查
- 作用域规则
- 声明检查
动态语义:在运行时才能检查的语义规则
- 除零错误
- 数组越界
- 空指针引用
语义分析器的位置
在编译器的工作流程中,语义分析位于:
词法分析 → 语法分析 → 语义分析 → 中间代码生成 → 代码优化 → 目标代码生成语义分析器接收语法分析器生成的抽象语法树(AST),对其进行分析和转换,生成增强的AST或中间表示(IR)。
实用案例分析
类型检查示例
语法正确但语义错误的代码:
# 语法正确
x = 10
x = "hello" # 类型不匹配(Python允许,但静态类型语言会报错)
# 语法正确但语义错误(在C语言中)
int x = 10;
x = "hello"; // 类型不匹配,编译时会报错作用域分析示例
def func():
x = 10 # 局部变量
print(x)
print(x) # 错误:x未定义(超出作用域)语义分析的输出
语义分析器的输出通常是:
- 增强的抽象语法树:添加了类型信息、作用域信息等
- 符号表:记录变量、函数等的信息
- 中间表示:如三地址码、SSA等
小结
语义分析是编译器中负责理解程序含义的重要阶段,它:
- 检查静态语义错误
- 构建符号表
- 进行类型检查
- 为后续阶段准备数据
通过语义分析,编译器可以在编译时发现许多潜在的错误,提高程序的可靠性和安全性。