📄 suanfuyouxian.cpp
字号:
#include<iostream>
#include <string.h>
using namespace std;
void getch();
void testchar();
typedef struct tag_token /* 存放种别码和值的 */
{
int sym;
char symbol[20];
}token[100];
static token token_PL;
static int cc=0;
static int j=0;
static char line[200];
static token s;
char ch;
int errorflag;
int form[10][10]={3,3,2,2,2,3,2,2,0,3,
3,3,2,2,2,3,2,2,0,3,
3,3,3,3,2,3,2,2,0,3,
3,3,3,3,2,3,2,2,0,3,
2,2,2,2,2,1,2,2,0,0,
3,3,3,3,0,3,0,0,0,3,
3,3,3,3,0,3,0,0,0,3,
3,3,3,3,0,3,0,0,1,3,
2,2,2,2,2,0,2,2,0,3,
0,0,0,0,0,0,0,2,0,1};
int str1[5]={7,8,11};
int str2[5]={11,0,11};
int str3[5]={11,1,11};
int str4[5]={11,2,11};
int str5[5]={11,3,11};
int str6[5]={4,11,5};
int str7[5]={6};
int str8[5]={7};
int str9[5]={9,11,9};
void testchar()
{
int k;
// int i;
char A[20];
while(ch!='\n')
{
if((ch>='A' && ch<='Z') || (ch>='a' && ch<='z'))
/* 判断取出的字是否为字母 */
{
k=0;
A[k]=ch;
k=k+1;
getch();
while(1)
{
if((ch>'A' && ch<'Z') || (ch>='a' && ch<='z') ||(ch>='0' && ch<='9'))
{
if(k<20)
{
A[k]=ch;
k=k+1;
getch();
}
else
{
getch();
/* k>10则继续取词,但对后面的不错处理,截取前10个 */
}
}
else
{
cc-=1;
break;
}
}
A[k]='\0';
token_PL[j].sym=7;
strcpy(token_PL[j].symbol,A);
j=j+1;
}
else if(ch>='0' && ch<='9') /* 判断是否为数字 */
{
int flag=0;
k=0;
A[k]=ch;
k=k+1;
getch();
while(1)
{
if(ch>='0' && ch<='9')
{
if(k<20)
{
A[k]=ch;
k=k+1;
getch();
}
else
{
getch();
}
}
else
{
cc-=1;
break;
}
}
if(ch=='.')
{cc++;
A[k]=ch;
k=k+1;
getch();
if(ch>='0' && ch<='9')
{
flag=2;
A[k]=ch;
k=k+1;
getch();
while(1)
{
if(ch>='0' && ch<='9')
{
if(k<20)
{
A[k]=ch;
k=k+1;
getch();
}
else
{
getch();
}
}
else
{
cc-=1; break;
}
}
}
else
{cc-=1;
errorflag=1;
token_PL[j].sym=10;
A[k]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1;
}
}
else flag=1;
if(flag==2)
{token_PL[j].sym=6;
A[k]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1; }
else if(flag==1)
{token_PL[j].sym=6;
A[k]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1;
}
}
else if(ch=='+') /* 是否为操作符 */
{
k=0;
A[k]=ch;
token_PL[j].sym=0;
A[k+1]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1;
}
else if(ch=='=') /* 是否为操作符 */
{
k=0;
A[k]=ch;
token_PL[j].sym=8;
A[k+1]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1;
}
else if(ch=='-')
{
k=0;
A[k]=ch;
token_PL[j].sym=1;
A[k+1]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1;
}
else if(ch=='*')
{
k=0;
A[k]=ch;
token_PL[j].sym=2;
A[k+1]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1;
}
else if(ch=='/')
{
k=0;
A[k]=ch;
token_PL[j].sym=3;
A[k+1]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1;
}
else if(ch=='(')
{
k=0;
A[k]=ch;
token_PL[j].sym=4;
A[k+1]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1;
}
else if(ch==')')
{
k=0;
A[k]=ch;
token_PL[j].sym=5;
A[k+1]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1;
}
else if(ch=='#')
{
k=0;
A[k]=ch;
token_PL[j].sym=9;
A[k+1]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1;
}
else if(ch!=' '&&ch!=NULL)
{
k=0;
A[k]=ch;
errorflag=1;
token_PL[j].sym=10;
A[k+1]='\0';
strcpy(token_PL[j].symbol,A);
j=j+1;
}
getch();
}
strcpy(token_PL[j].symbol,"#");
token_PL[j].sym=9;
}
int judge(int jj,int a)
{
int i=jj,j=a;
if(form[i][j]==3) return 3;
else if(form[i][j]==2)
return 2;
else if(form[i][j]==1)
return 1;
else return 0;
}
void print(int q,int u,int j,int k)//打印归约的过程
{
cout<<u<<" ";
for(int i=0;i<=k;i++)
cout<<s[i].symbol;
cout<<" ";
for(i=q;i<=j;i++)
cout<<token_PL[i].symbol;
cout<<" ";
}
int IsVN(int k)
{
if(s[k].sym==11)
return 1;
else return 0;
}
void process()//对输入的字符串进行归约的过程
{
cout<<"步骤"<<" "<<"符号栈"<<" "<<"剩余符号串"<<" "<<"移进或规约"<<endl;
int k=0,q=0,u=1,b,i,jj;
int a;
s[k].sym=token_PL[q].sym;
strcpy(s[k].symbol,token_PL[q].symbol);
q++;
print(q,u,j,k);
while(q<=j)
{
a=token_PL[q].sym;
if(!IsVN(k)) jj=k;
else jj=k-1;
b=judge(s[jj].sym,a);
if(b==3)//大于的情况进行归约
{if(s[jj].sym!=8)
{ while(IsVN(jj-1))
jj--;
if(judge(s[jj-1].sym,s[jj+1].sym)==1)
jj=jj-1;
int g[5]={0,0,0};
for(int c=0;c<=k-jj;c++)
{g[c]=s[c+jj].sym;}
int y=(g[0]==str1[0]&&g[1]==str1[1]&&g[2]==str1[2])
||(g[0]==str2[0]&&g[1]==str2[1]&&g[2]==str2[2])
||(g[0]==str3[0]&&g[1]==str3[1]&&g[2]==str3[2])
||(g[0]==str4[0]&&g[1]==str4[1]&&g[2]==str4[2])
||(g[0]==str5[0]&&g[1]==str5[1]&&g[2]==str5[2])
||(g[0]==str6[0]&&g[1]==str6[1]&&g[2]==str6[2])
||(g[0]==str7[0]&&g[1]==str7[1]&&g[2]==str7[2])
||(g[0]==str8[0]&&g[1]==str8[1]&&g[2]==str8[2])
||(g[0]==str9[0]&&g[1]==str9[1]&&g[2]==str9[2]);
if(y==1) cout<<"";
else break;
for(i=jj;i<=k;i++)
{
s[i].sym=NULL;
strcpy(s[i].symbol,"");}
k=jj;
s[k].sym=11;strcpy(s[k].symbol,"E");
u++;
cout<<"归约"<<endl;
print(q,u,j,k);
}
else {jj--;
if(judge(s[jj-1].sym,s[jj+1].sym)==1)
jj=jj-1;
/*for(int m=jj;m>=0;m--)
{while(IsVN(m-1))
m--;
if(judge(s[m-1].sym,s[m+1].sym)==1)
jj=m-1;
else if(judge(s[m-1].sym,s[m+1].sym)==2)
{jj=m;m=-1;}
}*/
int g[5]={0,0,0};
for(int c=0;c<=k-jj;c++)
{g[c]=s[c+jj].sym;}
int y=(g[0]==str1[0]&&g[1]==str1[1]&&g[2]==str1[2])
||(g[0]==str2[0]&&g[1]==str2[1]&&g[2]==str2[2])
||(g[0]==str3[0]&&g[1]==str3[1]&&g[2]==str3[2])
||(g[0]==str4[0]&&g[1]==str4[1]&&g[2]==str4[2])
||(g[0]==str5[0]&&g[1]==str5[1]&&g[2]==str5[2])
||(g[0]==str6[0]&&g[1]==str6[1]&&g[2]==str6[2])
||(g[0]==str7[0]&&g[1]==str7[1]&&g[2]==str7[2])
||(g[0]==str8[0]&&g[1]==str8[1]&&g[2]==str8[2])
||(g[0]==str9[0]&&g[1]==str9[1]&&g[2]==str9[2]);
if(y==1) cout<<"";
else break;
for(i=jj;i<=k;i++)
{
s[i].sym=NULL;
strcpy(s[i].symbol,"");}
k=jj;
s[k].sym=11;strcpy(s[k].symbol,"E");
u++;
cout<<"归约"<<endl;
print(q,u,j,k);}
}
else if(b==2||b==1)//小于或等于的情况移进
{
k++;
s[k].sym=a;strcpy(s[k].symbol,token_PL[q].symbol);
u++;
q++;
if(s[0].sym==9&&s[1].sym==11&&s[2].sym==9)
cout<<"接受"<<endl;
else cout<<"移进"<<endl;
print(q,u,j,k);
}
else
{cout<<"出错"<<endl;break;}
}
if(s[0].sym==9&&s[1].sym==11&&s[2].sym==9)
cout<<"归约成功"<<endl;
else cout<<"归约失败"<<endl;
}
void getch()
{
if(line[0]==NULL)
/*如果缓冲中第一个位置为空的话,就认为未有语句输入*/
{
int i=0;
line[i]='#';
do
{
i++;
line[i]=getchar();
}while(line[i-1]!='\n');}
ch=line[cc];
cc++;
}
void print1()
{
int i;
cout<<" 进行词法分析时出错"<<endl;
testchar();
for(i=0;i<j;i++)
{ if(token_PL[i].sym==10)
cout<<token_PL[i].symbol<<"的书写不符合词法规则!"<<endl;
}
}
void main()
{
cout<<"请输入要规约的字符串:"<<endl;
testchar();
if(errorflag==1)
print1();
else{
cout<<"下面是规约的过程:"<<endl;
process();}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -