【Bison学习笔记】1:生成简易的语法分析程序,使Bsion和Flex协同工作
简述
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协同工作相关推荐
- Spring学习笔记:第一个Spring Boot程序HelloWorld
Spring学习笔记:第一个Spring Boot程序HelloWorld 一.跟着 Spring 了解技术趋势 1.看看 Spring 5.x 的改变暗示了什么 2.Spring Boot 和 Sp ...
- 【Flex学习笔记】1:生成简易的词法分析程序
简述 Flex是重写Lex诞生的快速词法分析生成器,在编译前端(词法分析->语法分析->语义分析)中处在最靠前的位置,它可以用来生成特定的词法分析程序. 安装Flex: apt-get i ...
- 【TensorFlow-windows】学习笔记七——生成对抗网络
前言 既然学习了变分自编码(VAE),那也必须来一波生成对抗网络(GAN). 国际惯例,参考网址: 论文: Generative Adversarial Nets PPT:Generative Adv ...
- 【java学习笔记day01】运行第一个程序Helloworld!
java学习笔记day01 2.什么是软件工程师? 3.什么是软件? 4.开发软件需要计算机编程语言,计算机编程语言有很多,例如 c, c++,Java,NET,c#,php... 5.Java软件工 ...
- Java学习笔记(二):Java程序基础
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://mp.csdn.net/mdeditor/100619398 目录 ...
- Linux学习笔记(十八) -- 运行程序,出现Failed to load module canberra-gtk-module错误的解决方案
1.错误内容 错误描述 执行程序时,提示如下错误: Failed to load module "canberra-gtk-module" 2.解决方案 (1)执行语句: sudo ...
- 【DOTS学习笔记】从第一个Jobs程序入门
目录 前言 Unity Jobs System C# Jobs Systems Blittable Types VS Non-Blittable Types NativeContainers Nati ...
- 数据结构与算法学习笔记(python)——第一节 数组应用程序实战
前言 本人是一个长期的数据分析爱好者,最近半年的时间的在网上学习了很多关于python.数据分析.数据挖掘以及项目管理相关的课程和知识,但是在学习的过程中,过于追求课程数量的增长,长时间关注于学习了多 ...
- Spring.NET学习笔记9——打造简易的依赖注入框架(练习篇) Level 100
我们在第三篇中学习里一个简易的IoC框架.今天我们接着上次的程序,实现带参数构造函数对象的实例和属性的注入 . 我们知道可以通过反射获取类的构造函数及参数(GetConstructors方法):可以获 ...
最新文章
- 阿里新晋CNCF TOC委员张磊:“云原生”为什么对云计算生态充满吸引力?
- NSURLSession的应用
- 微软2020开源回顾:止不住的挨骂,停不下的贡献
- [cdq分治][树状数组] Jzoj P4419 hole
- 【转】揭开Linux的Swap之谜
- java中的函数指的是,函数式接口在Java中是指有且仅有一个抽象方法的接口。( )...
- 最全MD5 密码破解 碰撞 网站
- 5201314用计算机怎么打出来,计算器算出5201314抖音
- android通电自动开机,【图】改造导航仪,实现通电自动开机!
- Pycharm异常:selenium.common.exceptions.WebDriverException: Message: ‘geckodriver‘ execut运行项目无法打开火狐浏览器
- Python---贪心的狗熊
- 五步恢复XP系统“桌面清理向导”
- hdu 1429	胜利大逃亡(续)
- 基于百度AI实现的语音识别搜索文件
- 幸福是什么?怎么得到幸福?
- 信奥学习规划 信息学竞赛之路(2022.07.31)
- 关于思科CCIE重认证的方式,留给有需要的网络工程师
- rtsp h256 流 web 软解播放
- 最强特殊字符、表情符号、Unicdeo字符串处理
- Spark的宽依赖和窄依赖