📄 结合.cpp
字号:
#include <iostream.h>
#include <fstream.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <stdio.h>
int E_stack[10],T_stack[10],top_E_stack=-1,top_T_stack=-1;
char str[500];
char word[20];
char filename[50];
int num_stack[20]; int num_top=0;//状态压进数字栈
char *id_stack[20];int id_top=-1;//符号压入符号栈
char *X[37]={"(",")",";","id",":","int","=","else","if","then","{","}","while","do","+","*","and","<","num","$",
"P","D","A","S","L","Q","G","C","B","N","U","E","T","F","I","M","W"};
struct sym_table{
char name[20];
int bianma;
char type[4];
int addr;
}symtable[100];//符号表结构
int m=0;//符号表入口
int enterstack[50];//语义中用于顺序记住数字或标识符符号表入口的栈
int top_enterstack=-1;
struct mid_code{
int one;
int two;
int three;
int four;
}fourgroup[100];//伪四元式
int newtemp=99;
int nextquad=0;
int offset=0;
int A_width,S_nextlist,L_nextlist,U_nextlist,G_nextlist,C_nextlist,W_head,U_head,N_quad,M_quad,
B_truelist,B_falselist,F_place,I_place,id_place,M_truelist,M_falselist;
void enter(int entry_addr,int offset)
{ strcpy(symtable[entry_addr].type,"int");
symtable[entry_addr].addr=offset;
}
void emit(int a,int b,int c,int d)
{ ++nextquad;
fourgroup[nextquad].one=a;
fourgroup[nextquad].two=b;
fourgroup[nextquad].three=c;
fourgroup[nextquad].four=d;
}
int merge(int p1,int p2)
{ int p;
if(p2==0) return p1;
else
{ p=p2;
while(fourgroup[p].four!=0)
p=fourgroup[p].four;
fourgroup[p].four=p1;
return p2;
}
}
void backpatch(int p,int t)
{ int q,Q;
Q=p;
while(Q!=0)
{ q=fourgroup[Q].four;
fourgroup[Q].four=t;
Q=q;
}
}
void load()//用来把文件中的内容放到缓冲区中
{ int i=0;
char c;
ifstream infile(filename);
while (infile.get(c))
str[i++]=c;
str[i]='\0';
}
void cifa()//词法
{ int i,j,s,k,line=1;
i=0;s=0;
int sign=0;
FILE *fp;
ofstream OutFile1("token.txt");
cout<<"输入要打开的文件(路径、名称):";//提示用户键入路径名
F: cin.getline(filename,50);
fp=fopen(filename,"r");
while (fp==NULL)//若文件不存在,则要求继续输入文件的路径与名称
{ cout<<"文件不存在,请重新输入!"<<endl;
goto F;
}
load();//把文件中的内容放入缓冲区
fclose(fp);
A: i=s;
if(i<500 && str[i]!='\0')
{ if(isalpha(str[i]))//---------------------字母
{ k=0;
word[k++]=str[i];
while(isalpha(str[i+1]) || isdigit(str[i+1]))
{ word[k++]=str[++i];
s=i+1;
}
if(k==1) s=i+1;
word[k]='\0';
if(strcmp(word,"id")!=0 && strcmp(word,"num")!=0)
for(j=0;j<19;j++)//用来判断取出的当前单词是不是关键词
if(strcmp(word,X[j])==0)
{ OutFile1<<j<<" "<<-1<<endl; goto A; }
for (j=0;j<19;j++) if(strcmp(X[j],"id")==0) break;
for(i=0;i<100 && strcmp(symtable[i].name,"")==1;i++)
if(strcmp(word,symtable[i].name)==0)
{ OutFile1<<j<<" "<<i<<endl;goto A; }
OutFile1<<j<<" "<<i<<endl;
strcpy(symtable[i].name,word);
symtable[i].bianma=j;
goto A;
}
if(isdigit(str[i]))//---------------------数字
{ int k=0;
word[k++]=str[i];
while(isdigit(str[i+1])) {word[k++]=str[++i];s=i+1;}
if(k==1) s=i+1;
word[k]='\0';
for (j=0;j<19;j++) if(strcmp(X[j],"num")==0) break;
for(i=0;i<100 &&strcmp(symtable[i].name,"")==1;i++)
if(strcmp(word,symtable[i].name)==0)
{ OutFile1<<j<<" "<<i<<endl;goto A; }
OutFile1<<j<<" "<<i<<endl;
strcpy(symtable[i].name,word);
symtable[i].bianma=j;
goto A;
}
if(str[i]!=' ' && str[i]!='\n')
{ s=i+1;
word[0]=str[i];word[1]='\0';
for(j=0;j<19;j++)
if(strcmp(X[j],word)==0)
{ OutFile1<<j<<" "<<-1<<endl;
goto A;
}
cout<<filename<<"("<<line<<"):Error:'"<<str[i]<<"':illegal character!"<<endl;
goto A;
}
else
{ while(str[i]==' ' || str[i]=='\n')
{ if(str[i]=='\n') line++;i++;s=i;} //------除去空格和回车
goto A;
}
}
OutFile1<<19<<" "<<19<<endl;
}
void main()
{ int i=0,j=0,num1,num2,n=3,k=0,sk,slr[61][37];
char comma;
char *p[30]={"P'->P","P->D","D->id()D;S","D->D;D","D->id:A","A->int",
"S->id=QE","Q->ε","S->GS","S->CS","G->CSelse","C->if(B)then",
"S->{L}","L->L;NS","L->S","N->ε","S->US","U->W(B)do",
"E->E+T","E->T","T->T*F","T->F","F->(E)","F->I","B->BandMB",
"B->id<I","I->id","I->num","M->ε" ,"W->while"};
char *A_type;
char *math_operator[5]={"+","*","=","J","J<"};
cifa();
ifstream slrtable("slrtable.html");
while(!slrtable.eof())
{ slrtable>>slr[i][(j++)%37]>>comma;
if(j%37==0) i++;
}
num_stack[0]=0;
ifstream infile1("token.txt");
while(!infile1.eof())
{ infile1>>num1>>num2;
A: if(slr[num_stack[num_top]][num1]>0)
{ if(num1==3 || num1==18)
enterstack[++top_enterstack]=num2;
if(slr[num_stack[num_top]][num1]==100) { cout<<"----------------"<<endl; break; }
id_stack[++id_top]=X[num1];
num_stack[num_top+1]=slr[num_stack[num_top]][num1];
num_top++;
}
else if(slr[num_stack[num_top]][num1]<0)
{ sk=abs(slr[num_stack[num_top]][num1]);
switch(sk){
case 1: break; //P->D
case 2: break; //D->id()D;S
case 3: break; //D->D;D
case 4: enter(enterstack[top_enterstack--],offset); offset=offset+A_width; break; //D->id:A
case 5: A_type="int"; A_width=4; break; //A->int
case 6: emit(2,E_stack[top_E_stack--],0,enterstack[top_enterstack--]); S_nextlist=0; break; //S->id=QE
case 7: break; //Q->ε
case 8: S_nextlist=merge(G_nextlist,S_nextlist); break; //S->GS
case 9: S_nextlist=merge(C_nextlist,S_nextlist); break; //S->CS
case 10: emit(3,0,0,0); G_nextlist=merge(S_nextlist,nextquad);
backpatch(C_nextlist,nextquad+1); break; //G->CSelse
case 11: backpatch(B_truelist,nextquad+1); C_nextlist=B_falselist; break; //C->if(B)then
case 12: S_nextlist=L_nextlist; break; //S->{L}
case 13: backpatch(L_nextlist,N_quad); L_nextlist=S_nextlist; break; //L->L;NS
case 14: L_nextlist=S_nextlist; break; //L->S
case 15: N_quad=nextquad+1; break; //N->ε
case 16: backpatch(S_nextlist,U_head); emit(3,0,0,U_head); S_nextlist=U_nextlist; break; //S->US
case 17: backpatch(B_truelist,nextquad+1); U_nextlist=B_falselist; U_head=W_head; break; //U->W(B)do
case 18: i=E_stack[top_E_stack--]; E_stack[++top_E_stack]=++newtemp; emit(0,i,T_stack[top_T_stack--],E_stack[top_E_stack]); break; //E->E+T
case 19: E_stack[++top_E_stack]=T_stack[top_T_stack--]; break; //E->T
case 20: i=T_stack[top_T_stack--]; T_stack[++top_T_stack]=++newtemp; emit(1,i,F_place,T_stack[top_T_stack]); break; //T->T*F
case 21: T_stack[++top_T_stack]=F_place; break; //T->F
case 22: F_place=E_stack[top_E_stack--]; break; //F->(E)
case 23: F_place=I_place; break; //F->I
case 24: backpatch(M_truelist,M_quad); B_truelist=B_truelist;
B_falselist=merge(M_falselist,B_falselist); break; //B->BandMB
case 25: B_truelist=nextquad+1; emit(4,enterstack[top_enterstack--],I_place, 0);
B_falselist=nextquad+1; emit(3,0,0,0); break; //B->id>I
case 26: I_place=enterstack[top_enterstack--]; break; //I->id
case 27: I_place=enterstack[top_enterstack--]; break; //I->num
case 28: M_quad=nextquad+1; M_truelist=B_truelist; M_falselist=B_falselist; break; //M->ε
case 29: W_head=nextquad+1; break; //W->while
}
cout<<p[sk]<<endl;
if(p[sk][0]=='Q' || p[sk][0]=='N' || p[sk][0]=='M') goto B;
while(p[sk][n]!='\0')
{ k++;
if((p[sk][n]>='a' && p[sk][n]<='z') &&
(p[sk][n-1]>='a' && p[sk][n-1]<='z'))
k--;
n++;
}
id_top-=k;
num_top-=k;
B: for(i=20;i<37;i++)
if(X[i][0]==p[sk][0]) break;
id_stack[++id_top]=X[i];
num_stack[num_top+1]=slr[num_stack[num_top++]][i];
n=3;
k=0;
goto A;
}
else cout<<"_________________________ERROR!"<<endl;
}
for(i=1;i<=nextquad;i++)
{ cout<<i<<": "<<"("<<math_operator[fourgroup[i].one]<<",";
if(fourgroup[i].two==0) cout<<" "<<",";
else if(fourgroup[i].two>=100) cout<<"t"<<fourgroup[i].two-100<<",";
else cout<<symtable[fourgroup[i].two].name<<",";
if(fourgroup[i].three==0) cout<<" "<<",";
else if(fourgroup[i].three>=100) cout<<"t"<<fourgroup[i].three-100<<",";
else cout<<symtable[fourgroup[i].three].name<<",";
if(fourgroup[i].four>=100) cout<<"t"<<fourgroup[i].four-100<<")"<<endl;
else if(fourgroup[i].four==0) cout<<" "<<")"<<endl;
else if(fourgroup[i].one==3 || fourgroup[i].one==4) cout<<fourgroup[i].four<<")"<<endl;
else cout<<symtable[fourgroup[i].four].name<<")"<<endl;
}
ofstream OutFile2("symboltable.txt");
OutFile2<<"序号 "<<"符号 "<<"编码 "<<"类型 "<<"偏移地址 "<<endl;
OutFile2<<"----------------------------------------"<<endl;
for(i=0;i<100 && symtable[i].bianma!=0;i++)
{ OutFile2<<i+1<<" "<<symtable[i].name<<" "<<symtable[i].bianma<<" "<<symtable[i].type<<" ";
if(strcmp(symtable[i].type,"int")!=0) OutFile2<<endl;
else OutFile2<<symtable[i].addr<<endl;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -