编译原理词法2(NFA、DFA的确定化和化简)

合集下载

编译原理实验NFA确定化为DFA

编译原理实验NFA确定化为DFA

实用文档2016.11.02不确定有穷状态自动机的确定化目录一、实验名称 (2)二、实验目的 (2)三、实验原理 (2)1、NFA定义 (2)2、DFA的定义 (2)3、closure函数 (2)4、move函数 (3)四、实验思路 (3)1、输入 (3)2、closure算法 (3)3、move算法 (3)4、构造子集 (4)5、输出 (4)五、实验小结 (4)1、输入存储问题 (4)2、closure算法问题 (4)3、输出问题 (5)六、附件 (5)1、源代码 (5)2、运行结果截图 (7)一、实验名称不确定有穷状态自动机的确定化二、实验目的输入:非确定有穷状态自动机NFA输出:确定化的有穷状态自动机DFA三、实验原理1、NFA定义一个不确定的有穷自动机M是一个五元组,M=(K,E,f,S,Z)其中a.K是一个有穷集,它的每个元素称为一个状态;b.E是一个有穷字母表,它的每个元素称为一个输入符号;c.f是一个从K×E*到K的子集的映像,即:K*E*->2k,其中2k表示K的幂集;d.S包含于K,是一个非空初态集;e.Z包含于K,是一个终态集。

2、DFA的定义一个确定的有穷自动机M是一个五元组,M=(K,E,f,S,Z)其中a.K是一个有穷集,它的每个元素称为一个状态;b.E是一个有穷字母表,它的每个元素称为一个输入符号;c.f是转换函数,是K×E->K上的映像,即,如f(ki,a)=kj(ki∈K,kj∈K)就意味着,当前状态为ki,输入字符为a时,将转换到下一状态kj,我们把kj称作ki的一个后继状态;d.S∈K,是唯一的一个初态;e.Z包含于K,是一个终态集,终态也称可接受状态或结束状态。

3、closure函数状态集合I的ε—闭包,表示为ε—closure(I),定义为一状态集,是状态集I中的任何状态S经任意条ε弧而能到达的状态的集合。

4、move函数状态集合I的a弧转换,表示为move(I,a),定义为状态集合J,其中J是所有那些从I中的某一状态经过一条a弧而到达的状态的全体。

编译原理第三章_有穷自动机

编译原理第三章_有穷自动机
5
例 过河问题 分析(续)
初始状态:MWGC-φ;终止状态:φ-MWGC。 g
MWGC-φ
WC-MG
问题:
6
例 过河问题 状态转换图
起始 g
MWGC-φ g
g φ-MWGC
g
7
WC-MG
m
m MWC-G
w
w
c
C-MWG
c W-MGC
g
g
MGC-W c
MG-WC
w
m
c G-MWC
m
gg MWG-C
+dd. ddd;
输入符号串
数字 数字
SB
.
数字
+
A
H
-.
数字
.G
接收:若扫描完输入串, 且在一个终止状态上结 束。
数字 阻塞:若扫描结束但未 停止在终止状态上;或 者为能扫描完输入串 (如遇不合法符号)。
不完全描述:某些状态 对于某些输入符号不存 在转换。
练习:+34.567 .123 3.4.5
w
有穷自动机(FA)
数字系统:可以从一个状态移动到另一个状态;每次 状态转换,都上由当前状态及一组输入符号确定的;可以 输出某些离散的值集。
FA:一个状态集合;状态间的转换规则;通过读头来 扫描的一个输入符号串。
读头:从左到右扫描符号串。移动(扫描)是由状态 转换规则来决定的。
8
读头
一个FA的例子
(3)运行: 串f(,Q,且t1tt21)∈= Σf(,f(Qt1,t2t1∈), Σt2*),其中Q∈K, t1t2为输入字符
17
例3
题:试证abba可为例1的DFA M所识别(所接受)。

编译原理词法NFADFA的确定化和化简

编译原理词法NFADFA的确定化和化简

编译原理词法NFADFA的确定化和化简编译原理中的词法分析主要包括以下步骤:词法分析器将输入的源程序文本转化为一个个单词(token),即词法单元。

在词法分析过程中,使用的主要工具是有限自动机(NFA)和确定的有限自动机(DFA)。

NFA(DFA)的确定化是指将一个非确定的有限自动机转化为一个确定的有限自动机。

非确定有限自动机具有多个可能的转换路径,而确定有限自动机每个状态只能有一个转换路径。

确定化的目的是简化自动机的状态图,减少转换的复杂性,便于理解和实现。

确定化的过程一般包括以下步骤:1)初始化:将NFA的起始状态作为DFA的起始状态,并为其创建一个新的DFA状态。

2)闭包运算:对于DFA中的每个状态,根据NFA的ε-转换,计算其ε-闭包(即能够通过ε-转换到达的状态集合)。

3)转换运算:对于DFA中的每个状态和每个输入符号,根据NFA的转换函数,计算DFA中该输入下的状态转移集合。

4)如果新生成的DFA状态集合不在已有的DFA状态集合中,则将其加入到DFA状态集合中,并进行闭包和转换运算;如果已存在,则继续下一个输入符号的转换运算。

5)重复步骤4,直到不再生成新的DFA状态集合。

化简是指对于一个确定的有限自动机(DFA),将其中无用的状态进行合并,得到一个更加简洁的自动机。

化简的目的是减少状态数目,提高运行效率和存储效率。

化简的过程一般包括以下步骤:1)初始化:将DFA状态分为两个集合,一个是终止状态集合,一个是非终止状态集合。

2)将所有的等价状态划分到同一个等价类中。

3)不断迭代以下步骤,直到不能再划分等价类为止:a)对于每对不同的状态p和q,若存在一个输入符号a,通过转移函数计算得到的状态分别位于不同的等价类中,则将该状态划分到不同的等价类中。

b)对于每个等价类中的状态集合,将其进一步划分为更小的等价类。

最终,得到的化简DFA状态图比原始DFA状态图要小,且功能等价。

[编译原理代码][NFA转DFA并最小化DFA并使用DFA进行词法分析]

[编译原理代码][NFA转DFA并最小化DFA并使用DFA进行词法分析]

[编译原理代码][NFA转DFA并最⼩化DFA并使⽤DFA进⾏词法分析]#include <iostream>#include <vector>#include <cstring>#include "stack"#include "algorithm"using namespace std;int NFAStatusNum,AlphabetNum,StatusEdgeNum,AcceptStatusNum;char alphabet[1000];int accept[1000];int StartStatus;int isDFAok=1;int isDFA[1000][1000];/** NFA状态图的邻接表*/vector<vector<int>> Dstates;int Dstatesvisit[1000];int Dtran[1000][1000];vector<int> Dtranstart;vector<int> Dtranend;int isDtranstart[1000];int isDtranend[1000];class Edge{public:int to,w,next;} ;Edge edge[10000];int edgetot=0;int Graph[1000];void link(int u,int v,int w){edge[++edgetot].to=v;edge[edgetot].w=w;edge[edgetot].next=Graph[u];Graph[u]=edgetot;}void input(){int u,v,w;memset(Dtran,-1,sizeof(Dtran));scanf("%d %d %d %d\n",&NFAStatusNum,&AlphabetNum,&StatusEdgeNum,&AcceptStatusNum);for(int i=1;i<=AlphabetNum;i++){ //读⼊字母表scanf("%c",&alphabet[i]);}for(int i=1;i<=AcceptStatusNum;i++){scanf("%d",&accept[i]);}//开始状态序号scanf("%d",&StartStatus);for(int i=0;i<StatusEdgeNum;i++){scanf("%d%d%d\n",&u,&v,&w);link(u,v,w);if(isDFA[u][v]==0){isDFA[u][v]=1;}else{isDFAok=0;}if(w==0){isDFAok=0;}}//读⼊测试字符串}void e_clouser(vector<int> &T,vector<int> &ans){int visit[1000];memset(visit,0,sizeof(visit));stack<int> Stack;//T all push in Stack and copy to ansfor (int i=0;i < T.size();++i){Stack.push(T[i]);ans.push_back(T[i]);visit[T[i]]=1;while(Stack.empty()!=1){int t = Stack.top(); Stack.pop();for(int p=Graph[t];p!=0;p=edge[p].next){if(edge[p].w==0){if(visit[edge[p].to]==0){visit[edge[p].to]=1;Stack.push(edge[p].to);ans.push_back(edge[p].to);}}}}sort(ans.begin(),ans.end());}void move(vector<int> &T,int a,vector<int> &ans){ int visit[1000];memset(visit,0,sizeof(visit));for(int i=0;i<T.size();i++) {int t=T[i];for (int p = Graph[t]; p != 0; p = edge[p].next) { if (edge[p].w == a) {if (visit[edge[p].to] == 0) {visit[edge[p].to] = 1;ans.push_back(edge[p].to);}}}}}bool notin(vector<int> &a,int &U){for(int i=0;i<Dstates.size();i++){int ok=1;if(Dstates[i].size()==a.size()){for(int j=0;j<a.size();j++){if(Dstates[i][j]!=a[j]){ok=0;break;}}if(ok==1) {U=i;return false;}}}U=Dstates.size();return true;}void nfatodfa(){vector<int> s,t;s.push_back(StartStatus);e_clouser(s,t);Dstates.push_back(t);stack<int> Stack;Stack.push(Dstates.size()-1);while(Stack.empty()!=1){int T=Stack.top();Stack.pop();int U;for(int i=1;i<=AlphabetNum;i++){vector<int> ans,ans2;move(Dstates[T],i,ans2);e_clouser(ans2,ans);if(notin(ans,U)){Dstates.push_back(ans);Stack.push(Dstates.size()-1);}Dtran[T][i]=U;}}}void getDtranStartEnd(){for(int i=0;i<Dstates.size();i++){int ok=1;for(int j=0;j<Dstates[i].size();j++){if(Dstates[i][j]==StartStatus){Dtranstart.push_back(i);isDtranstart[i]=1;}for(int k=1;k<=AcceptStatusNum;k++){if(Dstates[i][j]==accept[k]){ok=0;Dtranend.push_back(i);isDtranend[i]=1;}}}}}}vector<vector<int>> newDstates;int newDstatesvisit[1000];int newDtran[1000][1000];int set[1000];vector<int> newDtranstart;vector<int> newDtranend;int isnewDtranstart[1000];int isnewDtranend[1000];void simple(){int visit[1000];memset(visit,0,sizeof(visit));vector<int> a,b;//接受结点加⼊afor(int i=0;i<Dtranend.size();i++){a.push_back(Dtranend[i]);visit[Dtranend[i]]=1;set[Dtranend[i]]=0;}//剩余结点加⼊bfor(int i=0;i<Dstates.size();i++){if(visit[i]==0){b.push_back(i);set[i]=1;}}newDstates.push_back(a);newDstates.push_back(b);while(1){int ok=0;for(int i=0;i<newDstates.size();i++){for (int k = 1; k <= AlphabetNum; k++) {for(int j=1;j<newDstates[i].size();j++) {int pp= Dtran[newDstates[i][0]][k];int u = newDstates[i][j], v = Dtran[u][k];if (set[v] != set[pp] ) {//将u剥离newDstates[i].erase(newDstates[i].begin() + j); vector<int> temp;temp.push_back(u);set[u] = newDstates.size();newDstates.push_back(temp);ok = 1;break;}if (ok == 1) break;}if(ok==1) break;}if(ok==1) break;}if(ok==0) break;}//isnewDtranstart,isnewDtranend,newDtranfor(int i=0;i<Dstates.size();i++) {for (int j = 1; j <= AlphabetNum; j++) {newDtran[set[i]][j]=set[Dtran[i][j]];}if(isDtranend[i]==1)isnewDtranend[set[i]]=1;if(isDtranstart[i]==1)isnewDtranstart[set[i]]=1;}//isnewDtranstart,isnewDtranend}bool dfa(char *S){int status=0;for(int i=0;i<newDstates.size();i++){if(isnewDtranstart[i]==1){status=i;}}for(int i=0;i<strlen(S);i++) {//这⾥我偷懒了,懒得弄个map存映射,直接对这个例⼦进⾏操作,就是 S[i]-'a'+1; int p=S[i]-'a'+1;status=newDtran[status][p];}if(isnewDtranend[status]==1) return true;else return false;}int main() {freopen("E:\\NFATODFA\\a.in","r",stdin);input();if(isDFAok==0){printf("This is NFA\n");nfatodfa();}else{printf("This is DNA\n");}//打印DFAprintf("\nPrint DFA's Dtran:\n");printf(" DFAstatu a b");getDtranStartEnd();for(int i=0;i<Dstates.size();i++){printf("\n");if(isDtranstart[i]==1)printf("start ");else if(isDtranend[i]==1)printf("end ");else printf(" ");printf("%5c ",i+'A');for(int j=1;j<=AlphabetNum;j++)printf("%5c ",Dtran[i][j]+'A');}printf("\nPrint simple DFA's Dtran:\n");simple();printf(" DFAstatu a b");for(int i=0;i<newDstates.size();i++){printf("\n");if(isnewDtranstart[i]==1)printf("start ");else if(isnewDtranend[i]==1)printf("end ");else printf(" ");printf("%5c ",i+'A');for(int j=1;j<=AlphabetNum;j++)printf("%5c ",newDtran[i][j]+'A');}printf("\n");char S[1000];while(scanf("%s\n",S)!=EOF){if(dfa(S)){printf("%s belongs to the DFA\n",S);}elseprintf("%s don't belong to the DFA\n",S);}return 0;}。

编译原理与技术 词法分析 (2)

编译原理与技术 词法分析 (2)

某终态。
识别相同正规集的DFA和NFA: DFA的规模(在状态 数和状态转换上)一般比相应的NFA复杂(可以达到 指数级)
2024/8/6
《编译原理与技术》讲义
16
比较 DFA 和 NFA(3)
e.g.11 识别正规式(0|1)*01的DFA和NFA
0
NFA :
S0
0
S1
1
S2
DFA :
1
1
0
S0
e.g.9 下面DFA M识别的语言L(M)是什么?
S
1
1
S0
S1
1
00 0
00
1
S2
1
S3
2024/8/6
《编译原理与技术》讲义
含偶数个0和偶数个1的0,1串}
1 S0
1 00
1
S2
1
S1 00
S3
S0 偶数个“0”与偶数个“1”的 0,1串
(S1,1)= {S2}
(S2,0)= {S2}
(S2,1)= {S2}
(S3,0)= {S4}
(S3,1)= ∅
(S4,0)= {S4}
(S4,1)= {S4}
2024/8/6
《编译原理与技术》讲义
6
有限自动机的表示
e.g.7 中NFA的状态转换图如下:
0,1
0,1
0
0
S0
S3
S4
1
S1 1
S2 0,1
18
正规式与有限自动机
✓ R= R1 | R2
(1)
Si
fi
R1对应的 NFA,Si为初 态,fi为终态
2024/8/6
Sj

NFA到DFA的确定化及最小化

NFA到DFA的确定化及最小化
{
m++;
flag=0;
}
//cout<<"sta="<<sta<<endl;
sta.erase();
}//k
}//i
cout<<endl<<"集合划分:";
for(i=0;i<m;i++)
cout<<"{"<<d[i]<<"} ";
cout<<endl;
//状态重新命名
chan *md=new chan[m];
{
//cout<<t[i].jihe[k]<<"->";
move(t[i],k,b); //求move(I,a)
//cout<<t[i].jihe[k]<<endl;
for(j=0;j<t[i].jihe[k].length();j++)
eclouse(t[i].jihe[k][j],t[i].jihe[k],b); //求e-clouse
NFA转化为DFA的确定化及最小化
一NFA向DFA的转换
从NFA的矩阵表示中可以看出,表项通常是一状态的集合,而在DFA的矩阵表示中,表项是一个状态,NFA到相应的DFA的构造的基本思路是:DFA的每一个状态对应NFA的一组状态.DFA使用它的状态记录在NFA读入一个输入符号后可能达到的所有状态.
得到新的DFA之后,并没有完成任务,因为通过NFA转化成DFA不一定是最简的,也就是说,有多余的状态可以被删除,而我们需要的是得到一个唯一的最简的DFA[12],也就是说,NFA转化为DFA之后,还需要化简,也就是最小化。

编译原理2.2 自动机理论

编译原理2.2 自动机理论

A=(aA|dA)|(a|d)
A=a|d
将它化为正规文法 变成A→
A=(a|d)A|(a|d)
A=(a|d)*(a|d)

(a|d)A|(a|d)
再根据上述 规则2转换 x=y= (a|d)
19
将A代入S=aA|a得到如下: S=a( (a|d)*(a|d)) |a =a(a|d)+|a
=a((a|d)+|)= a(a|d)+
含义:当前状态为 Ki,输入字符a, 转换为Kj状态
DFA映射的唯一性和初态的唯一性
22
DFA等价表示法:
DFA形式定义=状态转换图=状态矩阵
1、单词的构成规则用状态转换图表示
方法如下: 初始态用 “-”或“”表示;
终态点用 “+” 或“” 表示;
若f(Ki ,a)= Kj ,则从状态点Ki 到Kj画弧,标
“” 都是左结合的
9
讨论下面两个例子 例1 令={l,d},则上的正规式 r=l(ld)定义 的正规集为: {l,ll,ld,ldd,„„},其中l 代表字母,d代表数字,正规式 即是 字母 (字母|数字) ,它表示的正规集中的每个 元素的模式是“字母打头的字母数字串”, 就是Pascal和多数程序设计语言允许的标 识符的词法规则.
对于Σ*中的任何字符串t,若存在一条初态到 某一终态的路,且这条路上所有弧的标记符连接成 的字符串等于t,则称t可为DFA M所接受。 若M的初态同时又是终态,则空字可为M所接 受。
33
4、接受(识别)的理解:
① 设QK,函数f(Q,)=Q,则输入字符串是 空串,并停留在原状态上。
② 输入字符串t(t表示成Tt1形式,TΣ,t1 Σ*),在DFA M上运行的定义为:f(Q,Tt1) =f(f(Q,T),t1),其中QK。

编译原理 NFA转DFA

编译原理 NFA转DFA

实验一:利用子集法构造DFA一.实验目的掌握将非确定有限自动机确定化的方法和过程。

二.实验要求、内容及步骤实验要求:1.输入一个NFA,输出一个接受同一正规集的DFA;2.采用C++语言,实现该算法;3.编制测试程序;4.调试程序。

实验步骤:1.输入一个NFA关系图;2.通过一个转换算法将NFA转换为DFA;3.显示DFA关系图。

三.实验设备计算机、Windows 操作系统、Visual C++ 程序集成环境。

四.实验原理1.NFA-DFA转换原理:从NFA的矩阵表示中可以看出,表项通常是一状态的集合,而在DFA的矩阵表示中,表项是一个状态,NFA到相应的DFA的构造的基本思路是:DFA的每一个状态对应NFA的一组状态。

DFA使用它的状态去记录在NFA读入一个输入符号后可能到达的所有状态。

输入:一个NFA N输出:一个接受同样语言的DFA D方法:为D构造转换表Dtran,DFA的每个状态是NFA的状态集。

D的状态集合用Dstates表示。

D的开始状态为ε-closure(s0),s0是N的开始状态。

使用下列算法构造D的状态集合Dstates和转换表Dtran。

如果D的某个状态是至少包含一个N的接受状态的NFA状态集,那么它是D的一个接受状态。

2.子集构造法:初始时, ε-closure(S0) 是Dstates中唯一的状态且未被标记;while Dstates中存在一个未标记的状态T do begin标记T;for 每个输入符号a do beginU := ε-closure ( move (T, a) );if U 没在Dstates中then将U作为一个未被标记的状态添加到 Dstates.Dtran [ T, a ] := Uendend3.ε-closure的计算:将T中所有状态压入栈stack;将ε-closure (T) 初始化为T;while stack不空 do begin将栈顶元素t弹出栈;for 每个这样的状态u:从t到u有一条标记为ε的边do if u不在ε-closure ( T )中 do begin将u 添加到ε-closure ( T );将u压入栈stack中 endend五.程序设计1.总体设计2.子程序设计识别模块读入字符识别模块识别标识符识别分界符、运算符识别常数输出六.程序中的结构说明1.结构体Symbolrecord 结构体结构体成员名 成员属性Symbol[10] 用于存储关键字编码名 id用于存储关键字对应的编码读取字符字母识别标识符数字识别数字/识别注释打印并结束FTFTFTentrytype结构体结构体成员名成员属性idname[10] 用于存储识别后标识符名address 用于存储标识符的地址type 用于存储标识符的类型digittype结构体结构体成员名成员属性num 用于存储识别后的数字address 用于存储标识符数字的地址tokentype结构体结构体成员名成员属性id 用于存储被识别的类型名entry 用于存储标识符的地址idname[10] 用于存储被识别的标识符名2.符号编码表符号编码表符号名代码符号名代码Begin 0 } 14End 1 ( 15If 2 ) 16 Then 3 < 17 Else 4 <= 18for 5 = 19do 6 != 20while 7 > 21+ 8 >= 22- 9 := 23* 10 ‘’24/ 11 Id 25; 12 Const 26{ 133.重要函数介绍tokentype recogid(char ch)//识别标识符算法tokentype recogdig(char ch) ///识别数字函数tokentype recogdel(char ch) //识别算符和界符函数tokentype handlecom(char ch) //handlecom函数,识别注释函数void sort(char ch) //sort函数,读取文件内容,并根据读入内容调用不同的识别函数void scanner()//scanner函数,打开文件七.函数代码#include <stdio.h>#include <string.h>#include <ctype.h>#include <stdlib.h>;-----------------------定义单词编码表的数据结构-------------------- struct symbolrecord{ char symbol[10];int id;} ;;-------------------------定义符号表的数据结构---------------------- struct entrytype{ char idname[10];int address;int type;};;-------------------------定义常数表的数据结构---------------------- struct digittype{ int num;int address;};;---------------------------Token字的数据结构----------------------- struct tokentype{ int id;int entry;char idname[10];};FILE *fp; //源文件指针struct digittype d[10]; //定义常数表,个数指针struct entrytype a[40];int k=0,t=0;;---------------------------单词编码表初始化------------------------ struct symbolrecord s[26]={ "Begin",0,"End",1,"If",2,"Then",3, "Else",4, "for",5, "do",6,"while",7, "+",8,"-",9,"*",10,"/",11,";",12,"{",13,"}",14,"(",15,")",16,"<",17,"<=",18, "=",19,"!=",20, ">",21,">=",22, ":=",23, " ",24,"const",26 };;---------------------------识别标识符算法-------------------------- tokentype recogid(char ch){ tokentype tokenid;FILE *fs;int flag,fflag;char word[10]={0};int i,j;i=0;while(isalpha(ch)||isdigit(ch)){ word[i]=ch;ch=fgetc(fp);i=i+1;}ungetc(ch,fp);word[i]='\0';for(j=0;j<=8;j++){ flag=strcmp(word, s[j].symbol);if(flag==0) //是关键字{ tokenid.id=j;tokenid.entry=-1;break;} }if(flag!=0){ for(j=0;j<=k;j++){ fflag=strcmp(a[j].idname,word);if(fflag==0) //在符号表中可以找到{ tokenid.id=25;tokenid.entry=a[j].address;break;} }if(fflag!=0){ fs=fopen("symbol.txt","a"); //符号表中不存在的标识符 strcpy(a[k].idname, word);a[k].address=k;a[k].type=25;tokenid.id=25;tokenid.entry=k;for(j=0;j<9;j++)fprintf(fs,"%c",word[j]);fprintf(fs,"%c",'\t');fprintf(fs,"%d",a[k].address);fprintf(fs,"%c",'\t');fprintf(fs,"%d",a[k].type);fprintf(fs,"%c",'\n');fclose(fs);k=k+1;} }strcpy(tokenid.idname, word);//自行添加的return tokenid;};-----------------------------识别数字函数-------------------------- tokentype recogdig(char ch){ int flag;int i=0,j;int num=0;tokentype tokenid;while(isdigit(ch)){ num=(ch-48)+num*10;ch=fgetc(fp);i=i+1;}for(j=0;j<=t;j++)if(d[j].num==num){ flag=1;tokenid.id=26;tokenid.entry=d[j].address;break;}if(flag!=1){ d[t].num=num;d[t].address=t;tokenid.id=26;tokenid.entry=t;t=t+1;}sprintf(tokenid.idname, "%d", num);//int>>charreturn tokenid;};------------------------识别算符和界符函数------------------------- tokentype recogdel(char ch){ tokentype tokenid;switch(ch){ case'{':{ tokenid.id=13;strcpy(tokenid.idname, "{");//自行添加的}break;case'}':{ tokenid.id=14;strcpy(tokenid.idname, "}");}break;case';':{ tokenid.id=12;strcpy(tokenid.idname, ";");}break;case'=':{ tokenid.id=19;strcpy(tokenid.idname, "=");}break;case':':ch=fgetc(fp);if(ch=='=') tokenid.id=23; break;case'!':{ ch=fgetc(fp);if(ch=='=') tokenid.id=20;strcpy(tokenid.idname, "!="); } break;case'<':{ch=fgetc(fp);if(ch=='='){ tokenid.id=18;strcpy(tokenid.idname, "<=");}else{ tokenid.id=17;strcpy(tokenid.idname, "<");ungetc(ch,fp);}}; break;case'>':ch=fgetc(fp);if(ch=='='){tokenid.id=22;strcpy(tokenid.idname, ">=");}else { tokenid.id=21;strcpy(tokenid.idname, ">");ungetc(ch,fp);}; break;case'+':{ tokenid.id=8;strcpy(tokenid.idname, "+");}break;case'*':{ tokenid.id=10;strcpy(tokenid.idname, "*");}break;case'(':{ tokenid.id=15;strcpy(tokenid.idname, "(");}break;case')':{ tokenid.id=16;strcpy(tokenid.idname, ")");}break;}tokenid.entry=-1;return tokenid;};---------------------------handlecom函数--------------------------- tokentype handlecom(char ch){ tokentype tokenid;char ch1;int flag=0;if(ch!='*' ){ tokenid.id=25;tokenid.entry=-1;}else{ while(flag==0){ ch1=ch;ch=fgetc(fp);if((ch1='*')&&(ch='/'))flag=1;}}return tokenid;};---------------------------sort函数---------------------------- void sort(char ch){struct tokentype tokenword;FILE * fq = fopen("tokenfile.txt","a");if(isalpha(ch))tokenword=recogid(ch); //字母else if(isdigit(ch))tokenword=recogdig(ch); //数字else if(ch=='/')tokenword=handlecom(ch);elsetokenword=recogdel(ch);printf("%s\t%d\t%d\n",tokenword.idname,tokenword.id,tokenword.entry) ;fprintf(fq,"%d",tokenword.id);fprintf(fq,"%c",'\t');fprintf(fq,"%d",tokenword.entry);fprintf(fq,"%c",'\n');fclose(fq);};--------------------------scanner函数---------------------------- void scanner(){ char ch;fp=fopen("source.txt","r");ch=getc(fp);while(ch!=EOF){ if(!isspace(ch)){ sort(ch);}ch=fgetc(fp);}fclose(fp);};------------------------------主函数------------------------------ int main(){ int i;printf("输出token字如下:\n");printf("idname\ttype\taddress\n");scanner();printf("************************************\n");printf("输出符号表如下:\n");printf("%s\t%s\t%s\n","idname","address","type");for(i=0;i<=k-1;i++)printf("%s\t%d\t%d\n",a[i].idname,a[i].address,a[i].type);printf("************************************\n"); printf("输出常数表如下:\n");printf("%s\t%s\n","num","address");for(i=0;i<=t-1;i++)printf("%d\t%d\n",d[i].num,d[i].address);printf("\n\n");system("pause");}八.程序测试Source源文件程序截图main(){If a!=35end;do whileend;36}九.实验小结子集构造法的基本思想是构造得到的DFA的每个状态对应于NFA的一个状态集合。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

2.3 正规表达式与优先自动机简介
2.3.2:有限自动机 – 1、确定有限自动机(DFA): • DFA是一个五元组,Md= (S, ∑, f, s0 , Z) ,其中: (1) S是一个有限状态集合,它的每个元素称为一个状态 (2) ∑是一个有穷字母表,它的每个元素称为一个输入字符 (3)f是一个从S×∑至S的单值映射,也叫状态转移函数 (4)s0∈S 是唯一的初态 (5) Z S 是一个终态集
2.3 正规表达式与优先自动机简介
2.3.2:有限自动机
– 2、非确定有限自动机(例2.5):
假定NFA Mn =({s0, s1, s2},{a,b}, f , {s0 ,s2},{s2}),状态转移函数:
f(s0, a) ={s2 } f(s0, b) ={s0,s2 } f(s1, a) = Ф
r2Leabharlann sisksj
ε
si
sk
ε sj
r1
2.4 正规表达式到有限自动机的构造 例2.6 对给定正规表达式 b*(d|ad)(b|ab)+ 构造其NFA M [解答] 先用R+=RR*改造正规表达式
b*(d|ad)(b|ab)+ = b*(d|ad)(b|ab)(b|ab)* 按照正规式从左到右构造NFA:
b
d
b
b
ε
ε
X1 2
4
ε
ε
6
8
Y
a
da
b
3
5
ab 7
2.4 正规表达式到有限自动机的构造
2.4.2:NFA的确定化(相关概念) – NFA的确定化:构造一个和NFA等价的DFA – 状态集合I的ε_闭包 • 设I是FA M的状态子集,则以下状态属于ε_CLOSURE(I) : (1) 若si∈I,则si∈ ε_CLOSURE(I) ; (2) 若si∈I,则对从si出发经过任意条ε通路所能到达的 状态sj,都有sj ∈ ε_CLOSURE(I) 。 – 定义Ia = ε_CLOSURE(J) ,其中: I={s1, s2,…, sn},J = f(I,a) = f(s1,a)∪f(s2,a)∪… ∪ f(sn,a)
(1) S是一个有限状态集合,它的每个元素称为一个状态 (2) ∑是一个有穷字母表,它的每个元素称为一个输入字符
(3) f是一个从S×∑*至S的多值映射,也叫状态转移函数
(4) Q∈S 是非空初态集
(5) Z S 是一个终态集
• NFA相比于DFA的特征:
(1)若干个初始状态
(2) f多值映射
(3) 允许接收字和空字符ε
f(s1, b) ={s2 } f(s2, a) = Ф
f(s2, b) ={ s1 }
状态转换图: b
s0 bb
a
s1 b
s2
状态转换矩阵:

f
a
b
s0 {s2} {s0,s2} S s1 Ф {s2}
s2 Ф {s1}
2.3 正规表达式与优先自动机简介
2.3.2:有限自动机(识别的语言) – 对于一个自动机FA 而言,如果存在一条从初始状态到终止状 态的通路,通路上有向边所识别的字符依次连接所得到的字 符串为α, 则称α可以为FA 所接受或者α为FA 所识别 – FA 所能识别的字符串集为FA 所识别的语言,记为L(M) – FA的等价:对于任意两个FA M和 FA M’, 如果 L(M)=L(M’), 则称M和M’等价 – 对于任意一个NFA M,一定存在一个DFA M’与其等价
2.4 正规表达式到有限自动机的构造
2.4.1:由正规式构造等价的NFA
R
– 1、对于给定的正规式R,将其表示成 X
Y
称为“拓广转换图”其中X为初始状态,Y为终止状态
– 2、对正规式中的三种运算,分别采用如下的对应转换规则
r1|r2
si
sj
r1
si
r2 sj
si r1r2 sj
r1*
si
sj
r1
2.3 正规表达式与优先自动机简介
2.3.2:有限自动机
– 1、确定有限自动机(例2.4):
假定DFA Md =({s0, s1, s2},{a,b}, f , s0 ,{s2} ),状态转移函数:
f(s0, a) = s1 f(s1, b) = s2
f(s0, b) = s2 f(s2, a) = s2
2.3 正规表达式与优先自动机简介
2.3.2:有限自动机:可以自动识别单词的机器 – 有限自动机(Finite Automation): • FA是一个状态转换图,“有限”指的是状态有限。当前状 态读入一个字符后,和后继状态的转换有以下三种情形: (1)后继状态为自身 (2)后继状态只有一个 (3)后继状态有多个 • 如果每次转换的后继状态是唯一的,则称它为确定有限自 动机(Deterministic FA) • 如果每次转换的后继状态不是唯一的,则称它为非确定有 限自动机(Nondeterministic FA)
西北农林科技大学本科教程
第3 讲
主讲教师:赵建邦
本讲目标
第二章《词法分析》2.3-2.5节 2.3 正规表达式与有限自动机简介 2.4 正规表达式到优先自动机的构造 2.5 词法分析器的自动生成
重点掌握 有限自动机理论 有限自动机的构造、确定化和化简
第二章 词法分析
2.1 词法分析的设计方法 2.2 一个简单的词法分析器 2.3 正规表达式与有限自动机简介 2.4 正规表达式到有限自动机的构造 2.5 词法分析器的自动生成
f(s1, a) = s1 f(s2, b) = s1
状态转换图:
a s0
b
b
a s1
b s2
a
状态转换矩阵:

f
ab
s0 S s1
s2
s1 s2 s1 s2 s2 s1
2.3 正规表达式与优先自动机简介
2.3.2:有限自动机
– 2、非确定有限自动机(NFA):
• NFA是一个五元组,Md= (S, ∑, f, Q, Z) ,其中:
2.3 课堂例题
例2.5 接受与正规式(a|b) *abb相同的语言的DFA与NFA:
DFA: a
a
s1
b
a
b
s0
a
s2
b
s3
b
NFA:
a
a
a
b
s0
s1
s2
s3
b
第二章 词法分析
2.1 词法分析的设计方法 2.2 一个简单的词法分析器 2.3 正规表达式与有限自动机简介 2.4 正规表达式到有限自动机的构造 2.5 词法分析器的自动生成
2.4 正规表达式到有限自动机的构造(重点) 需要了解的等价性:
– 1.如果R是字母表Σ上的一个正规式,则必然存在一个NFA M, 使得L(M)=L(R);
– 2.对于任意一个NFA M,一定存在一个DFA M’与其等价 , 即L(M)=L(M’);
从正规式开始构造DFA的过程有以下几个步骤: – 1.由正规式构造NFA; – 2.由NFA构造与之等价的DFA(确定化) – 3.DFA的化简
相关文档
最新文档