goyacc

#lex & yacc

项目github地址
##1. 背景
网上关于lex和yacc的介绍真的又老又少,而goyacc的更加少,最近需要解析sql,接触到这块,虽然最后发现其效率没有用手动写代码解析效率高而放弃使用,但是学会了这种快速构建文法解析的工具还是有所收获吧。
##2. 相关知识
增加一点内容篇幅,不想看的直接跳到3就ok
####2.1词法分析
词法分析的作用就是对一个文本或称为一串字符串(包括空格,换行,特殊符号等)进行内容提取。通过分析给每一个字段打上标记(TOKEN)。那么如何分析呢,以sql的查询语句为例

select * from userinfo where name = 'zhang' order by age

这个字符串有多少信息呢,首先,select,from, where, order, by 这些单词在从左到右扫描时与userinfo,age这些并无不同,但很明显这些单词是数据库的保留单词,也称为关键字。所以一般的我们需要一个关键字表,在扫描到单词时判断其是可变的字段还是关键字。其次对于 * ,=,‘zhang’,我们单独将其标记为特殊符号,操作符,字符串,就这样,我们对所有的可能情况进行识别给不同类型的字段以唯一的标识(TOKEN)一般为int。所以此法分析的作用就是将一系列的文本转换成TOKEN序列。

####2.2文法分析
对于词法分析后的TOKEN序列,我们需要知道他是否符合我们的文法规范,例如

select from a=1

像这样的句子不符合sql规范,我们需要明确的指出。文法分析其实就是一个有限状态自动机,当扫描到一个TOKEN时,我们根据不同的情况跳转到另一状态,直到终结状态。
####2.3语义分析
语义阶段与文法阶段往往可以同步进行,在sql文法分析的阶段我们便可以标明该语义树的各个部分,比如在扫描到select时,我们便可以确定这是一个select语句或者可能是错误语句,然后根据后续信息补全select语法树。

##3. goyacc

为什么用goyacc,因为influxdb本身是go语言写的,我需要解析的语法树与influxdb使用的语法树相同,并且不需要二次构建,所以使用goyacc。其实还有一个原因就是go比c好写,alloc和malloc写起来,真的难受。

####工具 goyacc

go git github.com/golang/tools/cmd/goyacc
go build
go intall

####3.1 lex与yacc工作流程
go提供goyacc用于语法分析。在我们写好一个yacc规则后,使用goyacc sql.y指令生成对用的go文件。其中包含两个重要的对象

type yyLexer interface {
	Lex(lval *yySymType) int
	Error(s string)
} type yyParser interface {
	Parse(yyLexer) int
	Lookahead() int
}

yyparser是yacc自动实现的,不需要我们操作,parser是入口函数,它会不停的调用Lex函数来获取TOKEN进行文法分析。我们需要自己实现一个Lex即实现yyLexer接口。

Lex实现

type Tokenizer struct {
	query Query
	scanner *Scanner
}

func (tkn *Tokenizer) Lex(lval *yySymType) int{
	var typ int
	var val string

	for {
		typ, _, val  = tkn.scann
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值