bison 编译sql的基本知识
一。bison是干什么的?
bison 是一个语法分析器,把用户输入的内容,根绝在.y文件中事先定义好的规则,构建一课语法分析树。(所谓的规则就是,匹配上对应字符之后,执行相应的动作。)
1.一个简单的语法例子和分析:
statement :NAME '=' expression
expression :NUMBER '+' NUMBER
|NUMBER '-' NUMBER
这个语法的意思是:
冒号(:)用来间隔一条规则的左边和右边。
statement 等价于 NAME '=' expression 。
由于在语法中规定大写字母 和引号的内容为终结符,所以NAME '=' 两个字符不再有含义,已经终结。
但是expression 是非终结符,根据第二行的规定,expression 又等价为 两个数的加法或者两个数的减法。其中竖线(|)表示一个语法符号有两种等价方式。 NUMBER '+' NUMBER NUMBER '-' NUMBER均是终结符,所以语法解析结束。
假如现在的输入是fred=12+13. 则语法解析树如下:(圆形都是非终结符,矩形都是终结符)
2.移进 规约分析
当bison处理一个语法分析树时,会创建一组状态,每个状态对应一个或者多个分析过的规则中的可能的位置。当读到的记号不足以结束一条规则的时候,就会把这个记号压入一个内部堆栈,然后切换到新状态,这个过程叫做移进。当压入栈内的所有的语法符号已经等价于一个规则的右部时,就把这些符号全部弹出,把规则的左部压入栈。这个过程叫做规约。
下面是一个例子:
fred=12+13
语法分析器一次移进一个记号。
堆栈:
fred
fred =
fred =12
fred=12 +
fred =12+13 把12+13 规约成expression,12+13弹出,expression压入
fred = expression 把fred = expression规约成statement fred = expression弹出,statement压入
statement
3.sql语言中的语法解析过程。(以select为例)
首先,需要一个词法分析器来识别SQL中的所有关键字。
程序的运行流程:(以select为例)
1.用户输入sql语句,调用sql.tab.c中的解析函数,得到select_statement的状态。(。y文件中为sql语句定义了好多个状态。)
2.select_statement作为参数,去匹配规则,并执行相应的动作,即构建一课语法树。这个匹配的过程由yyparse()库函数来完成!
下面这段代码是.y文件中,定义的关于select_statement部分的代码:
- select_statement:
- SELECT selection table_exp
- {
- struct stnode * p = create_non_terminal_node("select_section");
- if(!p)
- {
- printf("error:create_non_terminal_node\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- $$ = p;
- }
- selection:
- scalar_exp_list
- {
- struct stnode * p = create_non_terminal_node("selection");
- if(!p)
- {
- printf("error:create_non_terminal_node\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- $$ = p;
- }
- | '*'
- {
- struct stnode * p = create_non_terminal_node("selection");
- if(!p)
- {
- printf("error:create_non_terminal_node\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- $$ = p;
- }
- ;
- scalar_exp_list:
- scalar_exp
- {
- struct stnode * p = create_non_terminal_node("scalar_exp_list");
- if(!p)
- {
- printf("error:create_non_terminal_node\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- $$ = p;
- }
- | scalar_exp_list','scalar_exp
- {
- struct stnode * p = create_non_terminal_node("scalar_exp_list");
- if(!p)
- {
- printf("error:create_non_terminal_node\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- $$ = p;
- }
- ;
- table_exp:
- from_clause
- opt_order_by_clause
- {
- struct stnode * p = create_non_terminal_node("table_exp");
- if(!p)
- {
- printf("error:create_non_terminal_node\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- $$ = p;
- }
- ;
- from_clause:
- FROM table_ref_list opt_where_clause
- {
- struct stnode * p = create_non_terminal_node("from_clause");
- if(!p)
- {
- printf("error:create_non_terminal_node\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- $$ = p;
- }
- ;
- table_ref_list:
- table_ref
- {
- struct stnode * p = create_non_terminal_node("table_ref_list");
- if(!p)
- {
- printf("error:create_non_terminal_node\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- $$ = p;
- }
- | table_ref_list','table_ref
- {
- struct stnode * p = create_non_terminal_node("table_ref_list");
- if(!p)
- {
- printf("error:create_non_terminal_node\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- $$ = p;
- }
- ;
- table_ref:
- table
- {
- struct stnode * p = create_non_terminal_node("table_ref");
- if(!p)
- {
- printf("error:create_non_terminal_node\n");
- return ;
- }
- if(!append_child(p, $))
- {
- printf("error:append_child\n");
- return ;
- }
- $$ = p;
- }
- ;
3.根据上面代码中的定义的规则,,,,展示下面的语法树的构建过程:
规则 动作: 语法树
select_statement : SELECT selection table_exp node("select_section") select_statement
SELECT selection table_exp
selection : scalar_exp_list node("selection") *
|*
table_exp : from_clause opt_order_by_clause node("table_exp") from_clause opt_order_by_clause
from_clause: FROM table_ref_list opt_where_clause node("from_clause") FROM table_ref_list opt_where_clause
table_ref_list :table_ref
| table_ref_list','table_ref node("table_ref_list ") table_ref
table_ref: table node("table ") table
bison 编译sql的基本知识的更多相关文章
- SQL server基础知识(表操作、数据约束、多表链接查询)
SQL server基础知识 一.基础知识 (1).存储结构:数据库->表->数据 (2).管理数据库 增加:create database 数据库名称 删除:drop database ...
- Sql Server 基础知识
Sql Server 基础知识: http://blog.csdn.net/t6786780/article/details/4525652 Sql Server 语句大全: http://www.c ...
- atitit.查看预编译sql问号 本质and原理and查看原生sql语句
atitit.查看预编译sql问号 本质and原理and查看原生sql语句 1. 预编译原理. 1 2. preparedStatement 有三大优点: 1 3. How to look gene ...
- SQL数据库基础知识-巩固篇<一>
SQL数据库基础知识-巩固篇<一>... =============== 首先展示两款我个人很喜欢的数据库-专用于平时个人SQL技术的练习<特点:体积小,好安装和好卸载,功能完全够用 ...
- mybatis中预编译sql与非预编译sql
预编译sql有缓存作用,非预编译没得 mybaits中带有#传参的有预编译左右,$没得 多用#传参 预编译语句的优势在于归纳为:一次编译.多次运行,省去了解析优化等过程:此外预编译语句能防止sql注入 ...
- APK反编译之一:基础知识—APK、Dalvik字节码和smali文件
refs: APK反编译之一:基础知识http://blog.csdn.net/lpohvbe/article/details/7981386 APK反编译之二:工具介绍http://blog.csd ...
- SQL语句之 知识补充
SQL语句之 知识补充 一.存储过程 运用SQL语句,写出一个像函数的模块,这就是存储过程. 需求: 编写存储过程,查询所有员工 -- 创建存储过程(必须要指定结束符号) -- 定义结束符号 DELI ...
- hibernate预编译SQL语句中的setParameter和setParameterList
使用预编译SQL语句和占位符參数(在jdbc中是?),可以避免由于使用字符串拼接sql语句带来的复杂性.我们先来简单的看下.使用预编译SQL语句的优点. 使用String sql = "se ...
- 转:sql server锁知识及锁应用
sql server锁(lock)知识及锁应用 提示:这里所摘抄的关于锁的知识有的是不同sql server版本的,对应于特定版本时会有问题. 一 关于锁的基础知识 (一). 为什么要引入锁 当多个用 ...
随机推荐
- 由浅到深理解ROS(4)
消息和消息类型 节点能相互传递消息,节点之间通信也是基于消息.消息类型也就是数据类型数据类型,理解消息的类型很重要,因为它决定了消息的内容.也就是说,一个话题的消息类型能告诉你该话题中每个消息携带了哪 ...
- .Net 开发Windows Service
1.首先创建一个Windows Service 2.创建完成后切换到代码视图,代码中默认有OnStart和OnStop方法执行服务开启和服务停止执行的操作,下面代码是详细解释: using Syste ...
- 九度OJ 1188:约瑟夫环 (约瑟夫环)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1891 解决:817 题目描述: N个人围成一圈顺序编号,从1号开始按1.2.3......顺序报数,报p者退出圈外,其余的人再从1.2.3 ...
- Generally a good method to avoid this is to randomly shuffle the data prior to each epoch of training.
http://ufldl.stanford.edu/tutorial/supervised/OptimizationStochasticGradientDescent/
- flex (html弹性布局)
flex是什么? 任何容器都可以指定为flex布局: .box{ display: flex; /* 行内元素可以使用:inline-flex,webket内核浏览器必须 -webkit-flex ...
- php在不同平台下路径分隔符不同的解决办法
在看phpamf时看到一个常量“DIRECTORY_SEPARATOR”,最后发现是一个全局的常量,用来定义路径分隔符的 主要解决在windows和linux下路径分隔符不同的造成代码不通用的问题,在 ...
- Django 模型系统(model)&ORM--进阶
QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. >>> Entry.objects.all()[ ...
- 计算机网络协议层次(转发:http://blog.csdn.net/gavin_john/article/details/53186570)
计算机网络学习的核心内容就是网络协议的学习.网络协议是为计算机网络中进行数据交换而建立的规则.标准或者说是约定的集合.计算机网络协议同我们的语言一样,多种多样. 为了给网络协议的设计提供一个结构,网络 ...
- 查看mysql支持的存储引擎
查看mysql支持的存储引擎 show engines\G;
- linux 指令(经常更新)
添加一个服务 # sudo update-rc.d 服务名 defaults 99 删除一个服务 # sudo update-rc.d 服务名 remove 临时重启一个服务 # /etc/init. ...