Flex & Bison 开始

Flex 与 Bison 是为编译器和解释器的编程人员特别设计的工具:

  • Flex 用于词法分析(lexical analysis,或称 scanning),把输入分割成一个个有意义的词块,称为记号(token)。
  • Bison 用于语法分析(syntax analysis,或称 parsing),确定这些记号是如何彼此关联的。

例如,如下代码片段:

1alpha = beta + gamma;

词法分析把这段代码分解为这样一些记号:alpha, =, beta, +, gamma, ;。接着语法分析确定了 beta + gamma 是一个表达式,而这个表达式被赋给了 alpha

不过后来它们在其他应用领域被证明也非常有效。任何应用程序,尤其文本处理,只要在其输入中寻找特定的模式,或者它使用命令语言作为输入,都适合使用 Flex 与 Bison。

例如,SQL 分析:

在编译器结构中,词法分析器、语法分析器是编译器前端的主要组成部分。大多数编译器组织成三个主要的阶段:前端、优化器和后端。前端专注于理解源语言程序,将其转换为某种中间表示(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 安装:

1# Ubuntu 20 2$ sudo apt install flex bison -y 3 4$ flex -V 5flex 2.6.4 6$ bison -V 7bison (GNU Bison) 3.5.1

范例

范例请见 https://github.com/ikuokuo/start-ai-compiler/tree/main/books/flex_bison ,都来自结语给出的 Flex & Bison 一书。

范例指导了我们如何使用 Flex & Bison 开发一个计算器,并能支持变量、过程、循环和条件表达式,有内置函数,也支持用户自定义函数。

如下编译所有范例:

1cd books/flex_bison/ 2 3# 编译 release 4make 5# 编译 debug 6make debug 7 8# 清理 9make clean

范例程序会输出进 _build 目录,如下执行:

1$ ./_build/linux-x86_64/release/1-5_calc/bin/1-5_calc 2> (1+2)*3 + 4/2 3= 11 4 5$ ./_build/linux-x86_64/release/3-5_calc/bin/3-5_calc 6> let sq(n)=e=1; while |((t=n/e)-e)>.001 do e=avg(e,t);; 7Defined sq 8> let avg(a,b)=(a+b)/2; 9Defined avg 10> sq(10) 11= 3.162 12> sqrt(10) 13= 3.162 14> sq(10)-sqrt(10) 15= 0.000178

如果只编译某一范例:

1cd ch01/1-1_wc/ 2 3# 编译 release 4make -j8 5# 编译 debug 6make -j8 args="debug" 7 8# 清理 9make clean

程序

Flex 与 Bison 程序都是由三部分构成:定义部分、规则部分和用户子例程。

1... definition section ... 2%% 3... rules section ... 4%% 5... user subroutines section ...

Flex 规则部分基于正则表达式,Bison 则基于 BNF (Backus-Naur Form) 文法。详细用法,请依照结语给出的 Flex & Bison 一书,及范例。

这里不做过多阐述,本文旨在让大家了解有 Flex 与 Bison 这样工具,以及它们能帮助我们完成什么样的工作。

结语

Flex 与 Bison 是词法分析器(Scanner)与语法分析器(Parser)的自动生成工具,应用了形式语言理论的结果。这些工具同样可用于文本搜索、网站过滤、文字处理和命令行语言解释器。

本文内容主要来源于以下书籍:

GoCoding 个人实践的经验分享,可关注公众号!

点赞
收藏

评论区

加载中...

相关推荐

Vue进阶(幺柒幺):前端用户体验提升(五)Flex实现弹性布局

需求背景在实现组件拖拽设计过程中,发现组件样式中设置了display:flex属性信息,导致组件生成后无法实现拖拽效果,网上查阅资料后发现Flex布局大有天地。Flex来源

想学会flex布局,我强烈推荐你来看看这篇文章!!

原文链接:为什么要使用flex布局?flex布局是目前比较流行的一种布局,因为它十分简单灵活,区区简单几行代码就可以实现各种页面的的布局,以前我在学习页面布局的时候我深受其float、display、position这些属性的困扰。使用flex属性就可以写

java做web项目比较多

WEB就是轻量级;如果要炫,FLEX或即将普及的html5.0都能做到像C/S那样。java做web项目比较多;如果是桌面程序,还是走C/S比较成熟。如果是B/S架构的,后台还是JAVA,前台可以用JSPJSCSS渲染;也可以把前台换成FLEX交互,效果也是很好的。1packageCom.MySwing;2impo

【Flutter实战】线性布局(Row、Column)

4.2线性布局(Row和Column)所谓线性布局,即指沿水平或垂直方向排布子组件。Flutter中通过Row和Column来实现线性布局,类似于Android中的LinearLayout控件。Row和Column都继承自Flex,我们将在弹性布局一节中详细介绍Flex。主轴和纵轴对于线性布局,有主轴和纵轴之分,如果

OpenCASCADE Expression Interpreter by Flex & Bison

OpenCASCADEExpressionInterpreterbyFlex&Bisoneryar@163.com(https://www.oschina.net/action/GoToLink?urlmailto%3Aeryar%40163.com)Abstract.OpenCASCADEprovidedat

PHP扩展开发

首先需要确定系统中安装了gcc编译器,合适版本的bison等构建一个基本的扩展骨架在PHP扩展开发时,使用ext_skel完成扩展的结构骨架创建。$./ext_skel./ext_skelextnamemoduleprotofilestubsfilexmlfile