编译原理实验三正规文法到正规式的转换.docx
《编译原理实验三正规文法到正规式的转换.docx》由会员分享,可在线阅读,更多相关《编译原理实验三正规文法到正规式的转换.docx(14页珍藏版)》请在冰豆网上搜索。
编译原理实验三正规文法到正规式的转换
实验三:
正规文法到正规式的转换
一:
要求
输入任意的正规文法,输出相应的正规式
二:
实验目的
1.熟练掌握正规文法到正规式的转换规则
2.理解正规文法和正规式的等价性
三:
实验原理
1.一个正规语言可以由正规文法定义,也可以由正规式定义,对任意一个正规文法,存在一个定义同一个语言的正规式,反之,对每个正规式,存在生成同一个语言的正规文法
2正规文法与正规式的转换规则:
1.A-〉xB,B->y则:
A=xy
2.A-〉xA,A->y则:
A-〉x*y
3.A-〉x,A-〉y则:
A=x|y
四:
数据结构与算法
structChomsky
{
stringleft;
stringright;
};
voidapart(Chomsky*p,inti)//分开产生式左右部
voidVNVT(Chomsky*p)//求VN和VT
intzero(Chomsky*p)//0型文法
intone(Chomsky*p)//1型文法
inttwo(Chomsky*p)//2型文法
intthree(Chomsky*p)//3型文法
voidchange(Chomsky*p)//正规文法到正规式的转换函数
五:
出错分析
1:
#include忽视了c++语言中的头文件应当去掉.h,须再另加上usingnamespacestd;
2:
规则分解不对,导致结果出错。
3:
太多循环嵌套容易造成程序出错,养成把括号提前打好的习惯。
六:
实验结果与分析
不是正规文法的不能转换:
是正规文法的才可以转换:
七:
源代码
#include
#include
usingnamespacestd;
#definemax50
intNONE=1;
stringstrings,noend,end;//非终结符与终结符存储
intn;//产生式总数
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)
{
return1;//属于2型文法
}
else
return0;
}
intthree(Chomsky*p)//3型文法
{
intflag=0;
inti;
if(two(p))
{
for(i=0;iif(!
(p[i].right.length()==1||p[i].right.length()==2)||(p[i].right[0]>='A'&&p[i].right[0]<='Z'))//右部字符个数不是1或2,或首字符是非终结符
{
flag++;
break;
}
else
if((p[i].right.length()==2)&&!
(p[i].right[1]>='A'&&p[i].right[1]<='Z'))//第二个字符不是非终结符
{
flag++;
break;
}
}
else
flag--;
if(flag>0)
{
cout<<"此文法属于2型文法,即上下文无关文法。
"<i=n;
return0;
}
else
if(flag==0)
{
cout<<"此文法属于3型文法,即正规文法。
"<return1;
}
else
return0;
}
voidchange(Chomsky*p)//正规文法到正规式的转换函数
{
inti,j,m,flag;//合并产生式
for(i=0;ifor(j=i+1;j{
if((p[i].left==p[j].left)&&(p[i].right[1]==p[j].right[1]))
{
if(p[i].right[1]==p[j].right[1]&&p[i].left[0]==p[j].right[1])//合并形如A->aA,A->bA的产生式为A->aA|bA的形式
{
p[i].right=p[i].right+"|"+p[j].right;
p[j].left="";
p[j].right="";
}
else
if(p[i].right[1]==p[j].right[1]&&p[i].left[0]!
=p[j].right[1])//合并形如S->aA,S->bA的产生式为S->aA|bA的形式
{
p[i].right=p[i].right+"|"+p[j].right;
p[j].left="";
p[j].right="";
}
}
if(p[i].right.length()==1&&p[j].right.length()==1&&p[i].left==p[j].left)//合并形如S->a,S->b,S->c的产生式为S->a|b|c的形式
{
p[i].right=p[i].right+"|"+p[j].right;
p[j].left="";
p[j].right="";
}
}
for(i=0;iaA|bA的公因式为S->(a|b)A的形式
{
flag=p[i].right.length();
if(p[i].right.length()>2&&'A'<=p[i].right[1]&&p[i].right[1]<='Z'&&p[i].right[2]=='|')
{
for(j=1;j{
p[i].right[j]='';
}
if(j==flag-1)
p[i].right="("+p[i].right.substr(0,p[i].right.length()-1)+")"+p[i].right.substr(p[i].right.length()-1);
}
}
for(i=0;i{
if(p[i].left[0]==p[i].right[p[i].right.length()-1]&&p[i].right.length()>1)
{
for(j=0;jif(p[i].left==p[j].left&&j!
=i)
{
for(m=0;m
if('A'<=p[j].right[m]&&p[j].right[m]<='Z')break;
if(m==p[j].right.length())
{
p[i].right=p[i].right.substr(0,p[i].right.length()-1)+"*"+"("+p[j].right+")";
p[j].right="";
p[j].left="";
}
}
}
}
flag=n;
while(flag>=0)//当所有产生式的右部均为终结符构成时停止转换
for(i=0,flag=flag-1;ifor(j=0;j
if('A'<=p[i].right[j]&&p[i].right[j]<='Z')
{
for(m=0;m{
if(p[m].left[0]==p[i].right[j]&&m!
=i)
{
p[i].right=p[i].right.substr(0,j)+p[m].right+p[i].right.substr(j+1);
p[m].left="";
p[m].right="";
break;
}
}
}
//再次合并左部相等的产生式
for(i=0;ifor(j=0;j{
if(p[i].left[0]==p[j].left[0]&&i!
=j)
{
if(p[j].right.length()>1)
{
p[i].right=p[i].right+"|"+"("+p[j].right+")";
p[j].left="";
p[j].right="";
}
else
{
p[i].right=p[i].right+"|"+p[j].right;
p[j].left="";
p[j].right="";
}
}
}
}
voidmain()
{
inti,j;
cout<<"....................编译原理实验三:
正规文法到正规式的转换...................."<cout<<"请输入正规文法(三型文法)的产生式总数及各产生式:
"<cin>>n;
Chomsky*p=newChomsky[max];
for(i=0;i{
cin>>strings;
apart(p,i);
}
VNVT(p);
if(three(p))//只有当输入为正规文法时才进行转换,否则实验退出!
!
{
cout<<"转换后的正规式为:
"<change(p);
for(i=0;i{
if(p[i].left[0]!
=NULL)
{
cout<
for(j=0;j
{
if(p[i].right[j]!
='')
cout<
}
}
}
}
else
cout<<"该文法不属于正规文法,实验结束!
!
"<}