这是我参与「第五届青训营 」伴学笔记创作活动的第 18 天
3.1 语法分析
即根据某种特定的形式文法(不同编译器或有不同文法)对 Token 序列构成的输入文本进行分析并确定其语法结构的过程。我们将词法分析串联起来就是,词法分析的输出文本————Token 序列就是语法分析的输入文本。
3.1.1 文法
上下文无关文法是用来形式化、精确描述某种编程语言的工具。文法都由以下的四个部分组成。
- N 有限个非终结符的集合;
- Σ 有限个终结符的集合;
- P 有限个生产规则的集合;
- S 非终结符集合中唯一的开始符号;
终结符是文法中无法再被展开的符号,而非终结符与之相反,还可以通过生产规则进行展开
3.1.2 分析方法
语法分析的分析方法一般分为自顶向下和自底向上两种,这两种方式会使用不同的方式对输入的 Token 序列进行推导。
- 自顶向下分析:对于任意一个输入流,根据当前的输入符号,确定一个生产规则,使用生产规则右侧的符号替代相应的非终结符向下推导。
- 自底向上分析:每次都尝试重写最右侧的多个符号,这其实是说解析器会从最简单的符号进行推导,在解析的最后合并成开始符号。
- 向前查看(Lookahead):在不同生产规则发生冲突时,当前解析器需要通过预读一些 Token 判断当前应该用什么规则对输入流进行展开或者归约。
3.1.3 LALR(1)文法
LALR(1)是Go 语言的解析器使用的文法,最右推导加向前查看构成了 Go 语言解析器的最基本原理,在这一点上大多数语言做出了同样的选择。
编译器的主函数会调用多个 Goroutine 来解析源文件,解析过程初始化了parser
结构体并调用fileOrNil
方法开启了对当前文件的词法和语法分析。
而fileOrNil
方法会先解析文件开头的package
定义,并匹配对应的包名保存到返回的文件结构体中,之后编译器会获取关键词进入 switch 的不同分支并通过appendGroup
方法传入该包中相关函数。
而fileOrNil
方法与其子方法共同构成了一棵树,树的根节点与 Go 语言的文法中的生产规则一一对应。