4

Flex & Bison 开始 - GoCodingInMyWay

 1 year ago
source link: https://www.cnblogs.com/gocodinginmyway/p/16412441.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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 个人实践的经验分享,可关注公众号!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK