编译原理实验二压缩文法的等价变换汇总.docx
《编译原理实验二压缩文法的等价变换汇总.docx》由会员分享,可在线阅读,更多相关《编译原理实验二压缩文法的等价变换汇总.docx(10页珍藏版)》请在冰豆网上搜索。
编译原理实验二压缩文法的等价变换汇总
实验二:
压缩文法的等价变换
一:
要求
输入:
任意的上下文无关文法
输出:
等价的压缩了的文法
要求:
除了可查看压缩了的文法,还可查看删除了哪些规则
二:
实验目的
了解文法的简化
三:
实验原理
删除文法中的有害规则和多余规则
有害规则:
若文法中有如U:
:
=U的规则,则这就是有害规则,它会引
起二义性,而无任何用处。
多余规则:
(1)某条规则U:
:
=u的左部非终结符U(U不是识别符号),不在任何其他规则右部出现,即所有的推导始终不会用到此规则。
【不可到达】
(2)在推导句子的过程中,一旦使用了该规则,将推不出任何终结符号串。
即该规则中含有推不出任何终结符号串的非终结符。
【不可终止】
四:
数据结构与算法
structChomsky
{
stringleft;
stringright;
};
voidapart(Chomsky*p,inti)//分开产生式左右部
voidVNVT(Chomsky*p)//求VN和VT
intzero(Chomsky*p)//0型文法
intone(Chomsky*p)//1型文法
inttwo(Chomsky*p)//2型文法
voidshanchu(Chomsky*p)//删除多余规则与有害规则
五:
出错分析
1:
变量重复定义导致了一些小错误
2:
程序太长{}缺少也导致了错误
3:
后面删除规则的程序出错了,没有调试成功。
六:
实验结果与分析
不是上下文无关文法的:
2型文法的压缩:
七:
源代码
#include
#include
usingnamespacestd;
#definemax50
intNONE=1;
intRELEFT=1;
stringstrings,noend,end;//非终结符与终结符存储
intn;//产生式总数
intflag;
structChomsky
{
stringleft;
stringright;
};
voidapart(Chomsky*p,inti)//分开产生式左右部
{
intj;
for(j=0;jif(strings[j]=='-')
{
p[i].left=strings.substr(0,j);
p[i].right=strings.substr(j+1,strings.length()-j);
}
}
voidVNVT(Chomsky*p)//求VN和VT
{
inti,j;
for(i=0;i{
for(j=0;j<(int)p[i].left.length();j++)
{
if((p[i].left[j]>='A'&&p[i].left[j]<='Z'))//非终结符判断
{
if(noend.find(p[i].left[j])>100)
noend+=p[i].left[j];
}
else
{
if(end.find(p[i].left[j])>100)
end+=p[i].left[j];
}
}
for(j=0;j<(int)p[i].right.length();j++)
{
if(!
(p[i].right[j]>='A'&&p[i].right[j]<='Z'))//终结符判断
{
if(end.find(p[i].right[j])>100)
end+=p[i].right[j];
}
else
{
if(noend.find(p[i].right[j])>100)
noend+=p[i].right[j];
}
}
}
}
intzero(Chomsky*p)//0型文法
{
intflag(0),count(0);
inti,j;
for(i=0;i{
for(j=0;j<(int)p[i].left.length();j++)
{
if(p[i].left[j]>='A'&&p[i].left[j]<='Z')//有否非终结符
flag++;
}
if(flag>0)
{
flag=0;
count++;
}
else
break;//左部没有非终结符,结束
}
if(count==n)
return1;//属于0型文法
else
{
cout<"<NONE=0;
return0;
}
}
intone(Chomsky*p)//1型文法
{
intflag(0);
inti;
if(zero(p))
{
for(i=0;i{
if(p[i].right.length()
{
flag++;
break;
}
}
}
else
flag--;
if(flag>0)
{
cout<"<return0;//不属于1型文法
}
else
if(flag==0)
return1;//属于1型文法
else
return0;
}
inttwo(Chomsky*p)//2型文法
{
intflag(0);
inti;
if(one(p))
{
for(i=0;iif((p[i].left.length()!
=1)||!
(p[i].left[0]>='A'&&p[i].left[0]<='Z'))//左部不属于一个字符或不属于非终结符
{
flag++;
break;
}
}
else
flag--;
if(flag>0)
{
cout<"<return0;//不属于2型文法
}
else
if(flag==0)
{
cout<<"次文法属于2型文法"<return1;//属于2型文法
}
else
return0;
}
voidshanchu(Chomsky*p)//删除多余规则与有害规则
{
if(two(p))
{
cout<<"此文法属于上下文无关文法,可进行文法压缩,实验继续"<inti,j;
for(i=0;i{
if(p[i].left.length()==p[i].right.length())
{
for(j=0;j<(int)p[i].left.length();j++)
{
if(p[i].left[j]!
=p[i].right[j])//不为有害规则
{
j--;
break;//次规则不是有害规则
}
}
if(j==p[i].left.length()-1)//此条规则为有害规则,删除
{
cout<<"删除此条有害规则"<
"<
n--;
}
}
}
for(intk=0;k<(int)noend.length();k++)//多余规则中不可到达的判断
{
for(i=0;i{
for(j=0;j<(int)p[i].right.length();j++)
{
if(noend[k]!
=p[i].right[j])
continue;
else
i--;break;
}
if(i==n-1)//此条规则为多余规则
{
for(i=0;i{
if(p[i].left[j]==noend[k]||p[i].right[j]==noend[k])
cout<<"删除此条多余规则"<
"<
n--;
}
}
}
}
for(k=0;k<(int)noend.length();k++)//多余规则中不可终止的判断
{
}
cout<<"压缩后的文法是:
"<for(i=0;i{
cout<
"<
}
}
else
cout<<"此文法不是上下文无关文法,实验结束"<}
voidmain()
{
inti;
cout<<"....................编译原理实验二:
压缩文法的等价变换...................."<cout<<"请输入产生式总数及各产生式:
"<cin>>n;
Chomsky*p=newChomsky[max];
for(i=0;i{
cin>>strings;
apart(p,i);
}
VNVT(p);
shanchu(p);
}