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

一点介绍

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
论坛里有人说是因为……重名定义了,然后如果直接引用实现,表示声明这个引用才是唯一引用。
最后我们看下原理:
就不详细说了,等我下次更新编译原理板块再说吧
这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值