【编译原理之】Bison 源文件结构原理
来源:互联网 发布:fc2域名用不了2017 编辑:程序博客网 时间:2024/04/20 07:25
- 0x00 What is BISON
- BISON源文件的结构
- 一 自由定义部分
- 二 语法栈的联合UNION结构
- 三 非终结符的类型声明
- 四 单词声明
- 五 确定运算符的优先级
- 六 声明语法的开始符号
- 七 语法规则定义
- 八 自由添加的C源代码
- A
- B
- C
- D
- E
- F
- BISON源文件的结构
- 0x01 参考
- 0x00 What is BISON
0x00 What is BISON
BISON用于语法分析器的自动生成,这个工具可以在网上下载获得。 化点时间学习这个工具的用法,并用于SQL语言的分析,可以让我们把精力专注在语法规则上,而不是具体的分析函数编写上。对整个DBMS来说,使用自动化工具进行语言处理程序的自动生成,使得语言分析模块成为最可靠最方便维护的模块之一。
BISON源文件的结构
我们需要按照BISON的要求,书写BISON的源程序(gramma.y),然后由BISON把它翻译为C文件。因此,BISON是编译程序的翻译器。BISON的源文件通常由八个部分组成:
一. 自由定义部分:
%{%}
这部分被BISON原封不动地复制到输出的.C文件中。
二. 语法栈的联合(UNION)结构
语法分析程序使用一个堆栈来存放规约到的各个语法成分,堆栈用一个数组表示,这个数组的每个元素需要能够描述每一个语法成分,所以采用一个UNION:
%union{}
Union中的每一个项,都是一个语法规则的每一个非终结符;以整数四则表达式为例:
exp : exp ‘+’ exp | exp ‘-‘ exp | exp ‘*’ exp | exp ‘/’ exp | ‘(‘ exp ‘)’ | lt_integer;
lt_integer: LT_INTEGER;
有两个语法规则,对应了两个非终结符号: exp 是表达式, lt_integer表示整数常量(LT_INTEGER表示词法分析程序返回的一个确认为整数的单词)。 对应的,这个union可以书写为:
%{ par_exp_t* exp; int lt_integer;};
其中par_exp_t用来描述被识别出的exp的信息,int存放被识别出的整数的值。上面的例子很简单,所以union只有两个字段;在DM的语法分析程序中,这个UNION大约有490个字段,也就是,大概有490个语法规则产生式。
三. 非终结符的类型声明
上面定义了分析栈的UNION类型, 还需要把字段名与语法非终结符号对应起来:
%type <</SPAN>字段名> 非终结符号
如上例,这部分应该写为:
%type exp%type lt_integer
看上去似乎有点多余,每一行都是一个简单的重复。但前面一个表示的是UNION中对应的字段名,后一个是语法符号;如果我们把UNION改为:
%{par_exp_t* eeee;int iiii;};
那么对应的类型声明需要改为:
%type <eeee> exp%type <iiii> lt_integer;
这种不一致的写法,事实上会造成混乱,所以在DM系统中,采用上面一致的写法。
四: 单词声明
语法分析的输入是连续的有确定意义的单词。下面需要声明分析程序支持的单词:
%token LT_INTEGER
对于SQL语法,关键字如:SELECT, FROM, WHERE等,都可以定义为单词:
%token KW_SELECT, KW_FROM%token KW_WHERE
五. 确定运算符的优先级
%left ‘-‘ ‘+’%left ‘*’ ‘/’%left ‘(‘ ‘)’
%left表示是左结合的,表示先规约左边的产生式,反应到表达式计算中:
1 + 2 + 3 别识别为:((1 + 2) + 3), 而不是 (1 + (2 + 3))
优先级低的符号列在前面,高有限级的符号列在后面;同一行的表示优先级相同。所以上面的书写方式, 符合“先乘除,后加减,括号最优先”的原则。
除了%left以后,还有%right, %nonassoc等用来只是右结合,或者不结合等说明符号,可查看bison的详细说明。
六. 声明语法的开始符号
%start exp
这是告知bison, 这是语法最终需要规约的非终结符号。
七. 语法规则定义
这是语法分析程序的核心定义部分,用%%开始, 前面已经列出了关于表达式的语法规则:
%%exp : exp ‘+’ exp | exp ‘-‘ exp | exp ‘*’ exp | exp ‘/’ exp | ‘(‘ exp ‘)’ | lt_integer;
lt_integer: LT_INTEGER;
八. 自由添加的C源代码
在语法规则定义部分的后面,可以用%%开始,定义C的辅助代码。这部分代码将被原封不动地复制到输出的.C文件中。
给语法规则配上规约动作
规约动作是一段C代码,它的作用是每当分析器识别出一个语法符号时,调用该代码,完成一定的动作。通常,我们使用这段代码,来建立当前语法节点与子节点勾连动作。规约动作应该紧接在语法规则的后面。
如上例:语法分析器 <wbr>BISON
这里仅列出了其中的两个子规则, 其中A, B, C, D四个语句构成了第一个子规则的语句块:
A:
为识别出的exp 生成一个结构, 用指向它。$$
是一个bison定义的特殊标记,其意义是当前语法栈的规约元素。如果没有规约动作代码,缺省情况下赋予$$
为NULL。new_node是一个需要自己编写的函数,用于生成各个子节点,PAR_EXP是一个事先定义的常量。显然,对于不同的规则,需要定义不同的常量类型。象new_node这样的函数,一般放在.y文件的最后一个部分。
B:
用来区分是哪个子规则规约的,这里用tag = 1来表示两个子表达式‘+’运算
C:
保留第一个子表达式;$1表示这个产生式的第1个语法成分所在的语法栈中对应的值
D:
保留第二个子表达式;$
3表示这个产生式的第3个语法成分所在的语法栈中对应的值;注意这里的’+’也占一个位置, 用$2,这里因为有tag=1,已经把相应的信息保存到$$
中,所以不需要管它。
E:
这是一个比较特别的语句, 它把$$
赋给了一个全局量。因为exp是个开始符号,当分析结束时,这个g_root就是语法树的根。
F:
因为 加了括号的表达式与原表达式等价,所以直接把$
2赋给$$
就可以了,不需要再生成par_exp节点。
最终的函数yyparse()
yyarse()是bison生成的分析器的主函数。 调用yyarse(),如果一切顺利,那么上例中的g_root将指向一个完成的语法树。
出错处理
如果输入的字符串有语法错误,则分析器将停止分析,在退出yyparse()函数前,会调用一个yyerror(char*s)的函数,这个函数需要用户自己定义,以便能捕获一些用意义的信息,比如:语法错误出现的行号,附近的单词等。
0x01 参考
[http://pkmonster.blog.51cto.com/390780/79366]
- 【编译原理之】Bison 源文件结构原理
- 编译原理--计算器Flex+Bison实现
- 编译原理利用Flex+Bison实现简单计算器
- 编译原理—Lex和Bison实现计算器
- 编译原理-用Bison构造语法分析程序-小小计算器
- 编译原理-用Bison构造语法分析程序-二进制转换十进制
- 编译原理 - 在 Windows 平台下使用 Flex 和 Bison
- 编译原理实验-FLEX+BISON+DEV C++完美解决方案
- 编译原理之编译器的结构
- java编码原理 -- 源文件编译和执行
- 【编译原理】源文件生成目标文件的过程
- 编译原理之概述
- 编译原理之语法分析
- 编译原理之扫描器
- 编译原理之文法
- 编译原理之序言
- 编译原理之引论
- 编译原理之文法
- vb API 串口通讯(串口配置、接收、发送数据)
- 动画
- 简单购物车可加减
- BigDecimal处理大数据精度
- Linux服务器之Redis集群搭建
- 【编译原理之】Bison 源文件结构原理
- Xlistview使用方法
- Linux
- linux通用GPIO驱动
- 资产登记
- Go 常用包介绍
- 几何与物理
- 我为什么辞去北京区委书记,而去搞学术
- 超融合如何克服启动风暴