DFA与NFAWord文档下载推荐.docx
- 文档编号:22500265
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:25
- 大小:441.70KB
DFA与NFAWord文档下载推荐.docx
《DFA与NFAWord文档下载推荐.docx》由会员分享,可在线阅读,更多相关《DFA与NFAWord文档下载推荐.docx(25页珍藏版)》请在冰豆网上搜索。
应用记号literal
在实际的编译器设计中,词法记号,一样用一个整形数字表示
词法记号的属性:
我们爱好用<
词法记号,属性>
那个二元组来描述一个词法单位,比如,关于源代码:
position:
=initial+rate*60
关于词法单位+,我们能够应用<
add_op,'
+'
>
来表示。
有些情形,加倍复杂一点,比如关于position,我们表示是如许的,<
id,指向符号表中的position元素的指针>
,具体来说应当是如许的,假定属性是一个字符串,那么id将指向如许一个字符串"
position\0"
,我们把存放那个字符串的处所叫做符号表。
有些时刻,属性是不须要的,比如:
=,表示赋值,我们能够应用<
assign_op,257>
如许的表示那个词法单位,只是那个显得有些多于,因为assign_op和词法单位是一对一的,也确实是assign_op只对应了:
=,因此额外信息(属性)就显得余外的了
词法缺点:
词法分析器是专门难(有些缺点照样能够检测)检测缺点的,因为词法分析器的目标是产生词法记号流,它没有才能去分析法度榜样构造,是以无法检测到和法度榜样构造有关的缺点,比如:
fi(a==b)
词法分析器可不能找到那个缺点,它认为fi是一个标识符,而不是一个关键字,只有在后面的时期中,那个缺点才会被发明,这是一个与法度榜样构造有关的缺点
词法分析器,只能检测到词法单位上的问题,比如12.ab,作为一个词法单位,却不没有对应的模式,那么确实是产生一个缺点。
2.正规式:
前面说过模式是一种规矩,为了应用,我们须要一种规范的方法来表达模式,这确实是正规式
1)串和说话
字符类(又叫字母表):
关于字符的有限集合
串:
字符类上字符的有穷序列,串那个概念,具体来说是,某个字符类上的串
串的长度:
串中字符的个数,比如串s=abc,那么串的长度为3,用|s|表示串的长度
空串:
用ε表示
说话:
某字符类上的串的集合,属于说话的串,成为说话的句子或字
比如:
{abc,a}这确实是一个说话,abc和a确实是句子。
别的空集也是属于说话
连接:
x是串,y是串,x和y连接,成果确实是xy那个串。
假如x是串,x^3为xxx。
关于x^n(n>
=0),x^0=ε
说话的运算(假定L和M是说话):
1.LUM={s|s属于L或者M},例如:
L={1,2}M={3,4}那么LUM={1,2,3,4}
2.LM={st|s属于L且t属于M},例如:
L={a,b}M={1,2}那么LM={a1,a2,b1,b2}
ML={1a,1b,2a,2b}
3.L^n=LLL...LLL(n个L),例如:
L={a,b}那么L^3={aaa,aab,aba,abb,baa,bab,bbb,bba}
留意n可认为0,L^0={ε}
4.L*=L^0UL^1UL^2UL^3U...
L*表示,说话L中,所有的句子(串)以随便率性数量随便率性次序构成的句子的集合,包含ε,例如:
{a,b}*={ε,a,b,ab,ba,aab,aba,baa,bba,bab,abb,aaa,bbb...}
L*叫做L的闭包
5.L+=L^1UL^2UL^3U...
L+表示,说话L中,所有的句子(串)以随便率性数量随便率性次序构成的句子的集合,然则不包含ε
L+中的句子和L*中的句子比拟少一个ε
那么,我们经由过程上面的常识就能够表示一个标识符了,我们明白一样说话规定标识符是由字母开首,后接若干个字母或数字,我们能够如许来表示:
L={a-zA-Z}N={0-9},那么标识符确实是L(LUN)*
2)正规式
正规式又叫正规表达式,正规式是模式得一种规范的表达情势,正规式描述了一个集合,那个集合是由串构成的,事实上那个集合确实是我们前面说过的说话,只是那个地点大年夜家爱好应用正规集那个术语。
正规式r表示正规集L(r)
正规式的运算:
1.闭包运算,运算优先级最高,(r)*表示(L(r))*
2.连接运算,运算优先集合低于闭包,(r)(s)表示(L(r))(L(s))
3.或运算,运算优先集合最低,(r)|(s)表示(L(r))U(L(s))
例如:
a|b表示集合(说话,正规集){a,b}
(a|b)(a|b)表示集合(说话,正规集){aa,ab,ba,bb}
a*表示由一切a字符构成的集合(说话,正规集),包含ε
(a|b)表示由a,b构成的集合(说话,正规集),包含ε
等价的正规式:
(a|b)=(b|a)
正规式的代数性质:
1.r|s=s|r
2.r|(s|t)=(r|s)|t
3.(rs)t=r(st)
4.r(s|t)=rs|rt
5.εr=r
6.r**=r*
7.r*=(r|ε)*
留意,rs!
=sr因为连接运确实是有次序的,记住并明白得2个最全然的运算:
a|b表示{a,b},ab表示{ab}
3.正规定义
我们能够应用名字->
正规式这种表示,来说明一个等价的代替,比如:
dight->
0|1|2|3|4|5|6|7|8|9
那个地点,我们就能够应用名字digit来代替后面的正规表达式
我们能够对某个串集进行正规定义,比如我们对标识符集合进行正规定义:
letter->
A|B|...|Z|a|b|...|z
id->
letter(letter|dight)*
请经由过程上面的例子明白得正规定义。
在我们表达正规表达式的时刻,能够应用一些符号使得表达简化
1)+,表示一个或者多个实力,比如,a+表示{a,aa,aaa,aaaa,...}。
差别一下*,他们的关系是那个地点r+=r*|ε
2)字符组,[abc]表示a|b|c,还能够如许表示[a-zA-Z]表示字母表中的字符
4.状况转换图
状况转换图是对词法分析器进行分析过程的描述,我们看一个确信关系运算的状况转化图:
1)图中圆圈表示状况
2)箭头叫做边。
X状况的边,一样指的是由X状况动身,指向其他状况的边
3)边上的符号叫做标记
若何来应用那个图?
假定输入字符串是<
=,那么辨认开端时,发明<
和状况0与状况1间的边上的标记一样,那么就进入1状况,下一个输入字符为=,将进入2状况,辨认停止,返回二元组<
relop,LE>
上图中2,3,4,5,7,8状况,他们表示辨认了一个关系运算符,那个状况叫做接收状况
状况4上面有一个*,表示说,输入指针须要回移。
所谓的输入指针,确实是指向输入字符串中现在被读入的字符的地位,4状况会多读取一个字符,因此须要回移,也确实是要留意的是,辨认完成之后,输入指针指向的是被辨认对象的最后一个字符,而不是待辨认对象的第一个字符,如许的规定在实现词法分析器时,是有必定的意义,举例说明:
输入字符串为:
a>
b
识其余时刻,从>
开端,读入下一个字符b时,进入4状况,那个时刻,输入指针指向b,这时刻须要回移
我们在须要回移的状况上加一个*
每个状况后面有一个return(relop,XX)那个是状况的行动,那个地点具体来说确实是返回一个二元组的行动,词法分析器分析的成果确实是获得二元组(词法记号和属性的二元组),那个二元组能够表示一个特定的字符串。
事实上上面的*,也是表示行动,也确实是输入指针回移的行动,我们能够看见,只有在接收状况才会有行动显现
对一门典范的说话来说状况可能有几百个
5.若何编写一个词法分析器
1)依照须要写出正规定义
2)依照正规定义画出转换图
3)依照转换图写出词法分析器
那个地点具体评论辩论面向过程的说话来实现一个词法分析器(比如c说话),同时重要评论辩论的是第3步
1)我们须要一个nextchar()函数,取得缓存中下一个等待分析的字符,那个函数完成年2个义务
1.
让输入指针向前移动一位
2.
返回输入指针指向的字符
2)定义一个变量token_beginning,在每个状况转换图开端的时刻,记录输入指针的地位,定义forward变量作为输入指针
3)状况转换图被实现成为代码之后,每个状况都有属于本身的一块代码,这些代码按次序完成以下工作:
读取一个字符,经由过程nextchar()函数
读取的字符(标记),假如它和当前状况的边上的标记雷同,那么状况将转换到边所指向的状况,具体实现只须要一个语句确实是state=xxx(xxx为目标状况);
假如当前状况的所有边的标记和那个读取字符不一样,那么表示没有找到token(词法记号),这时刻须要调用fail()函数
3.
fail()函数完成如许的功能:
a.指针回移,完成forward=token_beginning的操作b.找到恰当的开端状况(也确实是查找别的一个转换图的开端状况)。
假定所有的转换图都被测验测验过,同时无法匹配,这时刻会调用一个发明缺点的小法度榜样,来申报缺点
4.
请不要随便添加行动到各个状况所持有的代码中,应当以转换图中表示的行动为准
4)定义一个全局变量lexical_value,用于储存一个指针,那个指针由install_id()和install_num()两个函数中的一个返回
5)定义两个整形变量start,state,分别表示一个转换图的开端状况和当前的状况
6)nexttoken(),这是词法分析器的主法度榜样,能够说,我们经由过程调用nexttoken()就完成了词法分析,那个函数必定是如许的格局:
while
(1){
switch(state){
casexx:
...
caseyy:
default:
}
}
关于具体的设计那个地点就不说了,举例说明一个转换图若何转换成为法度榜样:
这是一个辨认浮点数的例子,看下面的代码:
#include<
stdio.h>
ctype.h>
string.h>
char*nexttoken();
charnextchar();
voidnext();
voidback();
char*gettoken();
charcbuf[]="
12.3*********klj12.2e2jj778"
;
intforward=-1;
intmain(){
while
(1){
printf("
%s\n"
nexttoken());
if(forward>
=strlen(cbuf)-1){
getchar();
return0;
intstate;
intstart;
char*nexttoken(){
charc;
state=12;
case12:
c=nextchar();
start=forward;
if(isdigit(c)){
state=13;
}else{
next();
break;
case13:
if(isdigit(c))
elseif(c=='
e'
||c=='
E'
)
state=16;
.'
)
state=14;
else
state=19;
case14:
state=15;
case15:
||c=='
case16:
state=18;
||c=='
-'
state=17;
case17:
case18:
case19:
back();
returngettoken();
charnextchar(){
forward++;
returncbuf[forward];
voidback(){
forward--;
voidnext(){
chartoken_buf[128];
char*gettoken(){
inti,j=0;
for(i=start;
i<
=forward;
i++){
token_buf[j++]=cbuf[i];
token_buf[j]='
\0'
returntoken_buf;
词法分析
(2)---NFA
假定一个输入符号(symbol),能够获得2个或者2个以上的可能状况,那么那个finiteautomaton确实是不确信的,反之确实是确信的。
这确实是一个不确信的无穷自念头,在symbola输入的时刻,无法确信状况应当转向0,照样1
不论是确信的finiteautomaton照样非确信的finiteautomaton,它们都能够精确的描述正规集(regularsets)
我们能够专门便利的把正规表达式(regularexpressions)转换成为不确信finiteautomaton
2.NFA(NondeterministicFiniteAutomaton)
非确信的无穷自念头,我们用NFA那个术语表示,它是一个数学模型(model):
一个关于状况的集合S
一个关于输入符号(inputsymbols)的集合Σ
函数move:
(状况,符号)->
P(S)
一个开端状况s0,是一个独一的状况
5.
一个停止(接收)状况集合F
留意,P(S),表示S的幂集。
在NFA中,inputsymbol可认为ε
转换函数(transitionfunction)的含义确实是,一个确信的状况差不多从那个状况动身的一条边的标签(符号symbol),能够确信它的下一个状况构成的集合,比如上图(那个转换图确实是NFA的一种表示方法),0状况,a符号,确信了一个状况的集合{0,1}
3.转换图(transitiongraph)的表示
我们明白,运算机是无法直截了当表示一个图,我们应当若何来表示一个转换图?
应用表格确实是一个最简单的方法,每行表示一个状况,每列表示一个inputsymbol,这种表格被叫做transtiontable(转换表)
能够说应用表格是最简单的表示方法,然则我们能够留意到在那个图中状况1和inputsymbola,是没有下一个状况的(空集合),也确实是,关于一个大年夜的状况图,我们可能花费大年夜量的空间,而个中空聚聚会会议消费许多空间,然则这种消费又不是必须的,因此,作为最简单的一种实现方法,却不是最优的
说话(language)被NFA定义成为一个inputstring的集合,而那个集合中的元素则是被NFA受接收的所有的字符串(那些能够从开端状况到某接收状况的inputstring)
至于储备的方法,能够尝尝邻接表。
留意,应用什么样的数据构造来储存NFA按情形不合而不合,在一些专门情形下,某些数据构造会变得专门便利应用,而换入其他情形,则弗成以应用了。
词法分析(3)---DFA
1.DFA(DeterministicFiniteautomaton)
DFA确实是确信的有限自念头,因为DFA和NFA关系紧密,我们经常须要把他们拿到一路来讲,NFA能够转化成为一个DFA,DFA依旧是一个数学model,它和NFA有以下差别
不存在ε-transition,也确实是说,不存在ε为inputsymbol的边
关于move函数,move:
(state,symbol)->
S,具体来说确实是,一个状况和一个特定的inputsymbol,可不能映射到2个不合的状况。
如许的成果是,每个状况,关于每个特定的inputsymbol,只有一条出边
下图确实是一个DFA:
接收说话(a|b)*ab,留意一下,接收说话(a|b)*ab的DFA我们前面见过,确实是这张图:
2.DFA的行动
我们用一个算法来仿照DFA的行动
s=s0;
c=nextchar();
while(c!
=EOF){
s=move(s,c);
if(s属于F)
return"
yes"
else
no"
词法分析(4)---NFA与DFA的转化
1.子集构造(SubsetConstruction)
这是一个转换NFA到DFA的算法。
我们明白NFA和DFA的差别最重要的确实是一个状况和一个inputsymbol是否能够或许确信一个状况的问题,关于NFA,它将确信一个组状况,而DFA将确信一个状况,是以,我们有一个专门好的方法确实是把NFA的状况集对应每个DFA的状况,这确实是subsetconstruction的思惟,只是这只是大年夜概泛泛而论,我们须要加倍明白的熟悉
1)NFA在任何一个inputsymbol下,映射的状况集(经由过程move函数,那个集合平日用T字母表示)应当被明白
2)必须包管1)中状况集都对应了DFA中的一个状况
具体算法:
Input:
一个NFAN
Output:
接收雷同说话的DFAD
Method:
为D构架一个transitiontable(转换表)Dtran,每个DFA的状况是一个NFA的状况集合(那个地点必定要留意前面说过的1)2)两点)。
我们定义一些操作:
s表示NFA的状况,T表示NFA的状况集合,a表示一个inputsymbol
ε-transition(ε转换)确实是说inputsymbol为ε时的transition(转换)
操作(operation)
描述(description)
ε-closure(s)
从NFA的状况s动身,只经由过程ε-transition达到的N
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- DFA NFA