E->E+T
E->E-T
E->T
T->T*F
T->T/F
T->id 一共30个状态,且代码写得个人感觉很罗嗦!
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<stack>
using namespace std;
char s[100]; //词法流
int length=0; //词法流长度
stack<char> S; //栈
char t1; //指向词法流的指针
int p1,p2;
int bb[30][3]; //goto表
char ch; //指针
int temp1,temp2;
int flag=0;
int nn=0;
int TEMP=0;
struct C{ //存储action表内每个单元信息
char c1; //移近、规约,错误标志
int c2; //数字
char *st; //返回一些有用的信息
};
C cc[30][8]; //action表
int zhong(char t) //将终结符数字化
{
if(t=='i') return 0;
if(t=='+') return 1;
if(t=='-') return 2;
if(t=='*') return 3;
if(t=='/') return 4;
if(t=='(') return 5;
if(t==')') return 6;
if(t=='$') return 7;
}
struct Chan{
int num; //产生式右侧个数
char *you;
char zuo;
};
Chan MM[8];
void ChuShiHua()
{
for(p1=0;p1<30;p1++)
{
for(p2=0;p2<8;p2++)
{
cc[p1][p2].st="error";
}
}
for(p1=0;p1<30;p1++)
for(p2=0;p2<3;p2++)
bb[p1][p2]=0;
cc[0][0].c1=cc[0][5].c1=cc[1][1].c1=cc[1][2].c1=cc[2][3].c1=cc[2][4].c1='s';
cc[4][0].c1=cc[4][5].c1=cc[6][0].c1=cc[6][5].c1=cc[7][0].c1=cc[7][5].c1='s';
cc[8][0].c1=cc[8][5].c1=cc[9][0].c1=cc[9][5].c1=cc[10][1].c1=cc[10][2].c1=cc[10][6].c1='s';
cc[11][3].c1=cc[11][4].c1=cc[13][0].c1=cc[13][5].c1=cc[15][3].c1=cc[15][4].c1=cc[16][3].c1=cc[16][4].c1='s';
cc[20][0].c1=cc[20][5].c1=cc[21][0].c1=cc[21][5].c1=cc[22][0].c1=cc[22][5].c1=cc[23][0].c1=cc[23][5].c1='s';
cc[24][1].c1=cc[24][2].c1=cc[24][6].c1=cc[25][3].c1=cc[25][4].c1=cc[26][3].c1=cc[26][4].c1='s';
//以上是移进标志!
cc[0][0].c2=cc[6][0].c2=cc[7][0].c2=cc[8][0].c2=cc[9][0].c2=5; //移近5号状态
cc[0][5].c2=cc[6][5].c2=cc[7][5].c2=cc[8][5].c2=cc[9][5].c2=4; //移近4号状态
cc[1][1].c2=6; //移近6号状态
cc[1][2].c2=7; //移近7号状态
cc[2][3].c2=cc[15][3].c2=cc[16][3].c2=8; //移近8号状态
cc[2][4].c2=cc[15][4].c2=cc[16][4].c2=9; //移近9号状态
cc[4][0].c2=cc[13][0].c2=cc[20][0].c2=cc[21][0].c2=cc[22][0].c2=cc[23][0].c2=14; //移近14号状态
cc[4][5].c2=cc[13][5].c2=cc[20][5].c2=cc[21][5].c2=cc[22][5].c2=cc[23][5].c2=13; //移近13号状态
cc[10][1].c2=cc[24][1].c2=20; //移近20号状态
cc[10][2].c2=cc[24][2].c2=21; //移近21号状态
cc[10][6].c2=19; //移近19号状态
cc[11][3].c2=cc[25][3].c2=cc[26][3].c2=22; //移近22号状态
cc[11][4].c2=cc[25][4].c2=cc[26][4].c2=23; //移近23号状态
cc[24][6].c2=29; //移近29号状态
cc[2][1].c1=cc[2][2].c1=cc[2][7].c1='r';
cc[2][1].c2=cc[2][2].c2=cc[2][7].c2=3;
cc[3][1].c1=cc[3][2].c1=cc[3][3].c1=cc[3][4].c1=cc[3][7].c1='r';
cc[3][1].c2=cc[3][2].c2=cc[3][3].c2=cc[3][4].c2=cc[3][7].c2=6;
cc[5][1].c1=cc[5][2].c1=cc[5][3].c1=cc[5][4].c1=cc[5][7].c1='r';
cc[5][1].c2=cc[5][2].c2=cc[5][3].c2=cc[5][4].c2=cc[5][7].c2=8;
cc[11][1].c1=cc[11][2].c1=cc[11][6].c1='r';
cc[11][1].c2=cc[11][2].c2=cc[11][6].c2=3;
cc[12][1].c1=cc[12][2].c1=cc[12][3].c1=cc[12][4].c1=cc[12][6].c1='r';
cc[12][1].c2=cc[12][2].c2=cc[12][3].c2=cc[12][4].c2=cc[12][6].c2=6;
cc[14][1].c1=cc[14][2].c1=cc[14][3].c1=cc[14][4].c1=cc[14][6].c1='r';
cc[14][1].c2=cc[14][2].c2=cc[14][3].c2=cc[14][4].c2=cc[14][6].c2=8;
cc[15][1].c1=cc[15][2].c1=cc[15][7].c1='r';
cc[15][1].c2=cc[15][2].c2=cc[15][7].c2=1;
cc[16][1].c1=cc[16][2].c1=cc[16][7].c1='r';
cc[16][1].c2=cc[16][2].c2=cc[16][7].c2=2;
cc[17][1].c1=cc[17][2].c1=cc[17][3].c1=cc[17][4].c1=cc[17][7].c1='r';
cc[17][1].c2=cc[17][2].c2=cc[17][3].c2=cc[17][4].c2=cc[17][7].c2=4;
cc[18][1].c1=cc[18][2].c1=cc[18][3].c1=cc[18][4].c1=cc[18][7].c1='r';
cc[18][1].c2=cc[18][2].c2=cc[18][3].c2=cc[18][4].c2=cc[18][7].c2=5;
cc[19][1].c1=cc[19][2].c1=cc[19][3].c1=cc[19][4].c1=cc[19][7].c1='r';
cc[19][1].c2=cc[19][2].c2=cc[19][3].c2=cc[19][4].c2=cc[19][7].c2=7;
cc[25][1].c1=cc[25][2].c1=cc[25][6].c1='r';
cc[25][1].c2=cc[25][2].c2=cc[25][6].c2=1;
cc[26][1].c1=cc[26][2].c1=cc[26][6].c1='r';
cc[26][1].c2=cc[26][2].c2=cc[26][6].c2=2;
cc[27][1].c1=cc[27][2].c1=cc[27][3].c1=cc[27][4].c1=cc[27][6].c1='r';
cc[27][1].c2=cc[27][2].c2=cc[27][3].c2=cc[27][4].c2=cc[27][6].c2=4;
cc[28][1].c1=cc[28][2].c1=cc[28][3].c1=cc[28][4].c1=cc[28][6].c1='r';
cc[28][1].c2=cc[28][2].c2=cc[28][3].c2=cc[28][4].c2=cc[28][6].c2=5;
cc[29][1].c1=cc[29][2].c1=cc[29][3].c1=cc[29][4].c1=cc[29][6].c1='r';
cc[29][1].c2=cc[29][2].c2=cc[29][3].c2=cc[29][4].c2=cc[29][6].c2=7;
cc[1][7].c1='o';
//以上规约完成
bb[0][0]=1;bb[0][1]=2;bb[0][2]=3;bb[4][0]=10;bb[4][1]=11;bb[4][2]=12;
bb[6][1]=15;bb[6][2]=3;bb[7][1]=16;bb[7][2]=3;bb[8][2]=17;bb[9][2]=18;
bb[13][0]=24;bb[13][1]=11;bb[13][2]=12;bb[20][1]=25;bb[20][2]=12;
bb[21][1]=26;bb[21][2]=12;bb[22][2]=27;bb[23][2]=28;
//以上goto
MM[0].num=3;MM[1].num=3;MM[2].num=1;MM[3].num=3;MM[4].num=3;MM[5].num=1;MM[6].num=3;MM[7].num=1;
MM[0].you="E->E+T";MM[0].zuo='E';
MM[1].you="E->E-T";MM[1].zuo='E';
MM[2].you="E->T";MM[2].zuo='E';
MM[3].you="T->T*F";MM[3].zuo='T';
MM[4].you="T->T/F";MM[4].zuo='T';
MM[5].you="T->F";MM[5].zuo='T';
MM[6].you="F->(E)";MM[6].zuo='F';
MM[7].you="F->id";MM[7].zuo='F';
for(p1=0;p1<30;p1++)
{
for(p2=0;p2<8;p2++)
{
if(cc[p1][p2].c1=='r')
cc[p1][p2].st="归约";
if(cc[p1][p2].c1=='s')
cc[p1][p2].st="移近";
}
}
}
void CuoWu()
{
cc[0][1].c1=cc[0][2].c1=cc[0][3].c1=cc[0][4].c1=cc[0][7].c1=cc[6][1].c1=cc[6][2].c1=cc[6][3].c1=cc[6][4].c1=cc[7][1].c1=cc[7][2].c1=cc[7][3].c1=cc[7][4].c1='a';
cc[8][1].c1=cc[8][2].c1=cc[8][3].c1=cc[8][4].c1=cc[9][1].c1=cc[9][2].c1=cc[9][3].c1=cc[9][4].c1=cc[6][7].c1=cc[7][7].c1=cc[8][7].c1=cc[9][7].c1=cc[6][6].c1=cc[7][6].c1=cc[8][6].c1=cc[9][6].c1='a';
cc[4][1].c1=cc[4][2].c1=cc[4][3].c1=cc[4][4].c1=cc[13][1].c1=cc[13][2].c1=cc[13][3].c1=cc[13][4].c1=cc[20][7].c1=cc[21][7].c1=cc[22][7].c1=cc[23][7].c1=cc[20][6].c1=cc[21][6].c1=cc[22][6].c1=cc[23][6].c1='a';
cc[20][1].c1=cc[20][2].c1=cc[20][3].c1=cc[20][4].c1=cc[21][1].c1=cc[21][2].c1=cc[21][3].c1=cc[21][4].c1=cc[22][1].c1=cc[22][2].c1=cc[22][3].c1=cc[22][4].c1=cc[23][1].c1=cc[23][2].c1=cc[23][3].c1=cc[23][4].c1='a';
cc[0][6].c1=cc[5][6].c1=cc[19][6].c1='b';
cc[4][6].c1=cc[13][6].c1='c';
cc[19][5].c1=cc[3][5].c1=cc[29][5].c1='d';
cc[5][5].c1=cc[5][0].c1=cc[14][0].c1=cc[14][5].c1='e';
cc[14][7].c1=cc[4][7].c1=cc[24][7].c1=cc[12][7].c1=cc[29][7].c1='f';
}
void a()
{
printf("error\t缺少操作数\n");
if(S.top()==20+48)
S.push(12+48);
else if(S.top()==21+48)
S.push(12+48);
else if(S.top()==22+48)
S.push(27+48);
else if(S.top()==23+48)
S.push(28+48);
else
S.push(5+48);
}
void b()
{
printf("error\t多余右括号\n");
nn=nn+1;
ch=s[nn];
}
void c()
{
printf("error\t括号里没有东西\n");
if(S.top()==4+48)
S.push(10+48);
else
S.push(24+48);
}
void d() //右括号后面直接左括号
{
printf("error\t缺少运算符\n");
S.pop();S.pop();S.pop();
if(S.top()==4+48)
{S.push(10+28);S.push(20+48);}
else if(S.top()==13+48||S.top()==20+48)
{S.push(24+48);S.push(20+48);}
else
{S.push(3+48);S.push(6+48);}
}
void e()
{
printf("error\t缺少运算符\n");
S.pop();
if(S.top()==4+48)
{S.push(10+48);S.push(20+48);}
else if(S.top()==13+48)
{S.push(24+48);S.push(20+48);}
else
{S.push(1+48);S.push(6+48);}
}
void f()
{
if(S.top()!=29+48)
{printf("error\t缺少右括号\n");TEMP++;}
while(S.top()!=13+48&&S.top()!=4+48)
{
S.pop();
}
if(S.top()==13+48)
{S.pop();S.push(12+48);}
else
{S.pop();S.push(3+48);}
}
int FeiZhong(char t) //非终结符数字化
{
if(t=='E') return 0;
if(t=='T') return 1;
if(t=='F') return 2;
}
void display()
{
cout<<"action"<<endl;
for(p1=0;p1<30;p1++)
{
for(p2=0;p2<8;p2++)
{
if(cc[p1][p2].c1=='s'||cc[p1][p2].c1=='r')
cout<<cc[p1][p2].c1<<cc[p1][p2].c2;
else
cout<<cc[p1][p2].st;
printf("\t");
}
cout<<endl;
}
cout<<"goto"<<endl;
for(p1=0;p1<30;p1++)
{
for(p2=0;p2<3;p2++)
printf("%d\t",bb[p1][p2]);
cout<<endl;
}
cout<<"chanshengshi"<<endl;
for(p1=0;p1<8;p1++)
printf("%d\t%s\t%c\n",MM[p1].num,MM[p1].you,MM[p1].zuo);
}
void fenxi(int m,char t)
{
if(cc[m][zhong(t)].c1=='s')
{
printf("%d\t%s\t%s",S.top()-48,s+nn,cc[m][zhong(t)].st);
if(t=='i')
printf("id\n");
else
printf("%c\n",t);
S.push(cc[m][zhong(t)].c2+48);
if(t=='i')
nn=nn+2;
else
nn=nn+1;
ch=s[nn];
}
else if(cc[m][zhong(t)].c1=='r')
{
printf("%d\t%s\t%s\t%s\n",S.top()-48,s+nn,cc[m][zhong(t)].st,MM[cc[m][zhong(t)].c2-1].you);
for(p1=0;p1<MM[cc[m][zhong(t)].c2-1].num;p1++)
S.pop();
temp2=FeiZhong(MM[cc[m][zhong(t)].c2-1].zuo);
temp1=bb[S.top()-48][temp2];
S.push(temp1+48);
}
else if(cc[m][zhong(t)].c1=='o')
{
flag=1;
}
else
{
if(cc[m][zhong(t)].c1=='a')
a();
if(cc[m][zhong(t)].c1=='b')
b();
if(cc[m][zhong(t)].c1=='c')
c();
if(cc[m][zhong(t)].c1=='d')
d();
if(cc[m][zhong(t)].c1=='e')
e();
if(cc[m][zhong(t)].c1=='f')
f();
}
}
void FENXI()
{
ch=s[nn];
cout<<"语法分析!"<<endl;
printf("栈顶:\n");
while(1)
{
fenxi(S.top()-48,ch);
if(flag==1)
{
printf("%d\t%s\t接受\tE'->E\n",S.top()-48,s+nn);
cout<<"语法正确!"<<endl;
break;
}
}
}
int main()
{
cout<<"请输入词法流!(以#结束)"<<endl;
gets(s);
length=strlen(s);
s[length]=s[length-1];
s[length-1]='$';
S.push('0');
ChuShiHua();
CuoWu();
//display();
FENXI();
system("pause");
return 0;
}