通过 Goyacc 构建 Elasticsearch Querystring 解析器 - 领域特定语言语法分析实践

本文介绍了如何使用 Goyacc 创建 Elasticsearch Querystring 解析器。通过Goyacc构建的DSL解析器包括语法分析器和词法分析器,详细讲解了Goyacc的使用,如安装、语法定义文件、AST节点定义等,并分享了一个Querystring解析器的实现。
摘要由CSDN通过智能技术生成

 

背景

领域特定语言(DSL),如 SQL、Elasticsearch Querystring 等,往往是为专门的目的设计的。在特定的任务中,DSL 通过在表达能力上做的妥协换取在某一领域内的高效。

在飞书套件日志系统的私有化研发过程中,为了符合研发同学查询日志的习惯,尝试使用 Elasticquery Querystring(下简称为 Querystring)作为过滤器的查询条件语句,由此需要可用的 Golang Querystring 解析器。由于目前开源界无法找到完善的实现,尝试使用 Goyacc 自行构建。

Yacc 是一个被普遍采用的编译器代码生成器,生成出的代码主要用于语法分析阶段,常常与作为词法分析器的 lex 匹配使用,使用 LALR 算法,将源代码构建为抽象语法树(AST)。Goyacc 是 yacc 的 Golang 版本。

本文尝试实现的 Querystring 解析器本质上是词法分析器和语法分析器的组合。语法分析器由 Goyacc 生成;为了方便实现符合 Querystring 习惯的反转义,词法分析器是自行实现的。Yacc 和它在各个语言上的实现,中文互联网上较少有具体的介绍。本文会尽量详细的描述 Goyacc 实践中可能需要注意的点。所述的 Querystring 解析器代码可在 https://github.com/bytedance/go-querystring-parser 此处查看。

框架

一套完整的应用 Goyacc 的 DSL 解析器包含以下部分:

  • 语法分析器(parser)

  • 词法分析器(lexer)

    • 较为简单的做法,是采用Scanner来进行构建;当存在特殊需求时,一般自行构建。

  • AST 节点的定义

  • 包装实体与工具函数

大致流程为,语法分析器调用词法分析器将源代码拆解为基本「Token(记号)」,根据语法规程将若干个「Token」组合成「Expr(表达式)」(Token 本身也被作为 Expr 处理)。「Expr」的结构构建在「AST」中,得到结果。

语法分析器

语法分析(syntactic analysis,或 parsing)是根据某种给定的形式文法对由记号序列构成的输入文本进行分析并确定其语法结构的一种过程。

语法分析器的作用是进行语法检查、并构建由输入的记号组成的数据结构(一般是语法分析树、抽象语法树等层次化的数据结构)。语法分析器通常使用一个独立的词法分析器从输入字符流中分离出一个个的「记号」,并将记号流作为其输入。实际开发中,语法分析器可以手工编写,也可以使用工具(半)自动生成。

在本例中,即为工具自动生成。使用巴科斯范式描述对应的语法定义,并使用 goyacc 生成 golang 代码,提供一个 LALR 语法分析器,并定义了供 lexer 返回的 token 定义。

安装 Goyacc

在安装了 golang 的环境中,执行:

1go get -u golang.org/x/tools/cmd/goyacc

如安装后无法正常运行,请检查 $GOPATH/bin 是否加入到了 $PATH 中。

Goyacc 语法定义文件

一个 yacc 语法定义文件,一般由以下若干部分构成。

头部目标语言代码

可参考「附录一:L1-L3」,使用 %{  和 }% 将需要的目标语言原生代码段落包围起来。目标语言往往涉及到语言应用中的一些头部代码。在例子里,golang 所需的包名称定义等需要通过这一部分添加进来。其他的例子如常量的定义、结构体的定义等。

Union(集合)声明

可参考「附录一:L5-L9」,以 %union{} 格式定义,只可定义一次。「Union」这一概念包含了下述类型声明中的各个类型,及这些类型对应的目标语言类型(即 Golang 中的类型)。与 c 语言中 union 的概念类似,在目标代码中(生成为 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倾听铃的声

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值