chomsky文法类型的判断.docx
《chomsky文法类型的判断.docx》由会员分享,可在线阅读,更多相关《chomsky文法类型的判断.docx(17页珍藏版)》请在冰豆网上搜索。
chomsky文法类型的判断
编译原理实验报告
实验名称Chomsky文法类型判断
实验时间2014-4-2
院系计算机科学与技术学院
班级2011级科技(3)班
学号E01114375
姓名张练钢
1.实验目的
(1)通过实验进一步理解chomsky文法类型判断的的依据,理解每个类型文法的特点。
(2)进一步理解4种文法类型之间的包含关系。
(3)体会这种理论对于计算机科学发展的深刻影响,特别是对程序设计语言的设计、编译方法和计算复杂性等方面的重大作用。
通过上机实现文法类型的自动判别。
2.实验原理
1.0型文法(短语文法)
如果对于某文法G,P中的每个规则具有下列形式:
u:
:
=v
其中u∈V+,v∈V*,则称该文法G为0型文法或短语文法,简写为PSG。
0型文法或短语结构文法的相应语言称为0型语言或短语结构语言L0。
这种文法由于没有其他任何限制,因此0型文法也称为无限制文法,其相应的语言称为无限制性语言。
任何0型语言都是递归可枚举的,故0型语言又称递归可枚举集。
这种语言可由图灵机(Turning)来识别。
2.1型文法(上下文有关文法)
如果对于某文法G,P中的每个规则具有下列形式:
xUy:
:
=xuy
其中U∈VN;u∈V+;x,y∈V*,则称该文法G为1型文法或上下文有关文法,也称上下文敏感文法,简写为CSG。
1型文法的规则左部的U和右部的u具有相同的上文x和下文y,利用该规则进行推导时,要用u替换U,必须在前面有x和后面有y的情况下才能进行,显示了上下文有关的特性。
1型文法所确定的语言为1型语言L1,1型语言可由线性有界自动机来识别。
3.2型文法(上下文无关文法)
如果对于某文法G,P中的每个规则具有下列形式:
U:
:
=u
其中U∈VN;u∈V+,则称该文法G为2型文法或上下文无关文法,简写为CFG。
按照这条规则,对于上下文无关文法,利用该规则进行推导时,无需考虑非终结符U所在的上下文,总能用u替换U,或者将u归约为U,显示了上下文无关的特点。
2型文法所确定的语言为2型语言L2,2型语言可由非确定的下推自动机来识别。
一般定义程序设计语言的文法是上下文无关的。
如C语言便是如此。
因此,上下文无关文法及相应语言引起了人们较大的兴趣与重视。
4.3型文法(正则文法,线性文法)
如果对于某文法G,P中的每个规则具有下列形式:
U:
:
=T或U:
:
=WT
其中T∈VT;U,W∈VN,则称该文法G为左线性文法。
如果对于某文法G,P中的每个规则具有下列形式:
U:
:
=T或U:
:
=TW
其中T∈VT;U,W∈VN,则称该文法G为右线性文法。
左线性文法和右线性文法通称为3型文法或正则文法,有时又称为有穷状态文法,简写为RG。
按照定义,对于正则文法应用规则时,单个非终结符号只能被替换为单个终结符号,或被替换为单个非终结符号加上单个终结符号,或者被替换为单个终结符号加上单个非终结符号。
3型文法所确定的语言为3型语言L3,3型语言可由确定的有限状态自动机来识别。
在常见的程序设计语言中,多数与词法有关的文法属于3型文法。
可以看出,上述4类文法,从0型到3型,产生式限制越来越强,其后一类都是前一类的子集,而描述语言的功能越来越弱,四类文法及其表示的语言之间的关系可表示为:
0型
1型
2型
3型;即L0
L1
L2
L
3..实验内容
(1)理解四种文法类型的特点,并利用他们之间包含关系0型
1型
2型
3型;即L0
L1
L2
L对所属类型作出判断。
(2)通过编程自动实现将输入的文法判断出其所属类型。
4.实验心得
本实验的上机实现需注意一下几点:
(1)数据的表示,利用structcon{
stringfront;
stringend;
};//定义每个产生式的结构如A:
:
=a则front=A,end=a;
因为每个文法都有多个产生式,我们将这多个文法依次存入一个string类型的test数组中,然后再将每个产生式分解成前端和后端的格式以便于分析每个产生式所属的类型。
(2)在对文法进行判断前先对每个产生式作出判断,那么所有产生式中文法类型最低的那个产生式所属的类型即为该文法所属的类型。
(3)在对每个每个产生的类型做出判断时要充分利用四种文法类型之间的包含关系以简化程序。
如3型文法和2型文法的产生前端都为一个非终端符我们可以先利用这个特点先判断一个产生式是否属于3型文法或2型文法,如果不符合以上条件然后在判断其是否属于1型或0型文法。
(4)在代码的编写过程中注意代码的结构以方便阅读。
5.实验代码与结果
/*作者:
张练钢(E01114375)
完成时间:
2014-4-5
程序任务:
chomsky文法类型的判断
运行环境:
vc++6.0
*/
#include
#include
#include
usingnamespacestd;
structcon{
stringfront;
stringend;
};//定义每个产生式的结构如A:
:
=a则front=A,end=a;
stringVNT;//非终端符集合
stringVT;//终端符集合
voiddecompose(strings,con&res)
{//该函数负责将输入的每个产生式转换成con结构如A:
:
=a则front=A,end=a;
intflag1=0,flag2=0;
for(inti=0;i{
if(s[i]==':
')
{
flag1=i;
}
elseif(s[i]=='=')
{
flag2=i;
}
}
res.front=s.substr(0,flag1-1);
res.end=s.substr(flag2+1,s.size()-1);
}
boolisBelongToVNT(chars)
{//判断一个字符是否属于非终端字符
for(inti=0;i{
if(VNT[i]==s)
return1;
}
return0;
}
boolisBelongToVT(chars)
{//判断一个字符是否属于终端字符
for(inti=0;i{
if(VT[i]==s)
return1;
}
return0;
}
boolisBelongToV(chars)
{//判断一个字符是否属于VNTUNT
stringtem=VNT+VT;//因为终端符和非终端符没有交集所以两个字符串直接连接的结果即为VNTUNT
for(inti=0;i{
if(tem[i]==s)
return1;
}
return0;
}
intjudgeTypeOfP(consen)
{//判断每个产生式的类型
intflag=0;
for(inti=0;i{
if(isBelongToV(sen.front[i])==0)//如果产生式前端中含有非V中的元素则不属于任何文法类型
{
flag=1;
break;
}
}
if(flag==1)
{
return-1;
}
flag=0;
for(i=0;i{
if(isBelongToV(sen.end[i])==0&&sen.end[i]!
='e')//如果产生式后端端中含有非V中的元素(空‘e’除外)则不属于任何文法类型
{
flag=1;
break;
}
}
if(flag==1)
{
return-1;
}
if(sen.front.size()==1)
{//若产生式的前端是一个非终端符则判断其是2型文法还是3型文法
chartem=sen.front[0];
if(isBelongToVNT(tem))
{//如果front为非终端符则先判断该产生式是不是正规文法或2型文法的结构
if(sen.end.size()==1)
{
if(isBelongToVT(sen.end[0]))//如果是A:
:
=a则属于正规文法
return3;
else
return2;//因为该产生式的前端是非终端字符所以满足2型文法的要求已经包含S:
:
=e(e为空)
}
elseif(sen.end.size()==2)
{
if(isBelongToVNT(sen.end[1])&&isBelongToVT(sen.end[0]))//如果是A:
:
=aB则属于正规文法
{
return3;
}
else
return2;
}//elseif(sen.end.size()==2)
}//if(isBelongToVNT(tem))
else
{
return-1;//如果产生的前端没有非终端符则不符合任何类型的文法
}
}//if(sen.front.size()==1)
else
{
intflag=0;
for(inti=0;i{
if(isBelongToVNT(sen.front[i]))//先判断其是否含有非终端符,如果没有则不符合任何文法类型
{
flag=1;
break;
}
}
if(flag==0)
{
return-1;
}
else
{
if(sen.end.size()>=sen.front.size())//如果产生式α->β满足|β|>=|α|则符合1型文法的要求,否则就是零型文法
return1;
else
return0;
}
}
}
voidjudge(intres[100],intcount)
{//根据每个产生式的类型判断文法的类型
intj,flag=1;
switch(res[0])
{
case3:
for(j=0;j{
if(res[j]<3)
{
flag=0;
break;
}
}
if(flag==1)
{
cout<<"这是3型文法"<break;
}
case2:
flag=1;
for(j=0;j{
if(res[j]<2)
{
flag=0;
break;
}
}
if(flag==1)
{
cout<<"这是2型文法"<break;
}
case1:
flag=1;
for(j=0;j{
if(res[j]<1)
{
flag=0;
break;
}
}
if(flag==1)
{
cout<<"这是1型文法"<break;
}
case0:
flag=1;
for(j=0;j{
if(res[j]<0)
{
flag=0;
break;
}
}
if(flag==1)
{
cout<<"这是0型文法"<break;
}
default:
cout<<"这不是任何类型的文法"<}
}
intmain()
{
intcount=0;//记录输入产生式的个数
stringtest[100];//存放每个文法的产生式
chartem[100];//临时输入的字符串
intres[100];//用于存放每个产生式的判别结果
cout<<"请先输入非终端符:
"<cin>>tem;
VNT=tem;
cout<<"请输入终端符号"<cin>>tem;
VT=tem;
cout<<"请输入产生式:
最后一条产生式以EOF结束"<while(cin>>tem)
{
test[count++]=tem;
}
for(inti=0;i{
cons;
decompose(test[i],s);
res[i]=judgeTypeOfP(s);//对每个产生式的类型做出判断
}
judge(res,count);//对文法类型作出判断
count=0;
return0;
}
结果:
(1)0型文法:
(2)1型文法
(3)2型文法
(4)3型文法
(5)如果产生式的前端或后端不属于V则不属于任何文法类型
(6)如果产生的前端不含有非终端符则不属于任何文法类型