基于FlexBison的高级解释器设计及实现.docx
- 文档编号:27538390
- 上传时间:2023-07-02
- 格式:DOCX
- 页数:17
- 大小:382.95KB
基于FlexBison的高级解释器设计及实现.docx
《基于FlexBison的高级解释器设计及实现.docx》由会员分享,可在线阅读,更多相关《基于FlexBison的高级解释器设计及实现.docx(17页珍藏版)》请在冰豆网上搜索。
基于FlexBison的高级解释器设计及实现
课程设计3基于Flex/Bison的高级解释器设计及实现
3.1需求分析
3.1.1问题定义
1.使用flex和bison开发了一个具有全部功能的桌面计算器,能够支持变量,过程,循环和条件表达式,使它成为一个虽然短小但是具有现实意义的编译器。
2.重点学习抽象语法树的用法,它具有强大而简单的数据结构来表示分析。
3.1.2功能描述
1.计算器具体需要实现的功能:
a)变量命名;
b)实现赋值功能;
c)实现比较表达式(大于、小于、等于等等)
d)实现if/then/else和do/while的流程控制;
e)用户可以自定义函数;
f)简单的错误恢复机制。
2.编写Flex/Bison源文件,实现C语言的语法分析功能,最后上机调试。
3.要求编写一个测试程序:
首先自定义两个函数sq和avg,sq函数使用Newton方法来迭代计算平方根;avg函数计算两个数值的平均值。
利用定义好的函数进行计算,得到计算结果并显示出来。
4.根据习题1的要求,修改fb3-2相关代码;
实现实现以下自定义函数,并保存为fb3-3。
函数示例:
letsq(n){e=1;while(|((t=n/e)-e)>.001)do{e=avg(e,t);}}
letavg(a,b){(a+b)/2;}
letmax(a,b){if(a>b)thena;elseb;}
letmax3(a,b,c){if(a>b)then{if(a>c)thena;elsec;}
else{if(b>c)thenb;elsec;}}
3.1.3开发环境及工具介绍
1、Window环境下载VisualStudio之后,利用其命令提示窗口进行操作。
下载并安装Flex。
2、vs2010的编译器cl.exe。
3、flex:
词法分析器
Flex是用来生成程序的工具,他们所生成的程序能够处理结构化输入,最初的Flex是用来生成编译器的,但是后来他们被证明在其他领域也非常有效。
Flex是一个SourceForge项目。
其依赖于GNUm4宏处理器。
Linux和BSD都应该有m4,对于Windos用户来说,Flex被包含在CygeinLinux模拟环境中。
什么是FLEX?
它是一个自动化工具,可以按照定义好的规则自动生成一个C函数yylex(),也成为扫描器(Scanner)。
这个C函数把文本串作为输入,按照定义好的规则分析文本串中的字符,找到符合规则的一些字符序列后,就执行在规则中定义好的动作(Action)。
例如在规则中可以这样定义:
如果遇到一个换行字符\n,那么就把行计数器的值加一。
Flex文件就是一个文本文件,内容包括定义好的一系列词法规则。
4、bison:
语法分析器
GNUbison是属于GNU项目的一个语法分析器生成器。
Bison把一个关于“向前查看从左到右最右”(LALR)上下文无关文法的描述转化成可以分析该文法的C或C++程序。
它也可以为二义文法生成“通用的从左到右最右”(GLR)语法分析器。
Bison是一种通用目的的分析器生成器。
它将LALR
(1)上下文无关文法的描述转化成分析该文法的C程序。
一旦你精通Bison,你可以用它生成从简单的桌面计算器到复杂的程序设计语言等等许多语言的分析器。
Bison基本上与Yacc兼容,并且在Yacc之上进行了改进。
它经常和Flex(一个自动的词法分析器生成器)一起使用。
此软件的源代码是可自由获得的,在GPL下发布。
3.2系统概要设计
3.2.1系统体系结构
本实验计算器系统是基于抽象语法树的改进的计算器,在fb3-3.h的文件中实现声明部分,在fb3-3.l文件中实现计算器对应的词法分析,在fb3-3.y文件实现计算器的语法语义分析部分,在fb3-3funcs.c文件对应的是相应的计算器的C语言的代码。
之后利用VisualStudio命令提示实现计算器的功能。
结构图如下:
图3-1系统体系结构图
计算器系统流程图:
图3-2系统流程图
3.2.2系统模块划分
(1)fb3-3.h文件头声明部分
我们要做开始声明部分,在.h头文件中我们可以用以下语句来定义抽象语法树的structast{intnodetype;structast*l;structast*r;};且所有节点都有公共的初始nodetype。
而删除和释放抽象语法树可以用语句voidtreefree(structast*)来实现即可。
常量使用numval,符号引用使用symref赋值使用symasgn,它有一个指向被赋值符号的指针和使用抽象语法树表示的值;
(2)fb3-3.l文件词法分析部分
词法分析器中设计六个比较操作符都返回一个带有字面值以便于区分的CMP记号,其中这六个关键字和四个内置函数通过文字模式加以识别,它们放在通用模式之前以便于在通用模式之前进行匹配;利用符号表进行词法分析,其中符号表中记录输入中使用的名称以及常用的符号。
在这部分需要注意与C语言的交叉使用,对于每一类的词法分析须严格按照正则表达式来实现。
(3)fb3-3.y文件语法分析部分
语法分析器的设计,其中在语法分析器的最后提供了小部分错误恢复机制,这让我们有可能在错误发生时把语法分析器恢复到可以继续工作的状态;在这一部分我们为每个表达式建立了抽象语法树,以抽象语法树为单位进行计算,并打印出结果,并释放语法树。
在这一部分需考虑移进/规约冲突和操作符的优先级,一定要在此代码中区分语句(stmt)和表达式(exp)。
(4)fb3-3funcs.c文件C语言代码部分
在这一部分的文件中语法分析器及.y文件需要调用其中的函数,创建语法树节点、分配节点进行填充、遍历抽象语法树。
最后还要加一个辅助函数,正如《flex与bison》中所讲的一样,例程treefree的扩展版本会递归的遍历一颗抽象语法树并释放这棵树的所有节点。
本计算器的核心例程是eval,它用来计算分析器中构造的抽象语法树。
我们采用深度优先遍历算法来计算表达式的值;
3.2.3系统的数据流图
在系统中,用户在输入要计算的内容后,先进行词法分析和语法分析,之后再判断用户要计算的类型是哪种四则运算,系统运算之后将结果返回给用户,数据流图如下:
图3-3系统数据流图
3.3详细设计与实现
3.3.1fb3-3..h文件模块的设计与实现
在这部分中,主要是对整个系统中的头文件的说明。
首先我们要做开始声明部分,在.h头文件中我们可以用以下语句来定义抽象语法树的节点,且所有节点都有公共的初始nodetype。
而删除和释放抽象语法树可以用语句voidtreefree(structast*)来实现即可。
常量使用numval,符号引用使用symref赋值使用symasgn,它有一个指向被赋值符号的指针和使用抽象语法树表示的值;在代码的一开始是说明与词法分析器的接口,其中的变量yylineno来自词法分析器,接下来的部分用于构造抽象语法树,抽象语法树有多个节点组成,每个节点都有一个节点类型。
不同的节点可以有不同的域,但是在这个文件中有八种不同类型的指针。
之后一部分是对抽象语法树的操作,首先用eval遍历抽象语法树,返回它所代表的表达式的值,之后删除和释放抽象语法树。
下一部分是对符号表的声明,其中symbol为变量名,func为函数体,syms为虚拟参数列表。
之后建立一个符号列表,并将其作为参数列表。
在这个计算器中,每个符号都有一个变量和一个用户自定义函数。
value域用来保存符号的值,func域指向用抽象语法树表达的该函数的用户代码,而sym域指向任意多个虚拟参数的链表,这些参数也是符号。
函数newsymlist和symlistfree创建和释放符号。
下面抽象语法树的声明:
structast*newast(intnodetype,structast*l,structast*r);
structast*newcmp(intcmptype,structast*l,structast*r);
structast*newfunc(intfunctype,structast*l);
structast*newcall(structsymbol*s,structast*l);
structast*newref(structsymbol*s);
structast*newasgn(structsymbol*s,structast*v);
structast*newnum(doubled);
structast*newflow(intnodetype,structast*cond,structast*tl,structast*tr);
图3-4声明文件流程图
3.3.2fb3-3.l文件模块的设计与实现
词法分析器中设计六个比较操作符都返回一个带有字面值以便于区分的CMP记号,其中这六个关键字和四个内置函数通过文字模式加以识别,它们放在通用模式之前以便于在通用模式之前进行匹配;该词法分析器能够实现基本的词法分析功能如行数、关键字个数、单词个数以及简单注释等的判别。
这部分流程图如下所示:
图3-5词法分析程序流程图
3.3.3fb3-3.y文件模块的设计与实现
这一部分主要是进行语法和语义分析。
语法分析器的设计,其中在语法分析器的最后提供了小部分错误恢复机制,这让我们有可能在错误发生时把语法分析器恢复到可以继续工作的状态;在在代码的一开始%union定义了很多种符号值,符号值可以是符号表中特定用户符号、符号列表、比较子类型和函数记号的指针。
FUNC表示内置函数,它的值确定了具体的某个函数,另外6个保留字,从IF到Let。
记号CMP是6种比较操作符之一,它的值确定了具体的操作符。
优先级声明列表从新的CMP和=操作符开始,%start声明定义了顶层规则。
接下的部分区分了stmt和exp,语句是一个控制流或者是一个表达式。
每当规则匹配到一条语句时,他将调用相应的程序去创建合适的抽象语法树。
且list的定义是右递归的。
新的CMP规则处理6种比较操作符,它使用CMP的值来判断当前的操作符,还有一条赋值规则来创建赋值节点。
这一部分的程序流程图如下图所示:
图3-6语法部分流程图
3.3.4fb3-3funcs.c模块的设计与实现
在这一部分,用C语言进行创建抽象语法树和符号列表的过程,代码中对每一个节点进行分配,然后基于节点类型恰当地填充各个域,利用treefree递归地遍历一棵抽象语法树,同时释放这棵树的所有节点。
计算器的核心是函数eval,他计算语法分析器中构造的抽象语法树。
最后还要加一个辅助函数,正如《flex与bison》中所讲的一样,例程treefree的扩展版本会递归的遍历一颗抽象语法树并释放这棵树的所有节点。
本计算器的核心例程是eval,它用来计算分析器中构造的抽象语法树。
我们采用深度优先遍历算法来计算表达式的值;
double
eval(structast*a)
{
doublev;
if(!
a){
yyerror("internalerror,nulleval");
return0.0;
}
switch(a->nodetype){
/*constant*/
case'K':
v=((structnumval*)a)->number;break;
/*namereference*/
case'N':
v=((structsymref*)a)->s->value;break;
/*assignment*/
case'=':
v=((structsymasgn*)a)->s->value=
eval(((structsymasgn*)a)->v);break;
/*expressions*/
图3-7语法分析树图
例如:
分析fred=14+23-11+7
图3-8抽象语法树
3.4系统分析与测试
3.4.1测试用例设计
(1)简单的计算器,只能进行简单的四则运算,如(1+2)-(2*6)、1+2-3*2/5;
C:
\GnuWin32\bin>fb3-1.tab.exe
>|-1
=1
>|123
=123
>(1+2)-(2*6)
=-9
>1+2-3*2/5
=1.8
>
(2)使用内置函数sqrt(n)、exp(n),log(n)
C:
\GnuWin32\bin>fb3-2.tab.exe
>sqrt(10)
=3.162
>exp
(2)
=7.389
>log(7.389)
=2
(3)定义函数sq(n)、avg(a,b),用于计算平方根
C:
\GnuWin32\bin>fb3-2.tab.exe
>letsq(n)=e=1;while|((t=n/e)-e)>.001doe=avg(e,t);;
Definedsq
>letavg(a,b)=(a+b)/2;
Definedavg
>sq(10)
=3.162
>sq(10)-sqrt(10)
=0.000178
(4)第二次的改进的计算器,可以进行自定义函数的运算,而且语法更加贴近C语言;
定义函数sq(n)、avg(a,b),用于计算平方根
C:
\GnuWin32\bin>fb3-2.tab.exe
>letavg(a,b){(a+b)/2;}
Definedavg
>letsq(n){e=1;while(|((t=n/e)-e)>.001)do{e=avg(e,t);}}
Definedsq
>sq(10);
=3.162
>sq(10)-sqrt(10);
=0.000178
定义函数max(a,b),用于求a,b的最大值
C:
\GnuWin32\bin>fb3-2.tab.exe
>letmax(a,b){if(a>b)thena;elseb;}
Definedmax
>max(4,5);
=5
>max(1,5);
=5
>max(9,5);
=9
定义函数max3(a,b,c),用于求a,b,c的最大值
>letmax3(a,b,c){if(a>b)then{if(a>c)thena;elsec;}else{if(b>c)then
b;elsec;}}
Definedmax3
>max3(3,4,5);
=5
>max3(3,9,5);
=9
>max3(10,9,5);
=10
4.2测试结果
1.执行计算任务
定义函数sq(n)、avg(a,b),用于计算平方根
2.执行计算任务:
增加新的内置函数pow(a,n)计算一个数a的n次方
3.执行计算任务:
定义函数max(a,b),用于求a,b的最大值
3.执行计算任务:
定义函数max3(a,b,c),用于求a,b,c的最大值
结论
本文工作和成果
使用flex和bison开发了一个具有全部功能的桌面计算器,能够支持变量,过程,循环和条件表达式,使它成为一个虽然短小但是具有现实意义的编译器。
本次实验我实现了一个基本计算器的功能,可以进行基本的四则运算,在一开始不会添加自定义函数的操作,在老师和同学的帮助下,实现了自定义函数的功能,使其语法规则变得比较简单明了。
系统不足与展望
本系统的不足是计算器的内置函数中只有简单的四则运算,没有其他类似于三角函数计算的函数,希望通过之后的进一步学习,可以实现这一功能。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 FlexBison 高级 解释 设计 实现