算符优先分析方法.docx
《算符优先分析方法.docx》由会员分享,可在线阅读,更多相关《算符优先分析方法.docx(24页珍藏版)》请在冰豆网上搜索。
算符优先分析方法
算符优先分析方法
1.课程设计目的与原理
1.1设计目的
1.了解利用算符优先算法进行移进规约分析的方法 。
2.锻炼和提高自己的编程能力。
3.熟悉编译原理语法分析的方法,加深对算符优先基本方法的了解。
4.进一步理解编译原理,更好的的学习它的思路,掌握编译原理的理论基础。
5.了解算符优先分析和规范规约的不同以及优缺点。
1.2设计原理
算符优先分析方法是根据算符之间的优先关系而设计的一种自底向上的语法分析方法。
算符优先分析的基本思想是只规定算符之间的优先关系,也就是只考虑终结符之间的优先关系。
由于算符优先分析不考虑非终结符之间的优先关系,在归约过程中只要找到可归约串就归约,并不考虑归约到哪个非终结符,因而算符优先归约不是规范归约。
2.课程设计环境
1.硬件运行环境:
WindowsXP
2.软件运行环境:
VC++6.0版本
3.课程设计内容
3.1算符优先分析流程图
流程图说明:
k:
表示的是符号栈S的使用深度
S:
用来存放终结符和非终结符的符号栈
Vt:
存放该文法中的所有终结符
3.2算符优先总流程图
3.3算符优先文法
例已知表达式文法为:
E->E+T
E->T
T->T*F
T->F
F->(E)
F->i
⑴计算FIRSTVE和LASTVT集合
FirstVT(E)={+,*,(,i}LastVT(E)={+,*,),i}
FirstVT(T)={*,(,i}LastVT(T)={*,),i}
FirstVT(F)={(,i}LastVT(F)={),i}
FirstVT(Q)={#}LastVT(Q)={#}
⑵构造算符优先矩阵
+
*
(
)
i
#
+
>
<
<
>
<
>
*
>
>
<
>
<
>
(
<
<
<
=
<
)
>
>
>
>
i
>
>
>
>
#
<
<
<
<
=
⑶对于输入串i+i*i+i#的手动分析过程:
步骤
符号栈
当前符号+剩余输入串
移进或归约
0
#
i+i*i+i#
预备
1
#i
+i*i+i#
移进
2
#N
+i*i+i#
归约
3
#N+
i*i+i#
移进
4
#N+i
*i+i#
移进
5
#N+N
*i+i#
归约
6
#N+N*
i+i#
移进
7
#N+N*i
+i#
移进
8
#N+N*N
+i#
归约
9
#N+N
+i#
归约
10
#N
+i#
归约
11
#N+
i#
移进
12
#N+i
#
移进
13
#N+N
#
归约
14
#N
#
归约
15
#N#
接受
见附录
3.4程序调试
例:
1、输入产生式的个数:
2、输入文法:
3、判断文法
4、生成非终结符的FIRSTVT集和LASTVT集:
5、生成算符优先分析表:
5、输入字符串进行分析:
输出结果与自己做的结果一模一样,说明设计成功。
4.总结
经过此次编译课程设计,使我对算符优先分析有了更深更进一步的理解,而且也锻炼了自己的程序编码能力,对自己今后的道路影响不小。
当然还有不足之处以后会慢慢改进。
在试验过程中,我忘记在程序最后面加上一句getchar();,导致我试验时,直接运行.exe文件,当运行到最后输入归约字符串时,执行完后界面自动关闭,导致我不能截图,经过不屑的努力,有两种解决方法,第一可以用VC软件运行,界面就不会关闭。
第二种是在程序里加上getchar();,.exe文件运行到最后就不会自动关闭。
附录
#include
#include
#include
typedefstruct
{
charR;
charr;
intflag;
}array;
typedefstruct
{
charE;
chare;
}charLode;
typedefstruct
{
charLode*base;
inttop;
}charstack;
charstr[80][80],arr[80][80],brr[80][80];
arrayF[20];
intm,kk,p,ppp,FF=1;
charr[10];
intcrr[20][20],FLAG=0;
charccrr1[1][20],ccrr2[20][1];
voidInitstack(charstack&s)//定义栈
{
s.base=newcharLode[20];
s.top=-1;
}
voidpush(charstack&s,charLodew)
{
s.top++;
s.base[s.top].E=w.E;
s.base[s.top].e=w.e;
}
voidpop(charstack&s,charLode&w)
{
w.E=s.base[s.top].E;
w.e=s.base[s.top].e;
s.top--;
}
intIsEmpty(charstacks)
{
if(s.top==-1)
return1;
elsereturn0;
}
intIsLetter(charch)
{
if(ch>='A'&&ch<='Z')
return1;
elsereturn0;
}
//judge1是判断是否是算符文法:
若产生式中含有两个相继的非终结符则不是算符文法
intjudge1(intn)
{
intj=3,flag=0;
for(inti=0;i<=n;i++)
while(str[i][j]!
='\0')
{
chara=str[i][j];
charb=str[i][j+1];
if(IsLetter(a)&&IsLetter(b))
{flag=1;break;}
elsej++;
}
if(flag==1)
return0;
else
return1;
}
//judge2是判断文法G是否为算符优先文法:
若不是算符文法或若文法中含空字或终结符的优先级不唯一则不是算符优先文法
voidjudge2(intn)
{
for(inti=0;i<=n;i++)
if(str[i][3]=='~'||judge1(n)==0||FLAG==1)//'~'代表空字
{cout<<"该文法不是算符优先文法!
"<if(i>n)
cout<<"该文法是算符优先文法!
"<}
//search1是查看存放终结符的数组r中是否含有重复的终结符
intsearch1(charr[],intkk,chara)
{
for(inti=0;iif(r[i]==a)
break;
if(i==kk)return0;
elsereturn1;
}
//createF函数是用F数组存放每个终结符与非终结符和组合,并且值每队的标志位为0;F数组是一个结构体
voidcreateF(intn)
{
intk=0,i=1;charg;
chart[10];//t数组用来存放非终结符
t[0]=str[0][0];
while(i<=n)
{
if(t[k]!
=str[i][0])
{k++;t[k]=str[i][0];g=t[k];i++;}
elsei++;
}
kk=0;
charc;
for(i=0;i<=n;i++)
{intj=3;
while(str[i][j]!
='\0')
{
c=str[i][j];
if(IsLetter(c)==0)
{
if(!
search1(r,kk,c))
r[kk]=c;kk++;//r数组用来存放终结符
}
j++;
}
}
m=0;
for(i=0;ifor(intj=0;j{
F[m].R=t[i];
F[m].r=r[j];
F[m].flag=0;
m++;
}
}
//search函数是将在F数组中寻找到的终结符与非终结符对的标志位值为1
voidsearch(charLodew)
{
for(inti=0;iif(F[i].R==w.E&&F[i].r==w.e)
{F[i].flag=1;break;}
}
voidFirstVT(intn)//求FirstVT
{
charstacksta;
charLodew;
inti=0;
Initstack(sta);
while(i<=n)
{
intk=3;
w.E=str[i][0];
chara=str[i][k];
charb=str[i][k+1];
if(!
IsLetter(a))//产生式的后选式的第一个字符就是终结符的情况
{
w.e=a;
push(sta,w);
search(w);
i++;
}
elseif(IsLetter(a)&&b!
='\0'&&!
IsLetter(b))//产生式的后选式的第一个字符是非终结符的情况
{
w.e=b;
push(sta,w);
search(w);
i++;
}
elsei++;
}
charLodeww;
while(!
IsEmpty(sta))
{
pop(sta,ww);
for(i=0;i<=n;i++)
{
w.E=str[i][0];
if(str[i][3]==ww.E&&str[i][4]=='\0')
{
w.e=ww.e;
push(sta,w);
search(w);
break;
}
}
}
p=0;intk=1;i=1;
while(i{
if(F[i-1].flag==1)
{
arr[p][0]=F[i-1].R;
arr[p][k]=F[i-1].r;
}
while(F[i].flag==0&&ii++;
if(F[i].flag==1)
{
if(F[i].R==arr[p][0])
k++;
else{arr[p][k+1]='\0';p++;k=1;}
i++;
}
}
}
voidLastVT(intn)//求LastVT
{
charstacksta;
charLodew;
for(inti=0;iF[i].flag=0;
i=0;
Initstack(sta);
while(i<=n)
{
intk=strlen(str[i]);
w.E=str[i][0];
chara=str[i][k-1];
charb=str[i][k-2];
if(!
IsLetter(a))
{
w.e=a;
push(sta,w);
search(w);
i++;
}
elseif(IsLetter(a)&&!
IsLetter(b))
{
w.e=b;
push(sta,w);
search(w);
i++;
}
elsei++;
}
charLodeee;
while(!
IsEmpty(sta))
{
pop(sta,ee);
for(i=0;i<=n;i++)
{
w.E=str[i][0];
if(str[i][3]==ee.E&&str[i][4]=='\0')
{
w.e=ee.e;
push(sta,w);
search(w);
}
}
}
intk=1;i=1;
ppp=0;
while(i{
if(F[i-1].flag==1)
{
brr[ppp][0]=F[i-1].R;
brr[ppp][k]=F[i-1].r;
}
while(F[i].flag==0&&ii++;
if(F[i].flag==1)
{
if(F[i].R==arr[ppp][0])
k++;
else{brr[ppp][k+1]='\0';ppp++;k=1;}
i++;
}
}
}
voidcreateYXB(intn)//构造优先表
{
inti,j;
for(j=1;j<=kk;j++)
ccrr1[0][j]=r[j-1];
for(i=1;i<=kk;i++)
ccrr2[i][0]=r[i-1];
for(i=1;i<=kk;i++)
for(j=1;j<=kk;j++)
crr[i][j]=0;
intI=0,J=3;
while(I<=n)
{
if(str[I][J+1]=='\0')
{I++;J=3;}
else
{
while(str[I][J+1]!
='\0')
{
charaa=str[I][J];
charbb=str[I][J+1];
if(!
IsLetter(aa)&&!
IsLetter(bb))//优先及等于的情况,用1值表示等于
{
for(i=1;i<=kk;i++)
{
if(ccrr2[i][0]==aa)
break;
}
for(j=1;j<=kk;j++)
{
if(ccrr1[0][j]==bb)
break;
}
if(crr[i][j]==0)
crr[i][j]=1;
else{FLAG=1;I=n+1;}
J++;
}
if(!
IsLetter(aa)&&IsLetter(bb)&&str[I]
[J+2]!
='\0'&&!
IsLetter(str[I][J+2]))//优先及等于的情况
{
for(i=1;i<=kk;i++)
{
if(ccrr2[i][0]==aa)
break;
}
for(intj=1;j<=kk;j++)
{
if(ccrr1[0][j]==str[I][J+2])
break;
}
if(crr[i][j]==0)
crr[i][j]=1;
else{FLAG=1;I=n+1;}
}
if(!
IsLetter(aa)&&IsLetter(bb))//优先及小于的情况,用2值表示小于
{
for(i=1;i<=kk;i++)
{
if(aa==ccrr2[i][0])
break;
}
for(j=0;j<=p;j++)
{
if(bb==arr[j][0])
break;
}
for(intmm=1;arr[j][mm]!
='\0';mm++)
{
for(intpp=1;pp<=kk;pp++)
{
if(ccrr1[0][pp]==arr[j][mm])
break;
}
if(crr[i][pp]==0)
crr[i][pp]=2;
else{FLAG=1;I=n+1;}
}
J++;
}
if(IsLetter(aa)&&!
IsLetter(bb))//优先及大于的情况,用3值表示大于
{
for(i=1;i<=kk;i++)
{
if(ccrr1[0][i]==bb)
break;
}
for(j=0;j<=ppp;j++)
{
if(aa==brr[j][0])
break;
}
for(intmm=1;brr[j][mm]!
='\0';mm++)
{
for(intpp=1;pp<=kk;pp++)
{
if(ccrr2[pp][0]==brr[j][mm])
break;
}
if(crr[pp][i]==0)
crr[pp][i]=3;
else{FLAG=1;I=n+1;}
}
J++;
}
}
}
}
}
//judge3是用来返回在归约过程中两个非终结符相比较的值
intjudge3(chars,chara)
{
inti=1,j=1;
while(ccrr2[i][0]!
=s)
i++;
while(ccrr1[0][j]!
=a)
j++;
if(crr[i][j]==3)return3;
elseif(crr[i][j]==2)
return2;
elseif(crr[i][j]==1)
return1;
elsereturn0;
}
voidprint(chars[],charSTR[][20],intq,intu,intii,intk)//打印归约的过程
{
cout<
for(inti=0;i<=k;i++)
cout<
cout<<"";
for(i=q;i<=ii;i++)
cout<cout<<"";
}
voidprocess(charSTR[][20],intii)//对输入的字符串进行归约的过程
{
cout<<"步骤"<<""<<"符号栈"<<""<<"输入串"<<""<<"动作"<intk=0,q=0,u=0,b,i,j;
chars[40],a;
s[k]='#';
print(s,STR,q,u,ii,k);
cout<<"预备"<k++;u++;
s[k]=STR[0][q];
q++;
print(s,STR,q,u,ii,k);
cout<<"移进"<while(q<=ii)
{
a=STR[0][q];
if(!
IsLetter(s[k]))j=k;
elsej=k-1;
b=judge3(s[j],a);
if(b==3)//大于的情况进行归约
{
while(IsLetter(s[j-1]))
j--;
for(i=j;i<=k;i++)
s[i]='\0';
k=j;s[k]='N';u++;
print(s,STR,q,u,ii,k);
cout<<"归约"<}
elseif(b==2||b==1)//小于或等于的情况移进
{
k++;
s[k]=a;
u++;
q++;
print(s,STR,q,u,ii,k);
if(s[0]=='#'&&s[1]=='N'&&s[2]=='#')
cout<<"接受"<elsecout<<"移进"<}
else
{cout<<"出错"<}
if(s[0]=='#'&&s[1]=='N'&&s[2]=='#')
cout<<"归约成功"<elsecout<<"归约失败"<}
voidmain()
{
intn,i,j;
cout<<"*******欢迎使用算符优先分析算法模拟器*******"<cout<<"请输入您要定义的文法G的产生式的个数n:
";
cin>>n;
for(i=0;i{
gets(str[i]);
j=strlen(str[i]);
str[i][j]='\0';
}
str[i][0]='Q';
str[i][1]='-';
str[i][2]='>';
str[i][3]='#';
str[i][4]=str[0][0];
str[i][5]='#';
str[i][6]='\0';
cout<<"您定义的产生式如下:
"<for(i=0;i<=n;i++)
cout<if(judge1(n)==0)//判断文法G是否为算符文法
cout<<"文法G不是算符文法!
"<if(judge1(n)==1)
{
cout<<"文法G是算符文法!
"<createF(n);
FirstVT(n);
LastVT(n);
createYXB(n);
}
judge2(n);//判断文法G是否为算符优先文法
if(FLAG==0)
{
for(i=0;i<=p;i++)//打印FirstVT
{
cout<<"FirstVT("<for(intl=1;arr[i][l+1]!
='\0';l++)
cout<cout<}
cout<<"FirstVT(Q)={#}"<for(i=0;i<=ppp;i++)//打印LastVT
{
cout<<"LastVT("<for(intl=1;brr[i][l+1]!
='\0';l++)
cout<cout<}
cout<<"LastVT(Q)={#}"<cout<<"优先表如下:
"<for(i=1;i{
cout<<"";
cout<}
cout<for(i=1;i{
cout<for(j=1;j{
if(crr[i][j]==0)
cout<<"";
elseif(crr[i][j]==1)
cout<<"=";
elseif(crr[i][j]==2)
cout<<"<";
elseif(crr[i][j]==3)
cout<<">";
cout<<"";
}
cout<}
}
if(FF==1)
{
charSTR[1][20];
cout<<"请输入要规约的字符串:
"<gets(STR[0]);
intii=strlen(STR[0]);
STR[0][ii]='#';
cout<<"下面是规约的过程:
"<process(STR,ii);
g