Flex & Bison 开始
Flex 与 Bison 是为编译器和解释器的编程人员特别设计的工具:
- Flex 用于词法分析(lexical analysis,或称 scanning),把输入分割成一个个有意义的词块,称为记号(token)。
- Bison 用于语法分析(syntax analysis,或称 parsing),确定这些记号是如何彼此关联的。
例如,如下代码片段:
alpha = beta + gamma;
词法分析把这段代码分解为这样一些记号:alpha, =, beta, +, gamma, ;。接着语法分析确定了 beta + gamma 是一个表达式,而这个表达式被赋给了 alpha。
不过后来它们在其他应用领域被证明也非常有效。任何应用程序,尤其文本处理,只要在其输入中寻找特定的模式,或者它使用命令语言作为输入,都适合使用 Flex 与 Bison。
例如,SQL 分析:
- MySQL: C++ 词法分析, Bison 语法分析
- PostgreSQL: Flex 词法分析, Bison 语法分析
在编译器结构中,词法分析器、语法分析器是编译器前端的主要组成部分。大多数编译器组织成三个主要的阶段:前端、优化器和后端。前端专注于理解源语言程序,将其转换为某种中间表示(IR)。而 Flex 与 Bison 就是给编译器前端设计出的工具。
起源
bison 来源于 yacc,一个由 Stephen C. Johnson 于 1975 年到 1978 年期间在贝尔实验室完成的语法分析器生成程序。正如它的名字(yacc 是 yet another compiler compiler 的缩写)所暗示的那样,那时很多人都在编写语法分析器生成程序。Johnson 的工具基于 D. E. Knuth 所研究的语法分析理论(因此 yacc 十分可靠)和方便的输入语法。这使得 yacc 在 Unix 用户中非常流行,尽管当时 Unix 所遵循的受限版权使它只能够被使用在学术界和贝尔系统里。大约在 1985 年,Bob Corbett,一个加州伯克利大学的研究生,使用改进的内部算法再次实现了 yacc 并演变成为伯克利 yacc。由于这个版本比贝尔实验室的 yacc 更快并且使用了灵活的伯克利许可证,它很快成为最流行的 yacc。来自自由软件基金会(Free Software Foundation)的 Richard Stallman 改写了 Corbett 的版本并把它用于 GNU 项目中,在那里,它被添加了大量的新特性并演化成为当前的 bison。bison 现在作为 FSF 的一个项目而被维护,且它基于 GNU 公共许可证进行发布。
在 1975 年,Mike Lesk 和暑期实习生 Eric Schmidt 编写了 lex,一个词法分析器生成程序,大部分编程工作由 Schmidt 完成。他们发现 lex 既可以作为一个独立的工具,也可以作为 Johnson 的 yacc 的协同程序。lex 因此变得十分流行,尽管它运行起来有一点慢并且有很多错误。(不过 Schmidt 后来在计算机行业里拥有一份非常成功的事业,他现在,2009年,是 Google 的 CEO。2010 年 CEO 移交了,继续担任 Google 董事长。)
大概在 1987 年,Lawrence Berkeley 实验室的 Vern Paxson 把一种用 ratfor(当时流行的一种扩展的 Fortran 语言)写成的 lex 版本改写为 C 语言的,被称为 flex,意思是“快速词法分析器生成程序”(Fast Lexical Analyzer Generator)。由于它比 AT&T 的 lex 更快速和可靠,并且就像伯克利的 yacc 那样基于伯克利许可证,它最终也超越了原来的 lex。flex 现在是 SourceForge 的一个项目,依然基于伯克利许可证。
安装
大多数 Linux 和 BSD 系统自带 flex 和 bison 作为系统的基础部分。如果你的系统没有包含它们,安装它们也很容易。
例如在 Ubuntu/Debian 系统,可以直接 apt 安装:
# Ubuntu 20
$ sudo apt install flex bison -y
$ flex -V
flex 2.6.4
$ bison -V
bison (GNU Bison) 3.5.1
范例
范例请见 https://github.com/ikuokuo/start-ai-compiler/tree/main/books/flex_bison ,都来自结语给出的 Flex & Bison 一书。
范例指导了我们如何使用 Flex & Bison 开发一个计算器,并能支持变量、过程、循环和条件表达式,有内置函数,也支持用户自定义函数。
如下编译所有范例:
cd books/flex_bison/
# 编译 release
make
# 编译 debug
make debug
# 清理
make clean
范例程序会输出进 _build 目录,如下执行:
$ ./_build/linux-x86_64/release/1-5_calc/bin/1-5_calc
> (1+2)*3 + 4/2
= 11
$ ./_build/linux-x86_64/release/3-5_calc/bin/3-5_calc
> let sq(n)=e=1; while |((t=n/e)-e)>.001 do e=avg(e,t);;
Defined sq
> let avg(a,b)=(a+b)/2;
Defined avg
> sq(10)
= 3.162
> sqrt(10)
= 3.162
> sq(10)-sqrt(10)
= 0.000178
如果只编译某一范例:
cd ch01/1-1_wc/
# 编译 release
make -j8
# 编译 debug
make -j8 args="debug"
# 清理
make clean
程序
Flex 与 Bison 程序都是由三部分构成:定义部分、规则部分和用户子例程。
... definition section ...
%%
... rules section ...
%%
... user subroutines section ...
Flex 规则部分基于正则表达式,Bison 则基于 BNF (Backus-Naur Form) 文法。详细用法,请依照结语给出的 Flex & Bison 一书,及范例。
这里不做过多阐述,本文旨在让大家了解有 Flex 与 Bison 这样工具,以及它们能帮助我们完成什么样的工作。
结语
Flex 与 Bison 是词法分析器(Scanner)与语法分析器(Parser)的自动生成工具,应用了形式语言理论的结果。这些工具同样可用于文本搜索、网站过滤、文字处理和命令行语言解释器。
本文内容主要来源于以下书籍:
GoCoding 个人实践的经验分享,可关注公众号!
Flex & Bison 开始的更多相关文章
- OpenCASCADE Expression Interpreter by Flex & Bison
OpenCASCADE Expression Interpreter by Flex & Bison eryar@163.com Abstract. OpenCASCADE provide d ...
- 编译器工具 Flex Bison for Windows 简单入门例子
最近从事一个系统仿真软件的开发,里面定义了自己的描述性语言MSL, MSL语言经FlexBison转换成C语言,然后用C编译器来编译并计算仿真. 现在领域驱动开发比较热门,有机会定义自己的语言对程序员 ...
- Windows下 flex + bison 小例子
.下载flex和bison,网址是http://gnuwin32.sourceforge.net/packages/flex.htm 和http://gnuwin32.sourceforge.net/ ...
- 应注意的Flex&Bison潜规则
1.Flex的二义性模式 语法分析器匹配输入时匹配尽可能多的字符串 如果两个模式都可以匹配的话,匹配在程序中更早出的模式. 针对这一点的理解,在语法分析文件当中,token的识别,应从特殊到一般的过程 ...
- flex&bison 1
. {ECHO;}-----单独的flex使用中有效 . { yyerror();}--------flex和bison交叉使用,即使不调用yyerror函数,也会报错的 error: syn ...
- flex/bison 计算器
flex %{ #include <stdio.h> #include "mycalc.tab.h" ;} %} %% "+" return ADD ...
- [flex & bison]编译器杂谈
flex与bison是编译器设计工具.这里的编译器为广义,其中包括一般的编译器.脚本解析器等,需要进行语言结构解析来得出意义的程序. 当我们需要用一个语言来设计一款编译器时,需要考虑太多设计重心外的东 ...
- lex yacc flex bison
lex与yacc是两个在Unix下的分别作词法分析和语法分析的工具, Linux对应flex与bison. windows:http://sourceforge.net/projects/unxuti ...
- flex bison
https://www.gnu.org/software/bison/manual/bison.html https://blog.csdn.net/sirouni2003/article/detai ...
随机推荐
- java并发问题总结
1.java中产生并发问题的主要原因有哪三个? 原子性.可见性和有序性 2.什么是java内存模型? java虚拟机规范中用来屏蔽掉各种硬件和操作系统内存访问差异,java内存模型的主要目标是定义程序 ...
- Zookeeper启动问题记录——ZooKeeper audit is enabled.
问题原因是Zookeeper的日志服务默认关闭,在zoo.cfg文件中添加 audit.enable=true 保存后重启服务就能够正常启动. 另外,这个只影响Zookeeper的日志记录,不影响其他 ...
- gin框架使用【2.RESTFUL API使用】
package mainimport ( "github.com/gin-gonic/gin")func main() { router := gin.Default() rout ...
- MQ系列:消息中间件执行原理
1 关于消息中间件 1.1 什么是消息中间件? 消息中间件是指在分布式系统中完成消息的发送和接收的基础软件. 消息中间件也可以称消息队列(Message Queue / MQ),用高效可靠的消息传递机 ...
- 数据传输POST心法分享,做前端的你还解决不了这个bug?
背景 随时随地给大家提供技术支持的葡萄又来了.这次的事情是这样的,提供demo属于是常规操作,但是前两天客户突然反馈压缩传输模块抛出异常,具体情况是压缩内容传输到服务端后无法解压. 由于代码没有发生任 ...
- python 处理网络帧时,CRC算法中整数按位取反运算(~)得到负数的规避方法
计算机中的符号数有三种表示方法,即原码.反码和补码.三种表示方法均有符号位和数值位两部分,符号位都是用0表示"正",用1表示"负". 正数的原码,反码,补码都是 ...
- django orm 更新数据时间不自动更新问题
gmt_create自动添加auto_now_add:gmt_modify自动更新auto_now class CommonInfo(models.Model): """ ...
- 21天学通Python PDF完整版
有需要的点击这里自取 内容简介 · · · · · · <21天学通Python>全面.系统.深入地讲解了Python编程基础语法与高级应用.在讲解过程中,通过大量实际操作的实例将Pyt ...
- Java 线程安全 与 锁
Java 线程安全 与 锁 多线程内存模型 线程私有栈内存 每个线程 私有的内存区域 进程公有堆内存 同一个进程 共有的内存区域 为什么会有线程安全问题? 多个线程同时具有对同一资源的操作权限,又发生 ...
- 团队Beta5
队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 **过去两天完成了哪些任务 ** 文字/口头描述 学习 展示GitHub当日代码/文档签入记录 无 接下来的计划 无 **还剩下哪些任务 ...