在mysql源码中,解析sql在sql_yacc.yy中实现,这个文件是一个硕大的文件,用bison来转换为c文件。
在《编译原理及实践》中有yacc介绍,编译原理是很深奥的科目,学好了对编程技术好很大的帮助,可惜当初没好好学,需要回炉一下。
这里是从《编译原理及实践》的摘录。
一个简单的算术表达式的计算器。calc.y,BNF文法如下:
%{
#include <stdio.h>
#include <ctype.h>
%}
%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
程序已经可以跑了,当输入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中有用到。
相关推荐
yacc 和flex的介绍,详细介绍了yacc和flex的使用方法
完整介绍Lex和Yacc Windows 上的使用 及工具的按装, 及环境变量的设置, GNU Bison实际上是使用最广泛的Yacc-like分析器生成器,使用它可以生成解释器,编译器,协议实现等多种程序. 它不但与Yacc兼容还具有许多Yacc不...
lex yacc的介绍文档 学习编译原理不容错过,内有词法分析的一个自动软件 很有名
Lex和Yacc简明教程 介绍基本lex和yacc的使用方法
编译原理概述 介绍PL/0编译程序 ...Yacc介绍,布置PP2 习题课 语法分析方法比较 语法制导翻译,布置PP3 语法制导翻译 运行时存储组织 运行时存储组织 代码优化, 布置PP4 代码生成 实践题目总结答辩
详细介绍了lex与yacc的语法规则,使用方法。
介绍lex和yacc的一些原理,以及其在词法分析和语法分析的作用。
Yacc 与 Lex 快速入门 介绍的一些基础
编译原理的上机环境工具及说明文档,Parser介绍 ,YACC和LEX的应用
简单介绍unix下的工具lex 和 yacc的语法与应用,很不错的资料
这是编译器Lex Yacc使用手册,介绍了它们的使用方法,大家可以用来编写编译器
Lex和Yacc工具使用方法,介绍了编译原理课程中的工具lex和yacc的基础使用方法
介绍flex-bison的使用,用简单的例子做示例,快速掌握两者的使用,其中有大量的例子进行解析
非常不错的介绍yacc的很全面的文档,与大家分享!
此文档详细介绍了lex和yacc的词法语法分析,附有部分源码,是比较不错的东东。
语法分析程序的自动生成工具YACC相关知识介绍。
本系列文档就是专门用来由浅入深的介绍两 个有名的Unix 工 具Lex 和Yacc,并会一步一步的详细解释如何用这两个工具 来实现我们想要的任何 功能的解析程序
详细全面介绍了lex和yacc,给初学者一个很好的教材。不但是你全面了解lex和yacc,而且给你很多例子。
简单介绍lex和yacc的使用及配置方法 还有学习笔记等 附含工具
Lex 是一种生成扫描器的工具。扫描器是一种识别文本中的词汇模式的程序。 这些词汇模式(或者常规表达式)在一种特殊的句子结构中定义。该书详细的介绍LEX与YACC的使用,以及例程