面试题答案
一键面试抽象语法树(AST)的主要作用
- 结构化表示:AST以树状结构表示源代码,每个节点对应一个语法结构。这使得编译器能够方便地对代码进行分析和操作,因为它将代码的层次结构清晰展现。例如,对于
if - else
语句,AST会有对应的IfStmt
节点,其下包含条件表达式节点、then
分支节点和else
分支节点。 - 语义分析基础:通过遍历AST,编译器可以进行语义分析,如类型检查、作用域分析等。例如,检查变量是否在使用前声明,函数调用的参数类型是否匹配等。
- 代码转换基础:为中间代码生成、优化以及目标代码生成提供了基础结构。基于AST的结构,可以方便地将源代码转换为各种中间表示形式。
AST与中间代码生成的关系
- 输入基础:AST是中间代码生成的重要输入。中间代码生成器通过遍历AST,根据不同节点类型生成相应的中间代码指令。
- 指导转换:AST的结构指导着中间代码生成的流程。不同类型的节点对应不同的中间代码生成规则,通过深度优先遍历或其他遍历方式,对每个节点进行处理并生成相应中间代码片段,最终组合成完整的中间代码。
关键节点类型在中间代码生成时的处理举例
- 赋值语句节点(
AssignStmt
):- 假设Go代码为
a := 10
,在AST中会有一个AssignStmt
节点。 - 中间代码生成时,会为变量
a
分配存储位置(可能是寄存器或内存地址),然后生成指令将常量10
存储到该位置。例如,在一些简单中间表示中可能生成类似于store 10, a
的指令,其中store
是存储指令,10
是值,a
是目标存储位置。
- 假设Go代码为
- 函数调用节点(
CallExpr
):- 对于代码
result := add(a, b)
,AST中会有一个CallExpr
节点。 - 中间代码生成时,首先会生成指令将函数参数
a
和b
传递到合适的位置(如栈上),然后生成调用函数add
的指令,最后将函数返回值存储到result
对应的位置。例如,可能生成push a
,push b
,call add
,pop result
这样的中间代码序列,push
用于将参数压入栈,call
用于调用函数,pop
用于从栈中取出返回值存储到变量。
- 对于代码
- 二元运算节点(
BinaryExpr
):- 对于代码
c := a + b
,AST中有BinaryExpr
节点,操作符为+
。 - 中间代码生成时,会生成指令将
a
和b
的值加载到运算单元(如寄存器),执行加法运算,然后将结果存储到c
。例如,可能生成load a, r1
,load b, r2
,add r1, r2, r3
,store r3, c
,其中load
用于加载值到寄存器,add
执行加法运算,store
将结果存储到变量c
。
- 对于代码