由正规则文法构造正规则式.docx
《由正规则文法构造正规则式.docx》由会员分享,可在线阅读,更多相关《由正规则文法构造正规则式.docx(13页珍藏版)》请在冰豆网上搜索。
![由正规则文法构造正规则式.docx](https://file1.bdocx.com/fileroot1/2023-4/16/66e1897a-4641-434c-a617-685feb7c6d0f/66e1897a-4641-434c-a617-685feb7c6d0f1.gif)
由正规则文法构造正规则式
由正规(则)文法构造正规(则)式
姓名:
学号:
指导老师:
时间:
一、实验目的:
了解三型文法,正则表达式和正则集的概念;了解正则表达式的性质以及正则表达式和正则文法之间的关系。
给出一个文法能判断其文法类型,并且能将一个正规文法转化为正规式。
二、实验内容:
判断文法是第几类文法,并将正规文法转化为正规式。
三、程序流程:
1.程序流程图
2.正规文法转为正规式流程图
四、实验代码:
#include
#include
usingnamespacestd;
structCSS
{
stringleft;//产生式左部
stringright;//产生式右部
};
boolIsZero(CSS*p,intn)//判断0型文法(左部不含非终结符则不是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())
{
cout<<"该文法不是0型文法"<returnfalse;
}
}
if(i==n)
returntrue;//如果每个产生式都能找到非终结符
}
boolIsFirst(CSS*p,intn)//判断1型文法(右边长度大于等于左边长度)
{
if(IsZero(p,n))//先判断是否是0型文法
{
inti;
for(i=0;i{
if((p[i].left.length()>p[i].right.length())&&p[i].right.length()!
=0)//判断产生式左部长度是否大于右部
break;
}
if(i==n)
returntrue;
cout<<"该文法是一个0型文法"<}
returnfalse;
}
boolIsSecond(CSS*p,intn)//判断2型文法(左部是一个非终结符)
{
inti;
if(IsFirst(p,n))//同上,先判断低级文法是否成立
{
for(i=0;i{
if((p[i].left.length()!
=1)||!
(p[i].left[0]>='A'&&p[i].left[0]<='Z'))//判断产生式左部长度是否为一,左部第一个是否是非终结符
break;
}
if(i==n)
returntrue;
cout<<"该文法是1型文法"<}
returnfalse;
}
boolIsThird(CSS*p,intn)//判断3型文法(形如A→a,A→aB的形式)
{
inti;
if(IsSecond(p,n))//同上,先判断是否是2型文法
{
for(i=0;i{
if((p[i].right.length()==0)||(p[i].right.length()>=3)||(p[i].right[0]>='A'&&p[i].right[0]<='Z'))//判断产生式右部字符个数是否是1或者2,判断右部第一个字符是否是非终结符
break;
}
if(i==n)
{
for(i=0;i{
if(p[i].right.length()==2)//如果右边长度为2,则判断第二个字符是否是非终结符
{
if(!
(p[i].right[1]>='A'&&p[i].right[1]<='Z'))
break;
}
}
if(i==n)
{
cout<<"该文法属于3型文法"<returntrue;
}
cout<<"该文法属于2型文法"<}
}
returnfalse;
}
//正规文法转换为正规式
voidtransfer(CSS*p,intn)
{
inti,j,m,flag;
//合并产生式
for(i=0;ifor(j=i+1;j{
//合并形如A->aA,A->bA的产生式为A->aA|bA的形式
if((p[i].left==p[j].left)&&(p[i].right[1]==p[j].right[1]))
{
p[i].right=p[i].right+"|"+p[j].right;
p[j].left="";
p[j].right="";
}
//正规文法到正规式的转换规则3(合并形如S->a,S->b,S->c的产生式为S->a|b|c的形式)
if(p[i].right.length()==1&&p[j].right.length()==1&&p[i].left==p[j].left)
{
p[i].right=p[i].right+"|"+p[j].right;
p[j].left="";
p[j].right="";
}
}
//提取形如S->aA|bA的公因式为S->(a|b)A的形式
for(i=0;i{
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);
}
}
//正规文法到正规式的转换规则2(A->xA|y--->A->x*(y))
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="";
}
}
}
}
//转换规则(S->(xx)AA->aA转化为S->(xx)a*A)
for(i=0;i{
if(p[i].right.length()>1&&p[i].left[0]!
=p[i].right[p[i].right.length()-1])
{
for(j=0;j{
if(p[j].right.length()>1&&p[i].right[p[i].right.length()-1]==p[j].left[0]&&p[j].left[0]==p[j].right[p[j].right.length()-1])
{
p[i].right=p[i].right.substr(0,p[i].right.length()-1)+p[j].right.substr(0,p[j].right.length()-1)+"*"+p[j].right[p[j].right.length()-1];
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="";
}
}
}
}
intmain()
{
inti,j,n;
stringinput;
while(true)
{
cout<<"请输入文法产生式个数N"<cin>>n;
CSS*p=newCSS[n];//初始化产生式数组
for(i=0;i{
input.erase();//清除
cin>>input;//输入
for(j=0;j{
if(input[j]=='-')
{
p[i].left=input.substr(0,j);
p[i].right=input.substr(j+2,input.length());
}
}
}
if(IsThird(p,n))//调用文法类型判断,自顶向下,如果是正规文法,则输出正规式
{
cout<<"该文法属于正规文法,它的正规式如下:
"<transfer(p,n);
for(i=0;i{
if(p[i].left[0]!
=NULL)
{
cout<
for(j=0;j
{
if(p[i].right[j]!
='')
cout<
}
}
}
cout<}
}
return0;
}
六、运行截图
五、设计总结
经过本次实验,加深了我对文法类型的理解,我学会了如何识别一个0型文法,1型文法,2型文法,正规文法。
尤其加深了我对正规文法的理解。
我学会了如何将一个正规文法转化为一个正规式。
而且还锻炼了我编写程序的能力,总之,收获颇多。