mysql yacc 解析_yacc介绍

这篇博客介绍了MySQL源码中SQL解析的实现,主要在sql_yacc.yy文件中,该文件由bison转换而来。文章通过一个简单的算术表达式计算器的yacc文法示例,解释了编译原理如何应用于SQL解析。内容包括yylex的手动实现、LALR(1)分析栈的工作原理以及bison生成的解析过程。通过实际编译和运行,展示了如何将输入的SQL表达式转化为计算结果。
摘要由CSDN通过智能技术生成

在mysql源码中,解析sql在sql_yacc.yy中实现,这个文件是一个硕大的文件,用bison来转换为c文件。

在《编译原理及实践》中有yacc介绍,编译原理是很深奥的科目,学好了对编程技术好很大的帮助,可惜当初没好好学,需要回炉一下。

这里是从《编译原理及实践》的摘录。

一个简单的算术表达式的计算器。calc.y,BNF文法如下:

d3b782562c62cdd2e29b0600e6d9ed77.png

%{

#include

#include

%}

%token NUMBER

%%

command : exp { printf("%d\n", $1);}

;

exp : exp '+' term { $$ = $1 + $3 ;}

| exp '-' term { $$ = $1 - $3 ;}

| term { $$ = $1 ;}

;

term : term '*' factor { $$ = $1 * $3 ;}

| factor { $$ = $1 ;}

;

factor : NUMBER { $$ = $1 ;}

| '(' exp ')' { $$ = $2 ;}

;

%%

main(){

/*extern int yydebug ;    ------- 此处为debug显示yacc执行调用用

yydebug = 1 ;*/

return yyparse();

}

int yylex(void){           -------可以通过lex工具来进行词法分析,这里用手工实现

int c ;

while( (c = getchar()) == ' ');

if( isdigit(c) ){

ungetc(c, stdin);

scanf("%d", &yylval);

return (NUMBER);

}

if (c == '\n') return 0 ;      ------0表示输入结束,结束词法分析

return (c) ;

}

int yyerror(char* s){

fprintf(stderr,"%s\n",s);

return 0 ;

}

上面的yylex,可以通过lex来实现,这里为手工实现。

同过main函数可以看出,执行yyparse,这个为yacc这类的工具产生的的方法,就是根据文法执行%%之间的用户定义的操作。

每个在L A L R ( 1 )分析栈中的符号值都可通过使用以$开始的伪变量来引用。$ $代表刚才被识别出来的非终结符的值,也就是在文法规则左边的符号。伪变量$ 1、$ 2、$ 3等等都代表了文法规则右边的每个连续的符号。

个人理解就是当文法匹配,执行{}里面的语句。

执行一下看看效果,bison -y calc.y  gcc y.tab.c -o test ----y.tab.c为自动产生的c文件

执行./test

4877c2f5adeeea47d218f4df0f8d5060.png

程序已经可以跑了,当输入12+4回车时,结果已经出来了。

把main函数的注释去掉,用bison -y -t 产生c文件,再用gcc y.tab.c -o test 编译

执行./test

显示如下:

Starting parse

Entering state 0

Reading a token: 12+3   ---此处为手工输入的值

Next token is token NUMBER ()

Shifting token NUMBER ()

Entering state 1

Reducing stack by rule 7 (line 19):   -----19行为factor : NUMBER { $$ = $1 ;}

$1 = token NUMBER ()

-> $$ = nterm factor ()

Stack now 0

Entering state 6

Reducing stack by rule 6 (line 17):  -----17行为factor { $$ = $1 ;}

$1 = nterm factor ()

-> $$ = nterm term ()

Stack now 0

Entering state 5

Reading a token: Next token is token '+' ()  ---解析到+号

Reducing stack by rule 4 (line 14):   ----14行为term { $$ = $1 ;}

$1 = nterm term ()

-> $$ = nterm exp ()

Stack now 0

Entering state 4

Next token is token '+' ()

Shifting token '+' ()

Entering state 9

Reading a token: Next token is token NUMBER ()

Shifting token NUMBER ()

Entering state 1

Reducing stack by rule 7 (line 19):  -----19行为factor : NUMBER { $$ = $1 ;}

$1 = token NUMBER ()

-> $$ = nterm factor ()

Stack now 0 4 9

Entering state 6

Reducing stack by rule 6 (line 17):  -----17行为factor { $$ = $1 ;}

$1 = nterm factor ()

-> $$ = nterm term ()

Stack now 0 4 9

Entering state 13

Reading a token: Now at end of input.

Reducing stack by rule 2 (line 12):   ----12行为exp : exp '+' term { $$ = $1 + $3 ;}

$1 = nterm exp ()

$2 = token '+' ()

$3 = nterm term ()

-> $$ = nterm exp ()

Stack now 0

Entering state 4

Now at end of input.

Reducing stack by rule 1 (line 10): ----10行为command : exp { printf("%d\n", $1);}

$1 = nterm exp ()

15

-> $$ = nterm command ()

Stack now 0

Entering state 3

Now at end of input.

Stack now 0 3

Cleanup: popping nterm command ()

yacc这东西还挺神奇,java也有个javacc,也能实现同样的功能,amoeba中有用到。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值