转载自:https://zhuanlan.zhihu.com/p/89479111

Bison是一种通用解析器生成器,它将带注释的上下文无关文法转换为使用LALR(1)解析器表的确定性LR或广义LR(GLR)解析器 。作为一项实验性功能,Bison还可以生成IELR(1)或规范的LR(1)解析器表。一旦您精通Bison,就可以使用它来开发各种语言解析器,从用于简单台式计算器的语言解析器到复杂的编程语言。 Bison与Yacc向上兼容:所有正确编写的Yacc语法都应与Bison一起使用,而无需进行任何更改。熟悉Yacc的任何人都应该可以轻松使用Bison。您需要精通C或C ++编程才能使用Bison。还支持将Java作为实验功能。

Bison由三部分组成

  • 定义部分
  • %%
  • 规则部分
  • %%
  • 用户附加的C语言部分

定义部分

代码部分

%{ ... %},或%code { ... }的内容都是C代码,并将代码照搬到生成的C文件中,可以定义一些函数声明,结构体,类型等,还可以重定义一些Bison的宏,从而改变程序的规则。

声明%name

与flex %option类似,提供一定机制来控制bison默认规则。

  1. %pure-parser,指定希望解析器是可重入的。
  2. %expect 0,希望冲突数量为0
  3. %name-prefix="base_yy",代表生成的函数和变量名从yy改成base_yy
  4. %locations,生成处理位置的代码。 语法使用特殊的'@n'标记后便会启用此模式,但是如果您的语法不使用它,则使用'%locations'可以获取更准确的语法错误消息。
  5. %parse-param {core_yyscan_t yyscanner},声明一个或多个参数声明是其他yyparse参数。 在声明函数或原型时使用参数声明。 参数声明中的最后一个标识符必须是参数名称。
  6. %lex-param {core_yyscan_t yyscanner},指定参数声明是其他yylex参数声明。 您可以传递一个或多个这样的声明,等效于重复%lex-param。
  7. %union,嵌入动作返回值类型,一般为非终结符的类型定义。如:
%union
{core_YYSTYPE            core_yystype;/* these fields must match core_YYSTYPE: */int                                     ival;char                            *str;const char                      *keyword;char                            chr;bool                            boolean;JoinType                        jtype;DropBehavior            dbehavior;OnCommitAction          oncommit;………………InsertStmt                      *istmt;VariableSetStmt         *vsetstmt;PartitionElem           *partelem;PartitionSpec           *partspec;PartitionBoundSpec      *partboundspec;RoleSpec                        *rolespec;
}

8. %type<>,Bison构造%type用于声明非终结符。 以前我们以前没有使用%type,因为非终结符通常由定义它们的规则隐式声明。 但是必须显式声明exp,以便我们可以指定其值类型。

9. %token<>,token类型定义。在PostgreSQL中为关键字定义。

10. 优先级定义,为了避免过多的语法冲突,在这里定义一些语法优先级,从上到下优先级依次递增

%nonassoc       SET                             /* see relation_expr_opt_alias */
%left           UNION EXCEPT
%left           INTERSECT
%left           OR
%left           AND
%right          NOT
%nonassoc       IS ISNULL NOTNULL       /* IS sets precedence for IS NULL, etc */
%nonassoc       '<' '>' '=' LESS_EQUALS GREATER_EQUALS NOT_EQUALS
%nonassoc       BETWEEN IN_P LIKE ILIKE SIMILAR NOT_LA
%nonassoc       ESCAPE                  /* ESCAPE must be just above LIKE/ILIKE/SIMILAR */
%left           POSTFIXOP               /* dummy for postfix Op rules */

规则部分

规则分为规则/行为行和C代码行。

规则/行为

bison语法是由一系列的规则组成。每个规则由非终结符开始,然后是“:”和可能为空的符号、文字记号和动作的列表。 例如:

simple_select:SELECT opt_all_clause opt_target_listinto_clause from_clause where_clausegroup_clause having_clause window_clause{SelectStmt *n = makeNode(SelectStmt);n->targetList = $3;n->intoClause = $4;n->fromClause = $5;n->whereClause = $6;n->groupClause = $7;n->havingClause = $8;n->windowClause = $9;$$ = (Node *)n;}|………………;
  1. “:”左边为非终结符。
  2. “:”右边为规则,由一系列的终结符或非终结符构成。
  3. “$$”,表示simple_select。
  4. “$number”,表示“:”右边符号,数字为几,则表示第几个符号。
  5. “|”,表示或,“simple_select”其他规则。

代码段

此段落,postgresql, 定义了一些在规则段中使用的工具函数。

移进/归约

移进:bison语法分析器通过查找能够匹配当前token的规则来运作。当bison处理一个语法分析器时,他创建一组状态,每个状态都反应出一个或者多个部分分析过的规则中可能的位置。当语法分析器读取记号时,每当它读到的记号无法结束一条规则时,它将把这个记号压入一个内部堆栈,然后切换到一个新状态,这个状态能够反映出刚刚读取的记号。这种行为被称为移进。

归约:当它发现压入的所有语法符号已经可一以组成规则的右部时,他将把右部符号全部从堆栈中弹出,然后把左部语法符号压入堆栈。这种行为被称为归约。因为它通常消减了堆栈中一定数量的符号。每当bison归约一条规则时,它会执行该规则关联的用户代码。

二义性

只要是对于语言的解析,往往都会伴随二义性的问题。bison把语法翻译为成语法分析器时有可能会报告冲突。一些情况下,语法确实有歧义;也就是说。对于一个输入的字符串,存在两种可能的语法分析器,而bison无法处理这种情况。(当然也有可能是bison对于某些规则不支持的缘故)。 bison的二义性冲突分为移进/归约冲突和归约/归约冲突。 移进/归约冲突:

%%
e:      'X'| e '+' e;

在这里,当我们输入X+X+X时,存在两种可能,(X+X)+X和X+(X+X)。移进会按照第二条规则进行,而归约会按照第一条规则进行,这时就会存在矛盾。 移进/归约冲突:

%%
prog: proga | progb ;proga:      'X';
progb       'X';

移进不会产生歧义,但当归约时,X既是proga又是progb,这就会造成归约/归约冲突。

工作流程

图片来自于同事,bret.shao

flex&bison协作方式

官方文档

https://www.gnu.org/software/bison/

Bison介绍[转]相关推荐

  1. 使用Flex Bison 和LLVM编写自己的编译器[zz]

    1.介绍 我总是对编译器和语言非常感兴趣,但是兴趣并不会让你走的更远.大量的编译器的设计概念可以搞的任何一个程序员迷失在这些概念之中.不用说,我也曾 今尝试过,但是并没有取得太大的成功,我以前的尝试都 ...

  2. bison版本问题导致编译报错:‘parse.error‘ is not used

    bison版本问题导致编译报错:'parse.error' is not used 'parse.error' 问题定位和修正 问题发现 问题调查与定位 更新bison/flex版本 问题修正 一些参 ...

  3. 3.01 bison基本概念及语法介绍

    由于本节篇幅较大,这里先将目录列出来以便于读者查阅感兴趣的内容(__) 嘻嘻--: 移进/规约分析 bison的两种语法分析方法 bison的基本规则 %start声明 %union声明 %type声 ...

  4. 在java 里kv 是什么_consul kv使用介绍

    一行python代码实现树结构 树结构是一种抽象数据类型,在计算机科学领域有着非常广泛的应用.一颗树可以简单的表示为根, 左子树, 右子树. 而左子树和右子树又可以有自己的子树.这似乎是一种比较复杂的 ...

  5. 启明云端分享|ESP32-S3开发环境搭建,这里我们会介绍两个比较常用的开发环境搭建:WINDOWS\LINUX

    ESP32-S3开发环境搭建,这里我们会介绍两个比较常用的开发环境搭建:WINDOWS\LINUX 详细安装步骤概览 注:目前master分支,支持S3. 官方开发文档:包含多种平台 https:// ...

  6. 数据库概述(了解数据库,当前数据库介绍,mysql数据库介绍,安装mysql数据库)

    文章目录 数据库概述 什么是数据库(数据,表,数据库) 数据库有什么作用? 关系数据库详解 非关系数据库详解 数据库系统发展史 数据库管理系统(DBMS) 当今主流数据库介绍 MySQL数据库 MyS ...

  7. Android Framework中的Application Framework层介绍

    Android的四层架构相比大家都很清楚,老生常谈的说一下分别为: Linux2.6内核层,核心库层,应用框架层,应用层.我今天重点介绍一下应用框架层Framework. Framework层为我们开 ...

  8. work节点使用外部包_AFLSmart工具简单分析及使用介绍

    AFLSmart 是一个在 AFL 基础上,结合了 Peach 的结构化输入组件的灰盒 smart fuzz 工具. AFLSmart 链接:https://github.com/aflsmart/a ...

  9. GoLang语言多版本管理工具--GVM入门介绍

    GoLang语言多版本管理工具--GVM入门介绍 GVM 由Josh Bussdieker(jbuss,jaja,jbussdieker)在Moovweb工作期间 GVM提供了一个管理Go版本的界面. ...

最新文章

  1. Android 正则表达式实例
  2. 个人知识管理专著《你的知识需要管理》出版
  3. linux查看cpu监控日志,Linux:日志,cpu,memory,mount,load等系统信息查看
  4. 手机版的python-python手机版
  5. 【WEB HTTP】缓存
  6. 计算机能自动写程序,忘掉编程语言吧,微软想让计算机自动生成程序 | 一周 AI 新闻...
  7. 3.Python配套习题
  8. 专为中国车主开发,特斯拉计划今年推出数据平台
  9. java.lang.IllegalArgumentException: Request header is too large的解决方法
  10. kafka 重新分配节点_你可能需要的Kafka面试题与部分答案整理
  11. Android实现思维导图功能,Android实现思维导图
  12. 如何在网页浏览器中缩放网页?
  13. C++天天练——两点间的距离
  14. 第一次写前后端分离项目的经验总结
  15. (分布式网络)基于残差网络的多光谱全色图像分布式融合框架
  16. yii2自动更新时间
  17. 漫话:如何给女朋友解释什么是语法糖?
  18. 淘系自研前端研发工具 AppWorks 正式发布
  19. 计算机中汉字的顺序有什么排列,汉字演变过程的时间排序是什么?
  20. 深度相机介绍(TOF、RGB双目、结构光参数对比)

热门文章

  1. 在新窗口中打开 base64 格式的图片
  2. IPC连接错误号分析
  3. 智能建筑中电力监控系统的应用与产品选型
  4. 注意力机制(Attention)最新综述论文及相关源码
  5. win10如何添加开机自己启动软件
  6. C++Builder Tchart与TDBchart
  7. 字符串最大跨距 (c++)
  8. 录音转文字高效又简单的方法以及过程
  9. python去掉空格常用方式
  10. python 去掉首尾空格