编译原理实验三正规文法到正规式的转换Word文件下载.docx
《编译原理实验三正规文法到正规式的转换Word文件下载.docx》由会员分享,可在线阅读,更多相关《编译原理实验三正规文法到正规式的转换Word文件下载.docx(14页珍藏版)》请在冰豆网上搜索。
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<
iostream>
忽视了c++语言中的头文件应当去掉.h,须再另加上usingnamespacestd;
2:
规则分解不对,导致结果出错。
3:
太多循环嵌套容易造成程序出错,养成把括号提前打好的习惯。
六:
实验结果与分析
不是正规文法的不能转换:
是正规文法的才可以转换:
七:
源代码
#include<
string>
usingnamespacestd;
#definemax50
intNONE=1;
stringstrings,noend,end;
//非终结符与终结符存储
intn;
//产生式总数
stringleft;
stringright;
intj;
for(j=0;
j<
strings.length();
j++)
if(strings[j]=='
-'
)
{
p[i].left=strings.substr(0,j);
p[i].right=strings.substr(j+1,strings.length()-j);
}
}
inti,j;
for(i=0;
i<
n;
i++)
{
for(j=0;
(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])>
end+=p[i].left[j];
(int)p[i].right.length();
if(!
(p[i].right[j]>
p[i].right[j]<
))//终结符判断
if(end.find(p[i].right[j])>
end+=p[i].right[j];
else
if(noend.find(p[i].right[j])>
noend+=p[i].right[j];
}
intflag(0),count(0);
if(p[i].left[j]>
)//有否非终结符
flag++;
if(flag>
0)
flag=0;
count++;
else
break;
//左部没有非终结符,结束
if(count==n)
return1;
//属于0型文法
else
cout<
<
endl<
"
所输产生式不属于任何文法。
endl;
NONE=0;
return0;
intflag(0);
inti;
if(zero(p))
for(i=0;
if(p[i].right.length()<
p[i].left.length())//右部长度是否小于左部
break;
flag--;
if(flag>
此文法属于0型文法,即短语文法。
return0;
//不属于1型文法
else
if(flag==0)
return1;
//属于1型文法
else
return0;
if(one(p))
i++)
if((p[i].left.length()!
=1)||!
(p[i].left[0]>
p[i].left[0]<
))//左部不属于一个字符或不属于非终结符
flag--;
此文法属于1型文法,即上下文有关文法。
//不属于2型文法
//属于2型文法
intflag=0;
inti;
if(two(p))
if(!
(p[i].right.length()==1||p[i].right.length()==2)||(p[i].right[0]>
p[i].right[0]<
))//右部字符个数不是1或2,或首字符是非终结符
flag++;
break;
if((p[i].right.length()==2)&
!
(p[i].right[1]>
p[i].right[1]<
))//第二个字符不是非终结符
else
if(flag>
cout<
此文法属于2型文法,即上下文无关文法。
i=n;
else
if(flag==0)
此文法属于3型文法,即正规文法。
return1;
inti,j,m,flag;
//合并产生式
for(i=0;
for(j=i+1;
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->
{
p[i].right=p[i].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[j].left="
p[j].right="
i++)//提取形如S->
aA|bA的公因式为S->
(a|b)A的形式
flag=p[i].right.length();
if(p[i].right.length()>
2&
'
=p[i].right[1]&
p[i].right[2]=='
|'
for(j=1;
flag-1;
j=j+3)
{
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);
if(p[i].left[0]==p[i].right[p[i].right.length()-1]&
p[i].right.length()>
1)
for(j=0;
if(p[i].left==p[j].left&
j!
=i)
for(m=0;
m<
p[j].right.length();
m++)
if('
=p[j].right[m]&
p[j].right[m]<
)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;
p[i].right.length();
if('
=p[i].right[j]&
{
for(m=0;
if(p[m].left[0]==p[i].right[j]&
m!
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;
//再次合并左部相等的产生式
if(p[i].left[0]==p[j].left[0]&
i!
=j)
if(p[j].right.length()>
voidmain()
....................编译原理实验三:
正规文法到正规式的转换...................."
请输入正规文法(三型文法)的产生式总数及各产生式:
其中左右部之间用'
表示,空用'
#'
表示"
cin>
>
Chomsky*p=newChomsky[max];
cin>
strings;
apart(p,i);
VNVT(p);
if(three(p))//只有当输入为正规文法时才进行转换,否则实验退出!
!
转换后的正规式为:
change(p);
i++)//输出转换后的文法
if(p[i].left[0]!
=NULL)
cout<
p[i].left<
="
for(j=0;
if(p[i].right[j]!
cout<
p[i].right[j];
该文法不属于正规文法,实验结束!