语法分析 | 青训营笔记

56 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 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 语言的文法中的生产规则一一对应。

image.png