编译原理实验1Chomsky文法类型判断.docx
《编译原理实验1Chomsky文法类型判断.docx》由会员分享,可在线阅读,更多相关《编译原理实验1Chomsky文法类型判断.docx(12页珍藏版)》请在冰豆网上搜索。
![编译原理实验1Chomsky文法类型判断.docx](https://file1.bdocx.com/fileroot1/2023-7/9/b18bc0f3-3650-460c-8bf2-5c41d843f2fe/b18bc0f3-3650-460c-8bf2-5c41d843f2fe1.gif)
编译原理实验1Chomsky文法类型判断
编译原理实验报告
实验名称Chomsky文法类型判断
实验时间2014年4月2日
院系计算机科学与技术学院
班级科技
(2)班
学号E01114174
姓名徐帅
1.试验目的
输入:
一组任意的规则。
输出:
相应的Chomsky文法的类型。
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
L3
3..实验内容
该实验用C++进行编译,利用函数功能,调用不同的函数来判定0型文法,1型文法,2型文法,3型文法的判断。
主要提高我们对文法类型的理解,也提高了我们编程的动手能力.理论与实践结合,加深对文法概念的理解.
3.实验心得
1.明确四种文法的定义,根据文法定义的不同,利用程序将其区分开
2.事先画好实验的流程图,可以帮助解决问题
5.实验代码与结果
#include
#include
usingnamespacestd;
intm;//文法产生式的个数
charVn[100];//记录非终结字符
charVt[100];//记录终结字符
typedefstructGZ//定义一个产生式结构体
{
stringleft;//定义产生式的左部
stringright;//定义产生式的右部
stringwhole;//定义整个产生式
}GZ;
boolwenfa0(GZ*p)//判断0型文法
{
inti,j;
for(i=0;i{
for(j=0;j
{
if((p[i].left[j]>='A')&&(p[i].left[j]<='Z'))//判断产生式左边是否含有非终结符
break;
}
if(j==p[i].left.length())
break;
else
continue;
}
if(i==m)
return1;//说明该文法是0型
else
{
cout<<"该文法不是0型文法!
"<return0;
}
}
boolwenfa1(GZ*p)//判断1型文法
{
inti;
if(wenfa0(p))
{
for(i=0;i{
if(p[i].right.length()>=p[i].left.length())//判断产生式右边是否大于左边
continue;
else
break;
}
if(i==m)
return1;//说明该文法是1型
else
{
cout<<"该文法是0型文法!
"<return0;
}
}
else
return0;
}
boolwenfa2(GZ*p)//判断2型文法
{
inti;
if(wenfa1(p))
{
for(i=0;i{
if(p[i].left.length()==1&&(p[i].left[0]>'A'&&p[i].left[0]<'Z'))
continue;
else
break;
}
if(i==m)
return1;//说明该文法是2型
else
{
cout<<"该文法是1型文法!
"<return0;
}
}
else
return0;
}
boolwenfa3(GZ*p)//判断3型文法
{
inti;
if(wenfa2(p))
{
for(i=0;i{
if((p[i].right[0]>='a'&&p[i].right[0]<='z')&&p[i].right.length()>=1&&p[i].right.length()<=2)//判断产生式右边第一个字符是否是终结符以及规定左边的字符个数为1或2
if((p[i].right.length()==2)&&(p[i].right[1]>='a'&&p[i].right[1]<='z'))
break;
else
continue;
else
break;
}
if(i==m)
{
cout<<"该文法是3型文法!
"<return1;
}
else
{
cout<<"该文法是2型文法!
"<return0;
}
}
else
return0;
}
voidoutput(GZ*p)//输出终结符和非终结符
{
inti,j,k;
intvn=0;//记录非终结字符个数
intvt=0;//记录终结字符个数
for(i=0;i{
for(j=0;j
{
if(p[i].whole[j]>='A'&&p[i].whole[j]<='Z')//判断字符是否为非终结字符
{
for(k=0;k<=vn;k++)//遍历整个非终结符集合,判断是否有重复
{
if(Vn[k]==p[i].whole[j])
break;
else
continue;
}
if(k>vn)//说明没有重复
{
Vn[vn]=p[i].whole[j];
vn++;
}
}
if(p[i].whole[j]>='a'&&p[i].whole[j]<='z')//判断字符是否为非终结字符
{
for(k=0;k<=vt;k++)//遍历整个非终结符集合,判断是否有重复
{
if(Vt[k]==p[i].whole[j])
break;
else
continue;
}
if(k>vt)//说明没有重复
{
Vt[vt]=p[i].whole[j];
vt++;
}
}
}
}
cout<<"\n";
cout<<"非终结符为:
\n";
for(i=0;icout<cout<<"\n";
cout<<"\n";
cout<<"终结符为:
\n";
for(i=0;icout<cout<<"\n";
}
voidmain()
{
inti,j;
stringin;//记录输入的产生式
cout<<"请输入文法产生式的个数!
\n";
cin>>m;
GZ*p=newGZ[m];
cout<<"请再输入文法规则:
\n";
for(i=0;i{
cin>>in;
for(j=0;j{
if(in[j]=='-')
{
p[i].left=in.substr(0,j);
p[i].right=in.substr(j+2,in.length()-j-2);
p[i].whole=in.substr(0,in.length());
}
}
}
wenfa3(p);
output(p);
}
6.运行结果
输入文法个数为:
3
文法规则为:
S->asD
D->deF
F->dd