语法树与抽象语法树
复习
- 语法分析要解决什么:给出语法结构
- 上下文无关文法:推导对应语法树
- 树:用父子关系表示层次结构
TL;DR
- 语法树忠实反映文法推导的每一步
- 抽象语法树(AST)去掉了只为文法服务的节点
- AST 更简洁,更适合后续处理
- 语义分析和代码生成主要基于 AST
正文
语法分析的结果是一棵树。不过,这棵树有两种“详细程度”,需要分清。
忠实记录推导的“具体语法树”
最直接的产物叫具体语法树(也叫语法分析树,parse tree)。它忠实反映推导的每一步:每用一条产生式,就长出一层节点。
好处是完整、精确;坏处是啰嗦。很多节点只是文法的“中间产物”,对理解程序含义没什么用。
比如 1 + 2 用分层文法推导,可能会长出“表达式 → 项 → 因子 → 数字”这样一串中间节点,还有括号之类的符号节点。可对“计算 1+2”来说,我们关心的是“加法,左 1、右 2”,那些中间层纯属陪衬。
精简之后的“抽象语法树”
抽象语法树(AST,Abstract Syntax Tree)就是去掉这些陪衬后的结果:只保留真正有意义的语法结构——运算符、操作数、控制结构等,去掉那些只为文法服务的中间节点和冗余符号。
对比一下 1 + 2 * 3:
- 具体语法树:层层叠叠,包含所有中间非终结符和括号
- 抽象语法树:一个
+节点,左孩子是1,右孩子是一个*节点(左 2、右 3)
后者小得多,也清楚得多,一眼就能看出“先乘后加”。 这正是编译器想要的。
后续阶段为什么爱用它
编译器后面的阶段——语义分析、优化、代码生成——几乎都以 AST 为基础。原因很自然:
- 它精简,处理起来更快
- 它只表达语义结构,不带文法噪音,逻辑更清晰
- 它与具体文法解耦,换一种写法解析同一段程序,AST 可以保持一致
可以说,从“具体语法树”到“抽象语法树”,是编译器做的第一次重要抽象。 它把“文法怎么推导”这件事留在身后,正式进入“程序是什么意思”的世界。
而这,正是下一组——语义分析——要登场的舞台。
思考题 1
具体语法树和抽象语法树,有什么区别?
思考题 2
为什么编译器的后续阶段更愿意使用抽象语法树?
小结
知识点
- 具体语法树忠实反映文法推导的每一步
- 抽象语法树去掉只为文法服务的中间节点
- AST 更精简、更清晰,且与具体文法解耦
- 语义分析与代码生成主要以 AST 为基础
参考资料
- Wikipedia(zh):抽象语法树:去掉冗余节点后的语法结构表示
- Wikipedia(zh):语法树:推导过程的树形表示
思考题答案(仅供参考)
思考题 1
具体语法树忠实记录推导的每一步,包含所有中间非终结符和符号节点,比较冗长;抽象语法树则去掉这些只为文法服务的节点,只保留有语义的结构(如运算符、操作数、控制结构),因此更精简。
思考题 2
因为 AST 更小、更清晰,去掉了文法噪音,只表达程序的语义结构,处理更快也更方便;而且它与具体文法解耦,即使解析方式变化,AST 也能保持稳定。所以后续的语义分析、优化和代码生成都基于它。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪