Pisa-Proxy SQL 解析之 Lex & Yacc

本文介绍了Pisa-Proxy SQL解析器的实现,涉及编译器工作流程、词法分析(直接扫描法与正则表达式扫描法)和语法分析。重点讲解了词法分析工具Lex和Yacc的使用,通过实例展示了如何使用Lex和Yacc构建简单的SQL解析器。文章最后简要分析了Pisa-Proxy的SQL解析实现。
摘要由CSDN通过智能技术生成

一、前言

1.1 作者介绍

王波,SphereEx MeshLab 研发工程师,目前专注于 Database Mesh,Cloud Native 的研发。Linux,llvm,yacc,ebpf user。 Gopher & Rustacean and c bug hunter。

GitHub: https://github.com/wbtlb

1.2 背景

在上篇文章《Pisa-Proxy 之 SQL 解析实践》中介绍了 Pisa-Proxy 的核心模块之一 SQL 解析器的相关内容。在 MySQL 和 PostgreSQL 中 SQL 解析是通过 Yacc 实现的,同样 Pisa- Proxy 的 SQL 解析器是由类似 Yacc 这样的工具实现的,所以本篇文章会围绕 SQL 解析器为大家介绍一些编译原理和 Lex & Yacc 的使用,同时也会为读者展示如何通过 Lex & Yacc 实现一个简单的 SQL 解析器。从而帮助大家更好地理解 Pisa-Proxy 中 SQL 解析器是如何工作的。

二、编译器初探

一个程序语言不论是我们常用的 Java,Golang 或者是 SQL 本质上都是一个记号系统,如同自然语言一样,它的完整定义应该包括语法和语义两个方面。一种语言的语法其实是对应的一组规则,用它可以形成和产生一个合适的程序。当前使用最广泛的手段是上下文无关的文法,上下文无关的文法作为程序设计语言语法的描述工具。语法只是定义什么样的符号序列是合法的,与这些符号的含义毫无关系。然而在语义中分为两类:静态语义和动态语义。静态语义是指一系列的限定规则,并确定哪些语法对于程序来说是合适的;动态语义也称作运行语义或者执行语义,明确程序具体要计算什么。

2.1 编译器工作流程

如图 2.1.1 中所示,通常编译器将源代码编译成可执行文件主要有以下几步:

  1. 对源文件进行扫描,将源文件的字符流拆分分一个个的词(token),此为词法分析
  2. 根据语法规则将这些记号构造出语法树,此为语法分析
  3. 对语法树的各个节点之间的关系进行检查,检查语义规则是否被违背,同时对语法树进行必要的优化,此为语义分析
  4. 遍历语法树的节点,将各节点转化为中间代码,并按特定的顺序拼装起来,此为中间代码生成
  5. 对中间代码进行优化
  6. 将中间代码转化为目标代码
  7. 对目标代码进行优化,生成最终的目标程序

图 2.1.1

对于 SQL 解析来说,就可以将上图中的步骤简化为如图 2.1.2 的形式,源码输入(SQL 语句),将 SQL 语句进行词法分析,生成 SQL 中特定的 token 记号流。然后拿到记号流后进行语法分析后生成最终的 SQL AST。

图 2.1.2

2.2 词法分析

上文中提到,无论是编译器还是 SQL 解析器有一个关键步骤就是要对源文件做词法分析,词法分析我们可以理解为对 SQL 语句本身做分词处理。那么在这个阶段,SQL 解析器要做的工作就是从左到右扫描源文件,将 SQL 语句分割成一个个的 token,这里说的 token 是指 SQL 中不能再进一步分割的一串字符。例如图 2.1.2 中的 SQL 语句,经过词法分析后,生成的 token 为:SELECT*FROMpisa_proxy 等等。

在 SQL 语句中能用到的 token 类别也是有限的,比如保留字 SELECTINSERTDELETE 等等。还有操作符,比如:算术操作符、比较操作符。还有标识符,比如:内置函数名等等。在此阶段每扫描一个 token 会被维护到一个数据结构中,然后在下个阶段语法分析阶段使用。
通常来说,词法分析有直接扫描,正则匹配扫描方式。

2.2.1 直接扫描法

直接扫描法逻辑非常清晰,每次扫描根据第一个字符判断属于哪种类型的 token,然后采取不同的策略扫描出一个完整的 token,然后再进行下一轮扫描。在 Pisa-Proxy 中的 SQL 解析中,词法分析就采用了这种实现方式,用 Python 展示如何实现一个简单的 SQL 词法分析器对 SQL 进行扫描,代码如下:

# -*- coding: utf-8 -*-

single_char_operators_typeA = {
    ";", ",", "(", ")","/", "+", "-", "*", "%", ".",
}

single_char_operators_typeB = {
    "<", ">", "=", "!"
}

double_char_operators = {
    ">=", "<=", "==", "~="
}

reservedWords = {
    "select", "insert", "update", "delete", "show",
    "create", "set", "grant", 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值