简述

Bison是在Yacc上改写并添加了大量特性后诞生的语法分析生成器,在编译前端(词法分析->语法分析->语义分析)中处在中间的位置,它可以用来生成特定的语法分析程序。

安装Bison:

apt-get install bison

没有专用于Bison的IDE,可以在VSCode安装Lex Flex Yacc Bison插件,可以让Bison语法高亮。

Bsion和Flex协同工作

在之前按照课本,用Flex生成了一个简易计算器的词法分析程序,这节书写Bison生成它的语法分析程序,然后让它们协同工作,来完成这个求解器。

Bison部分

Bison写在.y文件中,也和Flex一样由两个%%分割成了声明部分、规则部分、例程部分。下面是书写的Bison文件SimpleCalculator.y(课本程序是错的,这里改正了):

/*1 声明部分*/%{#include <stdio.h>
%}//声明记号(Token)
%token NUMBER
%token ADD SUB MUL DIV ABS
%token EOL%%/*2 规则部分,在这里写BNF规则,左部是语法符号(Symbol)*///计算列表的语法
calclist: //空,即计算列表::=\epsilon| calclist exp EOL { printf("= %d\n", $2); } //或者,计算列表::=计算列表.表达式.文件尾; //分号表示规则结束//表达式的语法
exp: term { $$ = $1; } //表达式:=项| exp ADD term { $$ = $1 + $3; } //或者,表达式::=表达式+项| exp SUB term { $$ = $1 - $3; } //或者,表达式::=表达式-项;//项的语法
term: factor { $$ = $1; } //项::=因子| term MUL factor { $$ = $1 * $3; } //或者,项::=项*因子| term DIV factor { $$ = $1 / $3; } //或者,项::=项/因子;//因子的语法
factor: NUMBER { $$ = $1; } //因子::=数字| ABS factor { $$ = $2>=0 ? $2 : -$2; } //或者,因子::=绝对值.因子;%%/*3 C代码部分*///主函数中调用解析器yyparse()
int main(int argc, char **argv) {yyparse();return 0;
}//定义解析出错时的处理
void yyerror(char *s) {fprintf(stderr, "error: %s\n", s);
}

这里在声明部分用%token声明了若干记号,这些记号实际上后面会给Flex使用,而Bison会自动为这些记号编号。

接下来在规则部分,用BNF来书写了上下文无关文法,这里用{c代码}将求解的计算写在了每条子规则的后面。这里$$表示规则左部的语法符号(Symbol),$1表示规则右部的第一个语法符号,以此类推。

最后在例程部分,Bison生成的语法分析程序要调用yyparse()进行语法分析。

Flex部分

Flex部分和之前的基本一样。下面是修改的Flex文件SimpleCalculator.l

%{//包含Bison翻译出来的头文件,文件中就定义了各个记号(Token)的编号,以及yylval记号值
//SimpleCalculator.tab.h是由SimpleCalculator.y这个Bison文件经过`bison -d`命令翻译得来的
#include "SimpleCalculator.tab.h"
%}%%"+"     { return ADD; }
"-"     { return SUB; }
"*"     { return MUL; }
"/"     { return DIV; }
"|"     { return ABS; }
[0-9]+  { yylval = atoi(yytext); return NUMBER; } //匹配到数字时,将其转为int写入记号值的变量中
\n      { return EOL; }
[ \t]   { } //忽略空白符
.       { printf("Mystery charactor %c\n", *yytext); } //其它字符是不合法的,提示错误%%//这部分例程不写了,因为Bison生成的语法分析器会调用这里Flex生成的词法分析器

去掉声明部分,是因为声明部分直接使用Bison编译出的.h文件中对记号(Token)的声明,直接就统一了。

去掉例程部分,是因为词法分析的yylex()要给Bison生成的语法分析器去调用,编译的时候编译到一起就可以了。

Makefile

创建Makefile文件:

SimpleCalculator: SimpleCalculator.l SimpleCalculator.ybison -d SimpleCalculator.yflex SimpleCalculator.lgcc -o $@ SimpleCalculator.tab.c lex.yy.c -lflclean:rm -f SimpleCalculator lex.yy.c SimpleCalculator.tab.c SimpleCalculator.tab.h

第一句是用Bison翻译SimpleCalculator.y,生成语法分析器SimpleCalculator.tab.c和其头文件SimpleCalculator.tab.h

第二句是用Flex翻译SimpleCalculator.l生成词法分析器lex.yy.c

第三句是用GCC将语法分析器、词法分析器、Flex库文件这三者编译到一起,-o指定输出的文件名,这里$@代表所有的目标文件,也就是SimpleCalculator。

编译:

make SimpleCalculator

运行

lzh@DESKTOP-HCSIG2E:/mnt/e/Compiler/flex_bison$ ./SimpleCalculator
12+34*|0-3
= 9
123-456
= -333

【Bison学习笔记】1:生成简易的语法分析程序,使Bsion和Flex协同工作相关推荐

  1. Spring学习笔记:第一个Spring Boot程序HelloWorld

    Spring学习笔记:第一个Spring Boot程序HelloWorld 一.跟着 Spring 了解技术趋势 1.看看 Spring 5.x 的改变暗示了什么 2.Spring Boot 和 Sp ...

  2. 【Flex学习笔记】1:生成简易的词法分析程序

    简述 Flex是重写Lex诞生的快速词法分析生成器,在编译前端(词法分析->语法分析->语义分析)中处在最靠前的位置,它可以用来生成特定的词法分析程序. 安装Flex: apt-get i ...

  3. 【TensorFlow-windows】学习笔记七——生成对抗网络

    前言 既然学习了变分自编码(VAE),那也必须来一波生成对抗网络(GAN). 国际惯例,参考网址: 论文: Generative Adversarial Nets PPT:Generative Adv ...

  4. 【java学习笔记day01】运行第一个程序Helloworld!

    java学习笔记day01 2.什么是软件工程师? 3.什么是软件? 4.开发软件需要计算机编程语言,计算机编程语言有很多,例如 c, c++,Java,NET,c#,php... 5.Java软件工 ...

  5. Java学习笔记(二):Java程序基础

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://mp.csdn.net/mdeditor/100619398 目录 ...

  6. Linux学习笔记(十八) -- 运行程序,出现Failed to load module canberra-gtk-module错误的解决方案

    1.错误内容 错误描述 执行程序时,提示如下错误: Failed to load module "canberra-gtk-module" 2.解决方案 (1)执行语句: sudo ...

  7. 【DOTS学习笔记】从第一个Jobs程序入门

    目录 前言 Unity Jobs System C# Jobs Systems Blittable Types VS Non-Blittable Types NativeContainers Nati ...

  8. 数据结构与算法学习笔记(python)——第一节 数组应用程序实战

    前言 本人是一个长期的数据分析爱好者,最近半年的时间的在网上学习了很多关于python.数据分析.数据挖掘以及项目管理相关的课程和知识,但是在学习的过程中,过于追求课程数量的增长,长时间关注于学习了多 ...

  9. Spring.NET学习笔记9——打造简易的依赖注入框架(练习篇) Level 100

    我们在第三篇中学习里一个简易的IoC框架.今天我们接着上次的程序,实现带参数构造函数对象的实例和属性的注入 . 我们知道可以通过反射获取类的构造函数及参数(GetConstructors方法):可以获 ...

最新文章

  1. 阿里新晋CNCF TOC委员张磊:“云原生”为什么对云计算生态充满吸引力?
  2. NSURLSession的应用
  3. 微软2020开源回顾:止不住的挨骂,停不下的贡献
  4. [cdq分治][树状数组] Jzoj P4419 hole
  5. 【转】揭开Linux的Swap之谜
  6. java中的函数指的是,函数式接口在Java中是指有且仅有一个抽象方法的接口。( )...
  7. 最全MD5 密码破解 碰撞 网站
  8. 5201314用计算机怎么打出来,计算器算出5201314抖音
  9. android通电自动开机,【图】改造导航仪,实现通电自动开机!
  10. Pycharm异常:selenium.common.exceptions.WebDriverException: Message: ‘geckodriver‘ execut运行项目无法打开火狐浏览器
  11. Python---贪心的狗熊
  12. 五步恢复XP系统“桌面清理向导”
  13. hdu 1429 胜利大逃亡(续)
  14. 基于百度AI实现的语音识别搜索文件
  15. 幸福是什么?怎么得到幸福?
  16. 信奥学习规划 信息学竞赛之路(2022.07.31)
  17. 关于思科CCIE重认证的方式,留给有需要的网络工程师
  18. rtsp h256 流 web 软解播放
  19. 最强特殊字符、表情符号、Unicdeo字符串处理
  20. Spark的宽依赖和窄依赖

热门文章

  1. 将Python代码制作成exe程序
  2. Github上开源项目readme里好看的高大上的有趣的徽章从何而来
  3. Lingo的基本用法(更新版)
  4. C++ 百钱百鸡问题
  5. MMA7361三轴加速度模块使用注意的问题
  6. 【最全的大数据面试系列】Hadoop面试题大全(一)
  7. 深入理解计算机系统(2.8)---浮点数的舍入,Java中的舍入例子以及浮点数运算(重要)
  8. 【通信协议】单总线协议详解——以DHT11为例
  9. 安装prometheus遇到:Failed to execute operation:file existed解决办法
  10. C语言中的指针以及二级指针