https://blog.csdn.net/qq_41735944/article/details/105810232
代码写的有点臃肿,请大家多多包涵
#include
using namespace std;
int n;//输入产生式数
int m1=0;//产生式打开
int m2=0;//集合长度
int m3=0;
int r=0;//jj长度
char zg[100][3];//存直接的左产生式
char zy[100][100];//存直接的右产生式
int jy[100][100];//中间
char fz[100][3];//非终结的集合
char fy[100];//终结集合
char sg[100][3];//存间接的左产生式
char sy[100][100];
char fir[100][100];
char fol[100][100];
char sec[100][100];
int tr[100][100];
char Tr[100][100];
//消直接
int DELz(char g[100][3],char y[100][100],int m)
{
char flag='3';
int M=m;
int ys=0;
char fl[100][3];
for(int i=0;i<M;i++)
{
char f[3];
char *p=strpbrk(y[i],g[i]);
int zsl=0;
for(int z=0;z<strlen(y[i]);z++)//排除A->A+a*A
{
if(y[i][z]==g[i][0]&&strlen(g[i])==1)//比对E
zsl++;
else if(y[i][z]==g[i][0]&&strlen(g[i])==2&&y[i][z+1]=='`')//比对E`
zsl++;
}
if(zsl==1&&p&&strcmp(f,g[i])!=0)//Aa直接左递归
{
fl[ys][0]=g[i][0];
fl[ys++][1]='`';
strcpy(f,g[i]);
for(int z=0;z<M;z++)//对所有A操作
{
//g==A
if(strcmp(g[z],f)==0)//A->Aa===》A'->aA'
{
char *p2=strpbrk(y[z],g[z]);
if(p2)
{
int e=p2-&y[z][0];
//新的产生式A1
g[m][0]=g[z][0];
g[m][1]='`';
int q1=0;
for(int j=0;j<strlen(y[z]);j++)
{
if(j!=e)
{
y[m][q1++]=y[z][j];
}
}
//加上A1
y[m][q1++]=g[z][0];
y[m][q1++]='`';
m++;
//删除原式
y[z][0]='\0';
g[z][0]='\0';
}
else//A->b==>A->bA'
{
int w=strlen(y[z]);
y[z][w++]=g[z][0];
y[z][w++]='`';
}
}
}
}
}
int m3=m;
char f[3];
for(int i=0;i<ys;i++)
{
//新的产生式A1->ε
g[m][0]=fl[i][0];
g[m][1]='`';
y[m][0]='$';
f[0]=fl[i][0];
f[1]='\0';
m2++;
//E'优先级仅此E
for(int j=0;j<m2;j++)
{
if(strcmp(fz[j],f)==0)//找E插入E`
{
for(int w=m2;w>j;w--)
{//全部后移
strcpy(fz[w+1],fz[w]);
}
strcpy(fz[j+1],g[m]);
}
}m++;
}
printf("直接——-------\n");
for(int i=0;i<m;i++)
{
if(g[i][0]!='\0')
{
printf("%s->%s\n",g[i],y[i]);
strcpy(sy[i],y[i]);
}
}
// for(int i=0;i
// {
// printf("fz=%s\n",fz[i]);
// }
return m;
}
//消间接
void BECj()
{
//临时数组
for(int j=0;j<m2;j++)
{
int r=1;//jy内循环
jy[j][0]=0;
for(int i=0;i<m1;i++)
{
if(strcmp(zg[i],fz[j])==0)
{
jy[j][0]++;
jy[j][r++]=i+1;
}
}
}
int zs=1;
for(int i=0;i<m2;i++)
{
zs*=jy[i][0];
}
for(int i=m2-1;i>=0;i--)
{
int zs=jy[i][0];
for(int j=1;j<=zs;j++)
{//防止死循环
char k[100];
strcpy(k,zy[jy[i][j]-1]);
int q=i+1;
{
char *p=strpbrk(k,fz[q]);
int e=p-&k[0];
if(p)
{
int u=strlen(zy[jy[i][j]-1]);
for(int w=1;w<=jy[q][0];w++)
{
if(jy[i][j]!=0&&jy[q][w]!=0)
{
int t=0;
//拼装
for(int z=0;z<e;z++)
{
zy[m1][t++]=zy[jy[i][j]-1][z];
}
for(int z=0;z<strlen(zy[jy[q][w]-1]);z++)
{
zy[m1][t++]=zy[jy[q][w]-1][z];
}
for(int z=e+1;z<u;z++)
{
zy[m1][t++]=zy[jy[i][j]-1][z];
}
//链接
jy[i][0]++;
jy[i][jy[i][0]]=m1+1;
m1++;
}
}
jy[i][j]=0;
}
}
}
}
//间接
for(int i=0;i<m2;i++)
{
for(int j=1;j<=jy[i][0];j++)
{
if(jy[i][j]!=0)
{
strcpy(sg[m3],fz[i]);
strcpy(sy[m3],zy[jy[i][j]-1]);
m3++;
}
}
}
printf("间接-------------\n");
for(int i=0;i<m3;i++)
{
printf("%s->%s\n",sg[i],sy[i]);
}
m3=DELz(sg,sy,m3);
}
void Fir(char g[100][3],char y[100][100],int m)
{
//first集
set<char> st;
set<char>::iterator ji;
int uy=0;
for(int z=0;z<m2;z++)
{
st.clear();
for(int i=0;i<m;i++)
{
char fl[2];
fl[0]=y[i][0];
fl[1]=y[i][1];
if(strcmp(g[i],fz[z])==0)
{
if(y[i][0]>=65&&y[i][0]<=95)//终结符
{
for(int j=0;j<m2;j++)
{
if((y[i][0]==fz[j][0])&&(y[i][1]!='`')&&(strlen(fz[j])==1))//E E
{
char a=j+48;
st.insert(a);
uy++;
}
else if((y[i][0]==fz[j][0])&&(y[i][1]=='`')&&(strlen(fz[j])==2)){//E` E`
char a=j+48;
st.insert(a);
uy++;
}
}
}
else{
st.insert(y[i][0]);
}
}
if(i==m-1)
{
int tz=0;
for(ji=st.begin();ji!=st.end();++ji)
{
fir[z][tz++]=*ji;
}
}
}
}
for(int hy=0;hy<uy;hy++)
{
for(int i=0;i<m2;i++)
{
st.clear();
int rl=strlen(fir[i]);
for(int j=0;j<rl;j++)
{
if(fir[i][j]<=57&&fir[i][j]>=48)
{
for(int z=0;z<rl;z++)
{
if(z!=j)
st.insert(fir[i][z]);
}
for(int z=0;z<strlen(fir[fir[i][j]-48]);z++)
{
st.insert(fir[fir[i][j]-48][z]);
}
}
}
int zj=0;
for(ji = st.begin() ; ji != st.end() ; ++ji)
fir[i][zj++]=*ji;
}
}
printf("first---------\n");
for(int i=0;i<m2;i++)
{
printf("%s\t",fz[i]);
for(int j=0;j<strlen(fir[i]);j++)
printf("%c ",fir[i][j]);
printf("\n");
}
}
void Fol(char g[100][3],char y[100][100],int m)
{
set<char> st;
set<char>::iterator ij;
st.insert('#');
for(int i=0;i<m2;i++)
{
for(int j=0;j<m;j++)
{
char *p=strpbrk(y[j],fz[i]);
int e=p-&y[j][0];
if(p)
{
int b=0;
for(int w=0;w<m2;w++)
{
if(strcmp(fz[w],g[j])==0)
{
b=w;
break;
}
}
for(int q=e+1;q<strlen(y[j]);q++)
{
if(strlen(fz[i])==1&&y[j][e+1]!='`')//EE
{
char a1=b+48;
if(i!=0&&i!=b)
st.insert(a1);
if(e+1==strlen(y[j]))
{
st.insert('#');
break;
}
if((y[j][q]>90||y[j][q]<65)&&y[j][q]!='`')//->Aa
{
st.insert(y[j][q]);
}
else if(y[j][q]<=90&&y[j][q]>=65&&y[j][q+1]!='`')//->AB
{
for(int w=0;w<m2;w++)
{
if(fz[w][0]==y[j][q])
{
for(int er=0;er<strlen(fir[w]);er++)
{
if(fir[w][er]!='$')
st.insert(fir[w][er]);
}
break;
}
}
}
else if(y[j][q]<=90&&y[j][q]>=65&&y[j][q+1]=='`')//->AB`
{
for(int w=0;w<m2;w++)
{
if(fz[w][0]==y[j][q]&&fz[w][1]=='`')
{
for(int er=0;er<strlen(fir[w]);er++)
{
if(fir[w][er]!='$')
st.insert(fir[w][er]);
}
break;
}
}
}
}
else if(strlen(fz[i])==2&&y[j][e+1]=='`')//E1E1
{
char a1=b+48;
if(i!=0&&i!=b)
st.insert(a1);
if(e+2==strlen(y[j]))
{
st.insert('#');
break;
}
if((y[j][q+1]>90||y[j][q+1]<65)&&y[j][q+1]!='`')//->Aa
{
st.insert(y[j][q+1]);
}
else if(y[j][q+1]<=90&&y[j][q+1]>=65&&y[j][q+2]!='`')//->A`B
{
for(int w=0;w<m2;w++)
{
if(fz[w][0]==y[j][q+1])
{
//链接到first[w]
for(int er=0;er<strlen(fir[w]);er++)
{
if(fir[w][er]!='$')
st.insert(fir[w][er]);
}
break;
}
}
}
else if(y[j][q+1]<=90&&y[j][q+1]>=65&&y[j][q+2]=='`')//->A`B`
{
for(int w=0;w<m2;w++)
{
if(fz[w][0]==y[j][q+1]&&fz[w][1]=='`')
{
for(int er=0;er<strlen(fir[w]);er++)
{
if(fir[w][er]!='$')
st.insert(fir[w][er]);
}
break;
}
}
}
}
}
}
}
int zj=0;
for(ij = st.begin(); ij != st.end(); ij++)
{
fol[i][zj++]=*ij;
}
st.clear();
}
for(int i=0;i<m2;i++)
{
for(int j=0;j<strlen(fol[i]);j++)
{
st.clear();
if(fol[i][j]<=57&&fol[i][j]>=48)
{
for(int z=0;z<strlen(fol[i]);z++)
{
if(z!=j)
st.insert(fol[i][z]);
}
for(int z=0;z<strlen(fol[fol[i][j]-48]);z++)
{
st.insert(fol[fol[i][j]-48][z]);
}
}
else{
for(int z=0;z<strlen(fol[i]);z++)
{
st.insert(fol[i][z]);
}
}
int zj=0;
for(ij = st.begin() ; ij != st.end() ; ++ij)
fol[i][zj++]=*ij;
fol[i][st.size()]='\0';
}
}
// }
printf("follow--------\n");
for(int i=0;i<m2;i++)
{
printf("%s\t",fz[i]);
for(int j=0;j<strlen(fol[i]);j++)
printf("%c ",fol[i][j]);
printf("\n");
}
}
void Sec(char g[100][3],char y[100][100],int m)
{
set<char> st;
set<char>::iterator ij;
for(int i=0;i<m;i++)
{
if(y[i][0]=='$')
{
int dg=0;
for(int j=0;j<m2;j++)
{//哪一个非终结符
if(g[i][1]!='`'&&g[i][0]==fz[j][0]&&strlen(fz[j])==1)
{
dg=j;break;
}
else if(g[i][1]=='`'&&g[i][0]==fz[j][0]&&strlen(fz[j])==2){
dg=j;break;
}
}
for(int j=0;j<strlen(fol[dg]);j++)
{
sec[i][j]=fol[dg][j];
}
}
else if(y[i][0]>90||y[i][0]<65)//终结符
{
sec[i][0]=y[i][0];
}
else{//非终结符
int df=0;
for(int j=0;j<m2;j++)
{//哪一个非终结符
if(y[i][1]!='`'&&y[i][0]==fz[j][0]&&strlen(fz[j])==1)
{
df=j;break;
}
else if(y[i][1]=='`'&&y[i][0]==fz[j][0]&&strlen(fz[j])==2){
df=j;break;
}
}
char fg[3];
fg[0]='#';
char *p=strpbrk(fir[df],fg);
if(p)
{
st.clear();
int dg=0;
for(int j=0;j<m2;j++)
{//哪一个非终结符
if(g[i][1]!='`'&&g[i][0]==fz[j][0]&&strlen(fz[j])==1)
{
dg=j;break;
}
else if(g[i][1]=='`'&&g[i][0]==fz[j][0]&&strlen(fz[j])==2){
dg=j;break;
}
}
for(int j=0;j<strlen(fir[df]);j++)
{
st.insert(fir[df][j]);
}
for(int j=0;j<strlen(fol[dg]);j++)
{
st.insert(fol[dg][j]);
}
int zj=0;
for(ij = st.begin() ; ij != st.end() ; ++ij)
sec[i][zj++]=*ij;
}
else{
for(int j=0;j<strlen(fir[df]);j++)
{
sec[i][j]=fir[df][j];
}
}
}
}
// 输出select集
// printf("select--------\n");
// for(int i=0;i
// {
// if(g[i][0]!='\0')
// printf("%s\t->%s\t\t\t%s\n",g[i],y[i],sec[i]);
// }
}
int LL(char g[100][3],char y[100][100],int m)
{
printf("文法判断-----------\n");
int a[200];
for(int i=0;i<m2;i++)
{
memset(a,0,sizeof(a));
// for(int j=0;j<200;j++)
// printf("%d %d\n",j,a[j]);
for(int j=0;j<m;j++)
{
if(strcmp(fz[i],g[j])==0)
{
for(int z=0;z<strlen(sec[j]);z++)
{
a[sec[j][z]]++;
if(a[sec[j][z]]>=2) return 2;
}
}
}
}
return 0;
}
void table(char g[100][3],char y[100][100],int m)
{
set<char> st;
set<char>::iterator ji;
for(int i=0;i<m2;i++)//终结符集合
{
for(int j=0;j<strlen(fol[i]);j++)
st.insert(fol[i][j]);
for(int j=0;j<strlen(fir[i]);j++)
if(fir[i][j]!='$') st.insert(fir[i][j]);
}
printf("预测分析表---------\n\t");
int zl=0;
for(ji=st.begin();ji!=st.end();++ji)
{
cout << * ji << "\t";
fy[zl++]=*ji;
}
printf("\n");
for(int i=0;i<strlen(fy);i++)
{
for(int j=0;j<m;j++)
{
char ft[3]; ft[0]=fy[i];
char *p=strpbrk(sec[j],ft);
if(p)
{
for(int z=0;z<m2;z++)
if(strcmp(g[j],fz[z])==0)
{
tr[z][i]=j+1;
}
}
}
}
for(int i=0;i<m2;i++)
{
printf("%s\t",fz[i]);
for(int j=0;j<strlen(fy);j++)
{
printf("%s\t",y[tr[i][j]-1]);
}
printf("\n");
}
}
void print_process1(stack<int> ss)
{
while(!ss.empty())
{
cout << fy[ss.top()];
ss.pop();
}
}
void print_process2(stack<char> ss)
{
while(!ss.empty())
{
cout << ss.top();
ss.pop();
}
}
void analysis(char g[100][3],char y[100][100],int m)
{
char ad[100];
printf("输入串:\n");
gets(ad);
stack<int> se;
stack<char> st;
int sl;
int pr[100];
for(int i=strlen(ad)-1;i>=0;i--)
{
for(int j=0;j<strlen(fy);j++)
{
if(ad[i]==fy[j])
se.push(j);
else if(fy[j]=='#')
sl=j;
}
}
st.push('#');
st.push(fz[0][0]);
int ry=0;
for(int we=0;we<12;we++)
{
char er;
for(int i=0;i<m2;i++)
{
if(st.top()=='#')
break;
if(st.top()==fy[se.top()])
{
st.pop(); se.pop();
print_process1(se);
printf("\t");
print_process2(st);
printf("\n");
}
else if(st.top()=='$')
{
st.pop();
print_process1(se);
printf("\t");
print_process2(st);
printf("\n");
}
if(st.top()==fz[i][0])
{
er=st.top();
st.pop();
if(st.top()=='`'&&strlen(fz[i])==2)
{
st.pop();
if(tr[i][se.top()]>=1)
{
for(int j=strlen(y[tr[i][se.top()]-1])-1;j>=0;j--)
{
char sd=y[tr[i][se.top()]-1][j];
st.push(sd);
}
pr[ry++]=tr[i][se.top()]-1;
print_process1(se);
printf("\t");
print_process2(st);
printf("\n");
}
else if(tr[i][se.top()]==0){
st.pop();
for(int j=strlen(y[tr[i][sl]-1])-1;j>=0;j--)
{
char sd=y[tr[i][sl]-1][j];
st.push(sd);
}
pr[ry++]=tr[i][sl]-1;
print_process1(se);
printf("\t");
print_process2(st);
printf("\n");
}
}
else if(st.top()!='`'&&strlen(fz[i])==1)
{
if(tr[i][se.top()]>=1)
{
for(int j=strlen(y[tr[i][se.top()]-1])-1;j>=0;j--)
{
char sd=y[tr[i][se.top()]-1][j];
st.push(sd);
}
pr[ry++]=tr[i][se.top()]-1;
print_process1(se);
printf("\t");
print_process2(st);
printf("\n");
}
else if(tr[i][se.top()]==0){
st.pop();
for(int j=strlen(y[tr[i][sl]-1])-1;j>=0;j--)
{
char sd=y[tr[i][sl]-1][j];
st.push(sd);
}
pr[ry++]=tr[i][sl]-1;
print_process1(se);
printf("\t");
print_process2(st);
printf("\n");
}
}
else
st.push(er);
}
}
}
}
int judBD(int b,int step,char f,char z)
{
int er;
if(step==0)
return 1;
for(int i=b%m1;i<4*m1;i++)
{
if(zg[i][0]==z)
{
for(int j=0;j<m2;j++)
{
if(zy[i][0]==fz[j][0]&&fz[j][0]!=z)
{
z=fz[j][0];
if(z==f)
return 8;
return judBD(++b,--step,f,z);
}
} return judBD(++b,--step,f,z);
}
}
return 0;
}
int main()
{
printf("请输入产生式个数:\n");
scanf("%d",&n);
getchar();
for(int i=0;i<n;i++)
{
char a[100];
gets(a);
// printf("%s\n",a);
zg[m1][0]=a[0];//左
fz[m2++][0]=a[0];
//右
int q=0;
for(int j=3;j<=strlen(a);j++)
{
if(a[j]!='|')
{
zy[m1][q]=a[j];
q++;
}
else{
m1++;
q=0;
zg[m1][0]=a[0];
}
}
m1++;
}
printf("------------\n");
for(int i=0;i<m1;i++)
{
printf("%s=>%s\n",zg[i],zy[i]);
}
int o=6,zv=0;
for(int i=0;i<m2;i++)
{
o=judBD(0,10,fz[i][0],fz[i][0]);//i,j,step,goal,now
if(o==8)
zv=1;
}
if(zv==1)
{
BECj();
Fir(sg,sy,m3);
Fol(sg,sy,m3);
Sec(sg,sy,m3);
if(LL(sg,sy,m3)==2) printf("该文法不是为LL(1)文法\n");
else{
printf("该文法是为LL(1)文法\n");
table(sg,sy,m3);
analysis(sg,sy,m3);
}
}
else
{
m1=DELz(zg,zy,m1);
Fir(zg,zy,m1);
Fol(zg,zy,m1);
Sec(zg,zy,m1);
if(LL(zg,zy,m1)==2) printf("该文法不是为LL(1)文法\n");
else {
printf("该文法是为LL(1)文法\n");
table(zg,zy,m1);
analysis(zg,zy,m1);
}
}
system("pause");
}