• go语言ast语法解析


    通过Demo来了解语法解析的过程

    了解 ast 语法解析,我们先从一个简单的 demo 开始,正向看看 ast 解析代码的过程,过程虽然不复杂,但是特别繁琐。

    看下面的代码,真实的环境中 32 行的 ParsePeople 是不存在的,我们要使用 ast 语法解析,通过分析 14 行的 BuildPeople 来自动生成 33 行的 BuildPeople 代码。

    业务上因为之前的写法有点难看了,但这种写法的代码又特别多,想结合 ast 来自动实现替换,这样也不太容易出错(整个例子都是假设的)。

    在这里插入图片描述

    核心的步骤就是①遍历整个语法树,找到目标的位置进行处理。这个例子比较简单,IfStmt 就是我们的目标位置,fSet和fNode、以及Inspect都属于标准处理方式。

    接下来解析的就是②断言类型,你会遇到各种各样的语法类型,只需要不停地做断言,不停地做case判断。IfStmt 结构体中的两个成员,一个是 Cond 属于 Expr 接口类型,一个是 Body 属于 BlockStmt 类型。

    import (
    	"go/ast"
    	"go/parser"
    	"go/token"
    	"log"
    )
    
    func main() {
    	fSet := token.NewFileSet()
    	fNode, err := parser.ParseFile(fSet, "/pwd/ifstat.txt", nil, parser.ParseComments)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	ast.Inspect(fNode, func(node ast.Node) bool {
    		switch n := node.(type) {
    		case *ast.IfStmt:
    		}
    		return true
    	})
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    拿 Expr 这个接口来说,断言的时候,你完全不需要知道有哪些类型实现了这个接口,我们只需要勤劳一些,不停地做试探就可以了,我来举个例子,我们断言 Cond,只写一个 default 分支,然后打印 Cond 的类型信息

    在这里插入图片描述
    结合解析的代码可以知道,len(param) >= 2 在语法解析中的类型为 *ast.BinaryExpr,我们继续重复这样的操作就可以了。

    这个例子我们不需要解析 Cond部分,因为我们完全可以通过解析 Body 的部分来构造我们想要的代码,将 Cond 的断言更换成对 Body 的断言。结合代码输出,我们可以知道,接下来要处理的类型是 赋值语句 *ast.AssignStmt

    在这里插入图片描述
    我们获取到AssignStmt结构体之后,紧接着就获取它左边的表达式和右边的表达式,继续断言
    在这里插入图片描述
    写到这里,这种不断试探断言的方式大家应该基本了解了,后面的方式处理方式也是相同的,下面是完整的处理逻辑。
    在这里插入图片描述
    我们通过已知的结果去生成另外一种结构,通过 ast 的方式写起来真的是非常繁琐,如果只靠纯文本的方式解析,也面临很多特殊的情况。

    如果我们将这两种方式结合起来,势必会有事半功倍的效果。

    将表达式转换为字符串

    如果我们获取到表达式,我们可以直接将其转换为原始的字符串,通过字符串的方式去解析。我们一步一步入手

  • 相关阅读:
    01-Node-Express系统框架搭建(express-generator)
    快手这款推荐新算法,我爱了~
    java培训之InitBinder注解
    从头开始,手写android应用框架(一)
    Entity FrameWork Core教程,从基础应用到原理实战
    如何快速让苹果TF上架
    两数之和(哈希解法)
    回溯算法总结
    汇编语言、寄存器分类及程序计数器
    element ui:常用的组件使用情况记录
  • 原文地址:https://blog.csdn.net/f1520107395/article/details/127836908