您的位置:首页 > 编程语言 > C语言/C++

编译原理实验-FLEX+BISON+DEV C++完美解决方案

2017-11-12 02:07 826 查看

一点介绍

flex,前身是lex,lex是1975年由Mike Lesk和当时尚在AT&T实习的Eric Schmidt共同完成的基于UNIX环境的词法分析器的生成工具。这个lex很有名气,但是无奈效率太低加上有bug,让人用的很不爽。后来伯克利实验室的Vern Paxson用C重新写了lex,并命名为flex(Fast Lexical Analyzer Generator)。

Bison,bison的前身是传说中的yacc,yacc是由贝尔实验室的S.C.Johnson基于Knuth大神的LR分析技术,于1975~1978年写成。1987年 UC Berkeley 的Bob Corbett在BSD下重写了yacc。在后来GNU project接管了项目,添加了很多特性,形成了今天的GNU Bison语法分析器生成工具。

这里提供的bison和flex的程序长这个样子:



实验噱头

看着很多人拿到老师的文档按部就班的做了,可是……很迷

下面给大家展示一下爽的一笔的实验过程:

第一步

先看下老师的指示和相应的文件:





文件呢,这里有前言说的flex和bison工具还有现有的tiny编译器的一些工具



第二步

进行flex生成词法分析器操作:



将flex放到tiny.l旁边,命令行执行,生成lex.yy.c



第三步

进行bison生成语法分析器操作:



将bison放到tiny.y旁边,命令行执行,生成tiny.tab.h&tiny.tab.c



第四步

构建工程,将所需要的所有文件放到一个文件夹中(可以忽略,个人强迫症)【注意,如果选了.h就一定要带上.c,老师的文件有缺漏】



构建工程【easy不说,最好是c项目+Console Application】—–记住flex生成的文件也要放进来,图中忘记截图的



之后!

打开global.h

将位于第30行附近的#include “y.tab.h”换成#include “tiny.tab.h”

进行第一次编译!

编译之后会是这样的错误:



这是因为我们没有拷贝词法语法分析包(因为我们使用的flex和bison生成的,而不是tiny编译器自己的)

这里只需要将analyze的开关关上即可。

/* set NO_PARSE to TRUE to get a scanner-only compiler */
#define NO_PARSE FALSE
/* set NO_ANALYZE to TRUE to get a parser-only compiler */
#define NO_ANALYZE TRUE


进行第二次编译(第一次出现很多warning和错误,再编译一次让warning消停会)

这个时候会有这样的错误



还是不要方,这里的问题是yylex的重复定义,你们还记得书上是怎么要求yacc的吗,最后面一定要有yylex,但是我们的这些个代码中已经在词法分析器的时候就已经设计好可yylex,解决方法很多,最简单粗暴的就是将tiny.tab.c中的yylex(最下面)给删了:



这个时候进行第三次编译,错误将会变成:



这里是一些类型强制转化的问题,和IDE有关,DEV C++貌似都有这个问题codeblocks等没有,所以大家可以开心进行最后这个讲得通的修改吧~

改完之后进行第四次编译出现这个爽歪歪的错误:



这里就开始解释不通了,这错误我们读一下,大概是有一些函数没有成功的声明,由于是多文件的编程,我们看到tiny.tab.c文件中去:

#include "globals.h"
#include "util.h"
#include "scan.h"
#include "parse.h"


引入的是这几个文件,发现出错的函数都是在这里

#include "util.h"


我们神奇的将这个.h改成.c

回到main函数,编译第五遍:

还是错的,但是错变成这样了:



说没有define那我们……就再define一下吧

#include "globals.h"
#include "util.h"
#define ENDFILE 0
/* Procedure printToken prints a token
* and its lexeme to the listing file
*/
void printToken( TokenType token, const char* tokenString )


再一次的编译:



我们发现这个yywrap的可恶,不过之前的实验是自己做的同学理论上也是会遇到这个问题的,直接去yy.lex.c文件中找到注释中yywrap的位置,声明一下就好了,让这个函数有返回值就好!

#define yywrap() 1
/* Flag which is used to allow yywrap()'s to do buffer switches
* instead of setting up a fresh yyin.  A bit of a hack ...
*/


大概是222行

这时候再一次的编译:



我还能说什么……

就这样……

结束了……

不过,如果幸运,你的电脑还会遇到这个问题:



这个时候……转战codeblocks吧

第五步

下面我们来运行一下!~



忘了!

要到main中打开这些开关

/* allocate and set tracing flags */
int EchoSource = TRUE;
int TraceScan = TRUE;
int TraceParse = FALSE;
int TraceAnalyze = FALSE;
int TraceCode = FALSE;


编译运行,然后,命令行执行生成的exe,和sample



大功告成

至于解释那个.h换.c

论坛里有人说是因为……重名定义了,然后如果直接引用实现,表示声明这个引用才是唯一引用。

最后我们看下原理:

就不详细说了,等我下次更新编译原理板块再说吧

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: