Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

语义分析总装

复习

  • 符号表:记录名字及其属性,是语义分析的基础
  • 名字解析:沿作用域从内到外确定名字指向哪个定义
  • 类型检查:沿语法树自底向上确认每个运算的类型是否匹配

TL;DR

  • 语义分析把名字、作用域、类型、控制规则合成一次完整检查
  • 它建立在符号表和抽象语法树之上
  • 通过之后,程序才算“讲得通”
  • 之后就可以进入中间表示与优化

正文

  这一章是语义分析的收尾。我们把前面几章的零件串起来,看看语义分析这一步在编译器里到底做了什么。

它到底在检查什么

  语义分析要回答的核心问题只有一个:这棵语法树,在语义上成立吗? 具体拆开,它做了这几类事:

  • 建符号表、做名字解析:弄清每个名字指向哪个定义
  • 管理作用域:处理名字的可见性与遮蔽
  • 做类型检查:确认每个运算、赋值、调用的类型都匹配
  • 检查控制规则:条件类型、跳转位置、返回路径是否合法
  • 必要时处理类型转换类型推断

  这些检查互相依赖,通常在遍历抽象语法树的过程中一并完成:一边进作用域、往符号表里登记名字,一边对每个节点做类型和规则检查。

它的产出是什么

  语义分析之后,编译器得到的,通常是一棵带类型标注的语法树(有时叫“装饰过的”AST):每个表达式节点上,都附上了它的类型;每个名字,都指向了它的定义。

  这棵树,就是后面阶段宝贵的输入:

  • 中间表示可以从它翻译而来
  • 优化可以借助类型信息做出更聪明的决定
  • 代码生成能据此选择正确的指令

  可以说,语义分析把“漂亮的语法结构”,升级成了“信息完备、可以往下走的结构”。

走到这里的意义

  回头看看这条线:字符 → 词法单元 → 语法树 → 抽象语法树 → 带类型的 AST。每一步都在剥离表层、补充信息,让程序越来越“接近机器能处理的样子”。

  这也正是编译器前端的完整旅程:读进来的是字符,交出去的是含义清晰、类型明确的结构。 至此,“读懂程序”这件事已经完成。

  下一组,我们要从“读懂”转向“翻译”:把这棵带类型的树,变成与具体机器无关的中间表示

思考题 1

  语义分析大致要完成哪几件事?

思考题 2

  语义分析的产出通常是什么?它为后续阶段提供了什么?

小结

知识点

  • 语义分析综合检查名字、作用域、类型与控制规则
  • 它在遍历 AST 时同步完成
  • 产出通常为带类型标注的语法树
  • 后续的中间表示、优化与代码生成都依赖它

参考资料

  1. Wikipedia(zh):语义分析:编译器前端中检查语义的阶段
  2. Wikipedia(zh):编译器:编译流程的整体阶段划分

思考题答案(仅供参考)

思考题 1

  大致包括:建立符号表并进行名字解析,管理作用域与遮蔽,进行类型检查与控制流检查,必要时处理类型转换和类型推断。这些检查通常在遍历抽象语法树时一并完成。

思考题 2

  产出通常是一棵带类型标注的语法树,其中每个表达式都带有类型、每个名字都指向其定义。它为中间表示、优化和代码生成提供了信息完备的输入。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪