sql语法解析

lex 和 yacc 是什么,为什么人们同时提及它们
lex 和 yacc 是一对配对工具。lex 将文件分解为成组的“记号(tokens)”,大体上类似于单词。yacc 接受 成组的记号,并将它们装配为高层次的结构,类似于句子

yacc 的语法

  • 结构,由%%分割的三部分组成:声明 %% 规则 %% 程序
  • %{与%}之间的代码将会直接出现在目标代码中
  • yacc 命令忽略语法文件中的空格、制表符和换行符
  • 注释:/* This is a comment on a line by itself. */
  • 使用’’(单引号)表示字符串
  • 优先顺序规则由 %prec 关键字定义,并更改与特定的语法规则关联的优先顺序级别。保留符号 %prec 可紧跟在语法规则的主体后面,且其后可有标记名称或者文字。构造使得语法规则的优先顺序成为标记名称或者文字的优先顺序。
  • yacc 生成的解析器将首先尝试去解析在文件的规则部分得到的第一个规则的实例, %start 来指定从哪个开始
  • $$符号可引用产生式左部非终结符的属性值,而$i则可以引用产生式右部第i个文法符号的属性值

编译生产go

1
2
goyacc -o sqlTest.go sql_test.y
gofmt -w sqlTest.go

EBNF文法

  1. ebnf2y安装
    1
    2
    3
    4
    5
    "github.com/cznic/ebnfutil"
    "github.com/cznic/strutil"
    替换成
    "modernc.org/ebnfutil"
    "modernc.org/strutil"

执行make

  1. EBNF文法
1
2
3
4
5
6
7
::= 表示定义;
< > 尖括号里的内容表示必选内容;
[ ] 中是可选项;
" " 双引号里的内容表示字符;
| 竖线两边的是可选内容,相当于or;
* 表示零个或者多个……
+ 表示一个或者多个……

解释:

$$符号可引用产生式左部非终结符的属性值,而$i则可以引用产生式右部第i个文法符号的属性值

1
2
3
4
5
6
7
8
9
into_table_name:
INTO table_name
{
$$ = $2
}
| table_name
{
$$ = $1
}

即$2代表table_name,赋值给$$

参考

anko 源代码阅读之 go 的 lex/yacc
YACC(BISON)使用指南
如何使用Lex/YACC
TiDB 源码阅读系列文章(五)TiDB SQL Parser 的实现
扩展巴科斯范式(EBNF)简介
BNF 以及 EBNF