实现算符优先算法,完成一个算符优先文法的算法优先分析过程。
(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);
(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)
(3)给定表达式文法为:
G(E’): E’→#E#
E→E+T | T
T→T*F |F
F→(E)|i
(4)分析的句子为:
(i+i)*i和i+i)*i
经过对这个程序的编写,我对算符优先分析的原理有了深入的理解,熟悉了算符分析的过程,掌握了算符优先分析的有关处理,能够使用一种高级语言构造算符优先的语法分析器。对算符优先分析的相关知识有了更加深入的了解和掌握。
代码:
#include<cstring>
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
# define MAX 100
char *SR;//输入串
char SY[MAX];//移近或规约后剩余串
char S[MAX];//堆栈
char grammer[10][30];//保存输入的语法规则
char chanshengshi[20][10];
char feizhongjie[10];//存放非终结符
char zhongjie[15];//存放终结符
int numf=0;//非终结符个数
int num=0;//终结符个数
int M=0;//转换后产生式个数
char Relation[6][6];//存放优先关系
int FIRSTVT[3][6];//存放 firstvt 集
int LASTVT[3][6];//存放 lastvt 集
int printRelent();
int type(char s)//在终结符串里查找字符 a 若 a 在其中返回下标,否则返回 -1
{
int len=strlen(zhongjie);
int tp=-1;
for(int i=0;i<len;i++)
{
if(s==zhongjie[i])
{ tp=i; break; }
}
return tp;
}
int type_fei(char s)
{
int len=strlen(feizhongjie);
int tp=-1;
for(int i=0;i<len;i++)
{
if(s==feizhongjie[i])
{ tp=i; break; }
}
return tp;
}
void transproduct(int n)//原始产生式处理
{
int x=0,y=0;
for(int i=0;i<n;i++)
{
for(int j=0;grammer[i][j]!='\0';j++)
{
if(grammer[i][0]<'A'||grammer[i][0]>'Z')
{ cout<<"该文法不是算符文法 !"<<endl; return; }
else
{
if(type_fei(grammer[i][0])<0)
feizhongjie[numf++]=grammer[i][0];//获取非终结符符号
}
if(grammer[i][j]>='A'&&grammer[i][j]<='Z')
{
if(grammer[i][j+1]>='A'&&grammer[i][j+1]<='Z')
{ cout<<"该文法不是算符文法 !"<<endl; return; }
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;grammer[i][j]!='\0';j++)
{
if((grammer[i][j]>'Z'||grammer[i][j]<'A')&&grammer[i][j]!='-'&&grammer[i][j]!='>'&&grammer[i][j]!='|')
{
if(type(grammer[i][j])<0)
zhongjie[num++]=grammer[i][j];//获取终结符符号 }
}
}
zhongjie[num]='#';
zhongjie[num+1]='\0'; x=1;
for(i=0;i<n;i++)//转换产生式从第二行开始存
{
chanshengshi[x][y]=grammer[i][0]; y++;
for(int j=1;grammer[i][j]!='\0';j++)
{
if(grammer[i][j]=='|')
{ chanshengshi[x][y]='\0'; x++; y=0; chanshengshi[x][y]=grammer[i][0]; y++; chanshengshi[x][y++]='-'; chanshengshi[x][y++]='>';
}
else
{ chanshengshi[x][y]=grammer[i][j]; y++; }
}
chanshengshi[x][y]='\0'; x++; y=0;
}
chanshengshi[0][0]=feizhongjie[0];//将开始符号以 #_#形式存入第一行产生式数组, 以便优先关系构造时 使用
chanshengshi[0][1]='-'; chanshengshi[0][2]='>'; chanshengshi[0][3]='#';
chanshengshi[0][4]=feizhongjie[0]; chanshengshi[0][5]='#'; chanshengshi[0][6]='\0';
M=x;
cout<<"转换后产生式如下:"<<endl;
for(int j=0;j<x;j++)
{ cout<<chanshengshi[j]<<endl; }
cout<<"产生式包含的终结符有:";
for(i=0;i<=num;i++)
{ cout<<zhongjie[i]<<" "; }
cout<<endl; cout<<"产生式包含的非终结符有:";
for(i=0;i<numf;i++)
{ cout<<feizhongjie[i]<<" "; }
cout<<endl;
}
}
void fristvt()//计算 firstvt 集并填入 FIRSTVT 中
{
int r1,x,y;
for(int i=0;i<numf;i++)
{
for(int j=0;j<num;j++)
FIRSTVT[i][j]=0;
}
for(int i=1;i<=M;i++)
{
r1=type_fei(chanshengshi[i][0]);
x=type(chanshengshi[i][3]);
y=type(chanshengshi[i][4]);
if(x>=0)
{ FIRSTVT[r1][x]=1;}
else
{ if(y>=0) FIRSTVT[r1][y]=1; }
}
for(int i=M;i>=1;i--)
{
int y=type(chanshengshi[i][3]);
if(y<0)
{
int m=type_fei(chanshengshi[i][0]);
int m1=type_fei(chanshengshi[i][3]);
if(m!=m1)
{
for(int t=0;t<num;t++)
if(FIRSTVT[m1][t]!=0)
{ FIRSTVT[m][t]=FIRSTVT[m1][t]; }
}
}
}
cout<<"非终结符的 firstvt 集:"<<endl;
for(int i=0;i<numf;i++)
{
cout<<feizhongjie[i]<<" ";
for(int j=0;j<num;j++)
{
if(FIRSTVT[i][j]!=0)
{ cout<<zhongjie[j]<<" "; }
}
cout<<endl;
}
}
void lastvt()//求非终结符的 lastvt 集
{
int d=0, r1,x,y;
for(int i=0;i<numf;i++)
{
for(int j=0;j<num;j++)
LASTVT[i][j]=0; }
for(int i=1;i<=M;i++)
{
r1=type_fei(chanshengshi[i][0]);//判断是否为非终结符
for(int cl=0;chanshengshi[i][cl]!='\0';cl++)
{ d=cl; }
x=type(chanshengshi[i][d]);
y=type(chanshengshi[i][d-1]);
if(x>=0)
{ LASTVT[r1][x]=1; }
else
{ if(y>=0) LASTVT[r1][y]=1; }
}
for(int i=M;i>=1;i--)
{
int y=type(chanshengshi[i][3]);
if(y<0)
{
int m=type_fei(chanshengshi[i][0]);
int m1=type_fei(chanshengshi[i][3]);
if(m!=m1)
{
for(int t=0;t<num;t++)
if(LASTVT[m1][t]!=0)
{ LASTVT[m][t]=LASTVT[m1][t]; }
}
}
}
cout<<"非终结符的 lastvt 集:"<<endl;
for(int i=0;i<numf;i++)
{
cout<<feizhongjie[i]<<" ";
for(int j=0;j<num;j++)
{
if(LASTVT[i][j]!=0)
{
cout<<zhongjie[j]<<" ";
}
}
cout<<endl;
}
}
void creatRelation()///创建优先关系表
{
int a=strlen(feizhongjie),b=strlen(zhongjie),c=strlen(*chanshengshi),x,x1,y,y1,f;
for(int i=0;i<=c;i++)
{
int j=strlen(chanshengshi[i]);
for(int v=3;v<j;v++)
{
x=type(chanshengshi[i][v]);
x1=type_fei(chanshengshi[i][v]);
y=type(chanshengshi[i][v+1]);
y1=type_fei(chanshengshi[i][v+1]);
f=type(chanshengshi[i][v+2]);
if((x>=0)&&(y>=0))
{ Relation[x][y]='='; }
if((v<=(j-2))&&x>=0&&f>=0&&y<0)
{ Relation[x][f]='=';}
if(x>=0&&y<0)
{
for(int h=0;h<b;h++)
if(FIRSTVT[y1][h]==1) { Relation[x][h]='<'; }
}
if(x<0&&y>=0)
{
for(int g=0;g<b;g++)
{
if(LASTVT[x1][g]==1)
{ Relation[g][y]='>'; }
}
}
}
}
}
char charcomplete(char a,char b)//优先关系比较,返回优先关系,若无返回 $
{
char ret='$';int x=type(a),y=type(b); if(x>=0&&y>=0) ret=Relation[x][y]; return ret;
}
void deelSY()//剩余串向前移一位
{
int i,j; i=strlen(SY);
for(j=0;j<i;j++)
{ SY[j]=SY[j+1]; }
SY[i-1]='\0';
}
int main()
{
int numP=0; cout<<"请输入产生式规则数:";
cin>>numP;
cout<<"请输入产生式:"<<endl;
for(int i=0;i<numP;i++)
{ cin>>grammer[i]; }
transproduct(numP);
fristvt();
lastvt();
creatRelation();
cout<<"产生式的终结符对应的优先关系如下:"<<endl;
int printRelent();//输出优先关系
FILE*fp;
char str[20];
cout<<" 请输入原文件名(包括后缀名) :";
while(true)
{
cin>>str;
if((fp=fopen(str,"r"))==NULL)
cout<<"输入错误,请检查文件名 "<<endl;
else break;
}
fseek(fp,0,SEEK_END); int n=ftell(fp),p=0; char ch; SR=new char [n];
fseek(fp,0,SEEK_SET); while(ch!=EOF)
{
ch=fgetc(fp);
SR[p]=ch;
SY[p]=ch;
p++;
}
char a,Q,N,B; int step=0;
cout<<"步骤 "<<"\t"<<"符号栈 "<<"\t\t"<<"输入串 "<<"\t\t\t"<<"动作 "<<endl;
int k=1,j=0,m=1,R,r=strlen(*chanshengshi); S[k]='#'; a=SR[k]; B=charcomplete(S[k],a);
deelSY();
cout<<step<<"\t"<<S[k]<<"\t\t"<<SY<<"\t\t"<<"预备 "<<endl;
do{
a=SR[m]; m++;
if(type(a)>=0) j=k;
else j=k-1;
B=charcomplete(S[j],a);
while(B=='>')
{ do
{ Q=S[j]; if(type(S[j-1])>=0) j--; else j=j-2;
B=charcomplete(S[j],Q);}while(B!='<');
for(int w=j+1;w<=k;w++) //将 S[j+1]。 。 。 S[k]规约
{
for(R=0;R<=r;R++)
for(n=3;chanshengshi[R][n]!='\0';n++)
{
if((type(S[w])<0)&&type(chanshengshi[R][n])<0)//栈中内容和产生式为非终结符(首字符)
{
if((type(S[w+1])>=0)&&(type(chanshengshi[R][n+1])>=0)&&(S[w+1]==chanshengshi[R][n+1]))// (次字符为终结符)
{ N=chanshengshi[R][0];//并且非终结符对应相同则用产生式的首个非终结符规约
break;
}
}
else
{
if(type(S[w])>=0)//若为非终结符规约条件为栈中内容和产生式右部相同则规约
if(S[w]==chanshengshi[R][n]) { N=chanshengshi[R][0]; break; }
}
}
}
k=j+1; S[k]=N; step++;//步骤数加 1
cout<<step<<"\t";
for(int t=1;t<=k;t++)
cout<<S[t]; cout<<"\t\t"<<SY<<"\t\t"<<"规约 "<<endl;
B=charcomplete(S[j],a);
}
if(B=='<'||B=='=')
{
k=k+1;
step++;
deelSY();
S[k]=a;
if(a=='#')
{
cout<<step<<"\t";
for(int t=1;t<=k;t++)
cout<<S[t];
cout<<"\t\t"<<SY<<"\t\t"<<"接受 "<<endl;
}
else
{ cout<<step<<"\t";
for(int t=1;t<=k;t++)
cout<<S[t];
cout<<"\t\t"<<SY<<"\t\t"<<"移进 "<<endl;
}
}
else
cout<<"错误! "<<endl;
}
while(a!='#');
cout<<"语法分析结束! "<<endl;
}