go语法解析之parser

4,769 阅读3分钟

golang版本: 1.13.1 


语法分析

上一篇的scanner词法分析转化后的token是提供给语法分析parser(cmd/compile/internal/syntax/parser)转成syntax tree来用的。好绕...

语法分析的定义:

语法分析是编译过程的一个逻辑阶段。语法分析的任务是在词法分析的基础上将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等.语法分析程序判断源程序在结构上是否正确.源程序的结构由上下文无关文法描述.语法分析程序可以用YACC等工具自动生成。
完成语法分析任务的程序称为语法分析器,或语法分析程序。 按照源语言的语法规则,从词法分析的结果中识别出相应的语法范畴,同时进行语法检查。

语法分析通常有两种方式:

自上而下 这种方式会首先构造根节点,然后就开始扫描 Token,遇到 STRING 或者其它类型就知道这是在进行类型申明,func 就表示是函数申明。就这样一直扫描直到程序结束。

自下而上 这种是与上一种方式相反的,它先构造子树,然后再组装成一颗完整的树。

go使用的是自下而上,接下来我们来看下go的语法分析过程吧。

分析过程

go的分析过程概述

parser首先会进行init()操作初始化一些数据,然后就进入fileOrNil()进行解析,该方法的返回值就是一个syntax tree。

fileOrNil()先判断package包名,再看是否有引入import,然后就是看是下面3个入口token的哪一个,fileOrNil()流程如下图所示:



struct和关键类

struct

解析器类


每个文件的syntax tree,这里的pos和posBase都是对当前步骤的自描述,作用是为了错误提示和之后的过程留存


appendGroup 这是对组的结构来做插入,像是上面四个都可以写成 type (tolen1;token2;token3)这样的结构


接下来我们从var的解析过程来具体了解一下,因为代码会有点多,所以就只简单的讲几个关键函数,go的写法还是比较简单的,只要知道了数据流向和流程就可以很轻松的去看一些源码。

var解析过程

var解析过程流程图如下所示:


补充:

  • exprList()在之后应该还会判断是否有 ( 这种情况 例: var a = new(int) 少了这条线

关键函数:

  • typeOrNil(): 这个函数主要解析 map[] make(map[])这些的情况
  • unaryExpr(): 这个函数主要解析 +a , <- a *a 这一类的情况

测试数据




总结

在看parser的源码过程中,可以根据原来知道的go的一些写法去推导流程,然后一些特殊的switch和if可以让你知道一些你之前不知道的写法,以及一些写法是不允许的,可以更深层次的去了解这个语言,在之后有新的commit之后可以更快的去掌握新的写法.

上面的解析过只写了var的,因为其他几个其实过程都差不多,只是生成的values的nodes不一样,如果是有需要添加可以留言,我有空也会添加上去的。

下一篇: go语义分析