Golang 的语法分析主要流程由 cmd/compile/internal/gc/noder.go 文件完成,这一步是在词法分析之后,会将 Go 源文件转成 AST。先来看来表示AST的基本数据结构(仅列举 Node 与 Type 类型,其他的类型可参见源码)。
// Node表示AST中的结点,是一个基础结构,用于将整个源代码串联起来
Node 是基本的结点结构,用于表示整棵语法树。Type 表示 Go 中的类型。还有其它的结构没有列出来,具体的可以见源码。下面举几个例子。
1 包导入
import
AST:
Pack 即 package,表示此棵语法树为包语法树。fmt 是要导入的包。Pkg 中另外一种结构,包含 fmt 包的基本信息。
2 类型定义
type
AST:
结构体定义相对复杂,但也并不难理解。ODCLTYPE 表示声明一个类型定义,OTYPE 代表一棵具体的类型语法树。
3 定义变量:
var
AST:
变量定义的 AST 比较简单,但有两棵语法树,左边是声明,右边是初始化。ODCL 结构定义声明变量 number1,OAS 给变量 number1 赋值100。
4 函数定义
func
AST:
函数定义的结构比较复杂,但并不难理解。函数类型包括入参与出参。入参由 List 保存,出参由 Rlist 保存。图中 OTFUNC 的 Left 子节点代表函数的接收者(本例中为空)。
再看下语法解析的流程。整棵语法树的构建由 noder.go:decls 函数开始,然后递归地进行。
func
decls 函数由一个大的 for 循环组成。在循环中判定声明的类型,然后调用对应的函数进行处理。变量,常量,类型以及函数的声明和定义所生成的 Node 结构最终会被追加到 xtop。xtop 代表的就是最终生成的语法树。
func
stmtFall 函数主要处理语句,例如赋值,函数调用,if/for/switch 等。它由一个不算很大的switch 组成。
func
expr 函数也是由一个不算很长的 switch 语句组成。若对 Go 语法比较熟悉的话,decls, stmtFall, expr 等函数的处理流程还是比较好理解的,按照声明,语句,表达式逐步处理。生成的 xtop 语法树为下一步的类型检查做好了准备。