NFA转化为DFA的转换算法及实现_第1页
NFA转化为DFA的转换算法及实现_第2页
NFA转化为DFA的转换算法及实现_第3页
NFA转化为DFA的转换算法及实现_第4页
NFA转化为DFA的转换算法及实现_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、精选优质文档-倾情为你奉上编译原理课程实践报告设计名称:NFA转化为DFA的转换算法及实现 二级学院: 数学与计算机科学学院 专 业: 计算机科学与技术 班 级: 计科本091班 姓 名: 学 号: 指导老师: 日 期: 2012年6月28日 摘要有穷自动机分为确定的有穷自动机(DFA)和不确定的有穷自动机(NFA)两类。两者各有特点、作用于不同的地方,因此需要进行转化。NFA转化为DFA的理论在词法构造乃至整个编译器构造过程中起着至关重要的作用,同时它们被广泛应用于计算机科学的各个领域,它们与计算机其它学科之间也有着很密切的关系。本文主要介绍基于编译器构造技术中的由NFA转化为DFA的算法设

2、计和实现技术:主要包括NFA转化为与其等价的DFA所使用的子集构造算法以及把DFA化简的算法,实现词法分析,最后使用Visual C+语言加以实现。NFA转化为与其等价的DFA需分两步进行:1、构造NFA的状态的子集的算法;2、计算-closure。完成这些子模块的设计后,再通过某一中间模块的总控程序对其调用,最后再由主程序总调用,也就实现了NFA转化为其等价的DFA,接下来就是以分割法的思想为指导实现DFA的化简,最后并以实例加以说明。关键词:有穷自动机;NFA ;DFA; 转化 ; 化简目录1 前言1.1 选题的依据和必要性由于很多计算机系统都配有多个高级语言的编译程序,对有些高级语言甚至

3、配置了几个不同性质的编译程序。从功能上看,一个编译程序就是一个语言翻译程序。语言翻译程序把源语言书写的程序翻译成目标语言的等价程序。经过编译程序的设计可以大大提高学生的编程能力。编译程序的工作过程通常是词法分析、语法分析、语义分析、代码生成、代码优化1。由于现在有很多词法分析程序工具都是基于有穷自动机的,而词法分析又是语法分析的基础2,所以我们有必要进行有穷自动机的确定化和最小化。1.2 课题意义编译程序的这些过程的执行先后构成了编译程序的逻辑结构3。有穷自动机(也称有限自动机)作为一种识别装置,它能准确地识别正规集,即识别正规文法所定义的语言和正规式所表示的集合,引入有穷自动机这个理论,正是

4、为词法分析程序的自动构造寻找特殊的方法和工具4。NFA转化为DFA的理论在词法构造至整个编译器构造过程中起着至关重要的作用,同时它们被广泛应用于计算机科学的各个领域,它们与计算机其它学科也有着密切的联系。2 NFA转化为DFA的算法及实现编译原理是计算机专业的一门重要专业课,旨在介绍编译程序构造的一般原理和基本方法。内容包括语言和文法、词法分析、语法分析、语法制导翻译、中间代码生成、存储管理、代码优化和目标代码生成。进行NFA转换为DFA的词法分析和语法分析,首先要对目标对象有有所了解,这就需要对NFA、DFA进一步了解。2.1 基本定义NFA,也称不确定的有穷自动机,是由一个五元式定义的数学

5、模型,特点是它的不确定性,即在当前状态下,读入同一个字符,可能有多个下一状态。DFA,也称确定的有穷自动机,也是由一个五元式定义的数学模型,相对的特点是它的确定性,即在当前状态下,读入同一个字符,最多有一个后继状态。2.1.1 NFA的概念 NFA(nondeterministic finite-state automata)即非确定有限自动机, 一个非确定的有限自动机NFA M是一个五元式: NFA M=(S, , , S0, F)其中 S有限状态集 输入符号加上,即自动机的每个结点所射出的弧可以是中一个字符或是. S0初态集 F终态集 转换函数 S× 2S (2S -S的幂集S的

6、子集构成的集合)状态转换图如图2.1.1:S1 Z1 0P10,1图2.1.1 NFA状态转换图2.1.2 DFA的概念DFA(deterministic finite-state automata)即确定有限自动机,一个确定的有限自动机DFA M是一个五元式: M=(S, ,, S0, Z) 其中: S 有限状态集 输入字母表 映射函数(也称状态转换函数) S×S (s,a)=S , S, S S, a S0 初始状态 S0 S Z终止状态集 ZÍSP ZPPaababba,b图2.1.2 DFA状态转换图2.1.3 NFA与DFA的矩阵表示一个NFA或者DFA还可以用一

7、个矩阵5表示,矩阵也可以说是状态转换表,它的优点是可以快速访问给定的状态在给定的输入字符时能转换到的状态集。矩阵,每个状态一行,每个输入符号和(如果有需要的)各占一列,表的第i行中与输入符号a对应的表项是一个状态集合,表示NFA或者DFA在状态i输入a时所能到达的状态集合(DFA的集合唯一),即(i,a)6。 (7)如图2.1.1可用表2.3.1.表示:表2.3.1 NFA状态转换表 输入状态01SPS,ZPZZPP 如图2.1.2可用表2.3.2表示:表2.3.2 DFA状态转换表 输入状态ab012132213333 2.1.4 NFA向DFA的转换的思路从NFA的矩阵表示中可以看出,表项

8、通常是一状态的集合,而在DFA的矩阵表示中,表项是一个状态,NFA到相应的DFA的构造的基本思路是:DFA的每一个状态对应NFA的一组状态DFA使用它的状态记录在NFA读入一个输入符号后可能达到的所有状态4。2.2 NFA和DFA之间的联系在非确定的有限自动机NFA中,由于某些状态的转移需从若干个可能的后续状态中进行选择,故一个NFA对符号串的识别就必然是一个试探的过程。这种不确定性给识别过程带来的反复,无疑会影响到FA的工作效率。而DFA则是确定的,将NFA转化为DFA将大大提高工作效率,因此将NFA转化为DFA是有其一定必要的。3 DFA的化简得到新的DFA之后,并没有完成任务,因为通过N

9、FA转化成DFA不一定是最简的,也就是说,有多余的状态可以被删除,而我们需要的是得到一个唯一的最简的DFA12,也就是说,NFA转化为DFA之后,还需要化简,也就是最小化。3.1 化简的理论基础DFA的化简是指:寻找一个状态数最少的DFA M,使得L(M)=L(M)。化简的方法是消去DFA M中的多余状态(或无用状态),合并等价状态。DFA中的多余状态是指这样的状态:从开始状态出发,读入任何输入串都不能到达的那个状态;或者从这个状态没有通路到达终态。两个状态S 和T等价是指:如果从状态S出发能读出某个字W而停于终态,从T出发也能读出同样的字W而停于终态;反之,从T出发能读出同样的字W而停于终态

10、,从S出发也能读出某个字W而停于终态。3.2 化简的基本思想化简DFA的基本思想是指导它的状态分成一些互不相交的子集,每一个子集中的状态都不是等价的,不同子集中的状态可以由某个输入串来区别,最后将不能区别的每个子集用一个状态来做代表13-15,这种方法称为“分割法”。具体过程是:(1)将M的所有状态分成两个子集终态集和非终态集;(2)考察每一个子集,若发现某子集中的状态不等价,将其划分为两个集合;(3)重复第(2)步,继续考察已得到的每一个子集,直到没有任何一个子集需要继续划分为止。这时DFA的状态被分成若干个互不相交的子集。(4)从每个子集中选出一个状态做代表即可得到最简的DFA。3.3 化

11、简的代码实现#include<iostream>#include<string>#define MAXS 100using namespace std;string NODE; /结点集合string CHANGE; /终结符集合int N; /NFA边数struct edgestring first;string change;string last;struct chanstring ltab;string jiheMAXS;void kong(int a)int i;for(i=0;i<a;i+)cout<<' '/排序void

12、paixu(string &a)int i,j;char b;for(j=0;j<a.length();j+)for(i=0;i<a.length();i+)if(NODE.find(ai)>NODE.find(ai+1)b=ai;ai=ai+1;ai+1=b; void eclouse(char c,string &he,edge b)int k;for(k=0;k<N;k+)if(c=bk.first0)if(bk.change="*")if(he.find(bk.last)>he.length()he+=bk.last;e

13、clouse(bk.last0,he,b);void move(chan &he,int m,edge b)int i,j,k,l;k=he.ltab.length();l=he.jihem.length();for(i=0;i<k;i+)for(j=0;j<N;j+)if(CHANGEm=bj.change0)&&(he.ltabi=bj.first0)if(he.jihem.find(bj.last0)>he.jihem.length()he.jihem+=bj.last0; for(i=0;i<l;i+)for(j=0;j<N;j+)

14、if(CHANGEm=bj.change0)&&(he.jihemi=bj.first0)if(he.jihem.find(bj.last0)>he.jihem.length()he.jihem+=bj.last0;/输出void outputfa(int len,int h,chan *t)int i,j,m;cout<<" I "for(i=0;i<len;i+)cout<<'I'<<CHANGEi<<" "cout<<endl<<&q

15、uot;-"<<endl;for(i=0;i<h;i+)cout<<' '<<ti.ltab;m=ti.ltab.length();for(j=0;j<len;j+)kong(8-m);m=ti.jihej.length();cout<<ti.jihej;cout<<endl;void main()edge *b=new edgeMAXS;int i,j,k,m,n,h,x,y,len;bool flag;string jhMAXS,endnode,ednode,sta;cout<<&

16、quot;请输入NFA各边信息(起点 条件空为* 终点),以#结束:"<<endl;for(i=0;i<MAXS;i+)cin>>bi.first;if(bi.first="#") break;cin>>bi.change>>bi.last;N=i;/*for(j=0;j<N;j+)cout<<bj.first<<bj.change<<bj.last<<endl;*/for(i=0;i<N;i+)if(NODE.find(bi.first)>NO

17、DE.length()NODE+=bi.first;if(NODE.find(bi.last)>NODE.length()NODE+=bi.last;if(CHANGE.find(bi.change)>CHANGE.length()&&(bi.change!="*")CHANGE+=bi.change;len=CHANGE.length();cout<<"结点中属于终态的是:"<<endl;cin>>endnode;for(i=0;i<endnode.length();i+)if(NO

18、DE.find(endnodei)>NODE.length()cout<<"所输终态不在集合中,错误!"<<endl;return;/cout<<"endnode="<<endnode<<endl;chan *t=new chanMAXS; t0.ltab=b0.first;h=1;eclouse(b0.first0,t0.ltab,b); /求e-clouse/cout<<t0.ltab<<endl;for(i=0;i<h;i+) for(j=0;j<

19、ti.ltab.length();j+)for(m=0;m<len;m+)eclouse(ti.ltabj,ti.jihem,b); /求e-clousefor(k=0;k<len;k+)/cout<<ti.jihek<<"->"move(ti,k,b); /求move(I,a)/cout<<ti.jihek<<endl;for(j=0;j<ti.jihek.length();j+)eclouse(ti.jihekj,ti.jihek,b); /求e-clousefor(j=0;j<len;j+)

20、paixu(ti.jihej); /对集合排序以便比较for(k=0;k<h;k+)flag=operator=(tk.ltab,ti.jihej);if(flag)break;if(!flag&&ti.jihej.length()th+.ltab=ti.jihej;cout<<endl<<"状态转换矩阵如下:"<<endl;outputfa(len,h,t); /输出状态转换矩阵/状态重新命名string *d=new stringh;NODE.erase();cout<<endl<<&qu

21、ot;重命名:"<<endl;for(i=0;i<h;i+) sta=ti.ltab;ti.ltab.erase(); ti.ltab='A'+i;NODE+=ti.ltab;cout<<''<<sta<<"="<<ti.ltab<<endl;for(j=0;j<endnode.length();j+)if(sta.find(endnodej)<sta.length()d1=ednode+=ti.ltab;for(k=0;k<h;k+)f

22、or(m=0;m<len;m+)if(sta=tk.jihem)tk.jihem=ti.ltab;for(i=0;i<NODE.length();i+)if(ednode.find(NODEi)>ednode.length()d0+=NODEi;endnode=ednode;cout<<endl<<"DFA如下:"<<endl;outputfa(len,h,t); /输出DFAcout<<"其中终态为:"<<endnode<<endl;/DFA最小化m=2;sta.

23、erase();flag=0; for(i=0;i<m;i+)/cout<<"d"<<i<<"="<<di<<endl;for(k=0;k<len;k+)/cout<<"I"<<CHANGEk<<endl;y=m;for(j=0;j<di.length();j+)for(n=0;n<y;n+)if(dn.find(tNODE.find(dij).jihek)<dn.length()|tNODE.find(dij

24、).jihek.length()=0)if(tNODE.find(dij).jihek.length()=0) x=m;else x=n;if(!sta.length() sta+=x+48;elseif(sta0!=x+48)dm+=dij;flag=1;di.erase(j,1);/cout<<di<<endl;j-;break; /跳出n/n/jif(flag)m+;flag=0;/cout<<"sta="<<sta<<endl;sta.erase();/k/icout<<endl<<

25、"集合划分:"for(i=0;i<m;i+)cout<<""<<di<<" "cout<<endl;/状态重新命名chan *md=new chanm; NODE.erase();cout<<endl<<"重命名:"<<endl;for(i=0;i<m;i+) mdi.ltab='A'+i; NODE+=mdi.ltab;cout<<""<<di<<

26、"="<<mdi.ltab<<endl;for(i=0;i<m;i+)for(k=0;k<len;k+)for(j=0;j<h;j+)if(di0=tj.ltab0)for(n=0;n<m;n+)if(!tj.jihek.length()break;elseif(dn.find(tj.jihek)<dn.length()mdi.jihek=mdn.ltab;break;break;ednode.erase();for(i=0;i<m;i+)for(j=0;j<endnode.length();j+)if(di

27、.find(endnodej)<di.length()&&ednode.find(mdi.ltab)ednode+=mdi.ltab;endnode=ednode;cout<<endl<<"最小化DFA如下:"<<endl;outputfa(len,m,md); cout<<"其中终态为:"<<endnode<<endl;4 程序设计通过本设计所要求达到的目的是:充分理解和掌握NFA,DFA以及NFA确定化过程的相关概念和知识,理解和掌握子集法的相关知识和应用,

28、现在需要编程16-18实现对输入NFA转换成DFA输出的功能。4.1 程序分析4.1.1 流程图程序总框图如图4.1所示: 总模块NFA图结构状态转换表DFA图结构初始化状态转换矩阵状态转换操作图4.1 .1 程序总框图开始输入NFA,初始化NFA初步转化为DFA结束重命名化简 图4.1.2 功能图4.1.2 子集构造法已证明:非确定的有限自动机与确定的有限自动机从功能上来说是等价的,也就是说,我们能够从:NFA M DFA M使得 L(M)=L(M)为了使得NFA确定化,我们首先给出两个定义:定义1:集合I的-闭包:令I是一个状态集的子集,定义-closure(I)为:1)若sI,则s-closure(I);2)若sI,则从s出发经过任意条弧能够到达的任何 状态都属于-clos

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论