📄 unit1.cpp
字号:
while (SYM==IDENT||SymIn(SYM, SymSetAdd(SEMICOLON,STATBEGSYS))) {
if (SYM==SEMICOLON||b) { if(b) b=0; else GetSym(); }
else Error(10);
STATEMENT(SymSetUnion(SymSetNew(SEMICOLON,ENDSYM),FSYS),LEV,TX);
}
if (SYM==ENDSYM) GetSym();
else Error(17);
break;
case WHILESYM:
CX1=CX; GetSym(); CONDITION(SymSetAdd(DOSYM,FSYS),LEV,TX);
CX2=CX; GEN(JPC,0,0);
if (SYM==DOSYM) GetSym();
else Error(18);
STATEMENT(FSYS,LEV,TX);
GEN(JMP,0,CX1);
CODE[CX2].A=CX;
break;
case FORSYM: //7 添加for
GetSym(); //PASCAL语法 FOR <变量> := <运算表达式> TO|DOWNTO <运算表达式> DO
if(SYM==IDENT)
{
i=POSITION(ID,TX);
if(i==0) Error(11);
else
{ //变量为常数或过程都出错
if(TABLE[i].KIND==CONSTANT||TABLE[i].KIND==PROCEDUR)
{
Error(12);
i=0;
}
if(TABLE[i].KIND==ARR)
{
ARRGetSub(FSYS,LEV,TX);
jk=0;
}
if(TABLE[i].IsVAR) //处理变量是否为按地址传递的参数
{
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
jk=2;
}
}//else if(i==0)
GetSym();
if(SYM==BECOMES) //变量赋初始值
{
GetSym(); //第一个运算表达式
EXPRESSION(SymSetUnion(SymSetNew(TOSYM,DOWNTOSYM),FSYS),LEV,TX);
}
if(SYM==TOSYM) //如果为TO
{
CX1=CX; //CX1记录当前代码段作为开始循环位置
GEN(STOMode[jk],LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //把数存进变量中
GEN(LODMode[jk],LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //读取此变量的数,放入栈顶
GetSym();
EXPRESSION(SymSetUnion(SymSetNew(DOSYM),FSYS),LEV,TX); //计算第二个运算表达式,放入栈顶
GEN(OPR,0,13); //判断运算是否大于
CX2=CX; GEN(JPC,0,0); //CX2记录当前代码段,用于JPC的跳转地址回填
Temp=TOSYM;
}
else if(SYM==DOWNTOSYM) //DOWNTO 类似 TO,不同处为判断预算选是否小于
{
CX1=CX;
GEN(STOMode[jk],LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LODMode[jk],LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GetSym();
EXPRESSION(SymSetUnion(SymSetNew(DOSYM),FSYS),LEV,TX);
GEN(OPR,0,11);
CX2=CX; GEN(JPC,0,0);
Temp=DOWNTOSYM;
}
else Error(19);
if(SYM==DOSYM) GetSym(); //做DO后面的<语句>
else Error(18);
STATEMENT(FSYS,LEV,TX);
GEN(LODMode[jk],LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //读取变量的值,放入栈顶
GEN(LIT,0,1); //步长为1
switch(Temp)
{
case DOWNTOSYM: GEN(OPR,0,3); break; //DOWNTOSYM 就减 1
case TOSYM: GEN(OPR,0,2); break; //TOSYM 就加 1
}
GEN(JMP,0,CX1); //无条件跳转到CX1记录的地址段
CODE[CX2].A=CX; //回填JPC的跳转地址
}// if(SYM)
else Error(97);
break;
}
TEST(FSYS,SymSetNULL(),19);
} /*STATEMENT*/
//---------------------------------------------------------------------------
//编译程序主体
void Block(int LEV, int TX, SYMSET FSYS) {
int DX=3; /*DATA ALLOCATION INDEX*/
int TX0=TX; /*INITIAL TABLE INDEX*/
int CX0=CX; /*INITIAL CODE INDEX*/
//int n=0;
TABLE[TX-n].vp.ADR=CX; GEN(JMP,0,0);
if (LEV>LEVMAX) Error(32);
do {
if (SYM==CONSTSYM) {
GetSym();
do {
ConstDeclaration(LEV,TX,DX);
while (SYM==COMMA) {
GetSym(); ConstDeclaration(LEV,TX,DX);
}
if (SYM==SEMICOLON) GetSym();
else Error(5);
}while(SYM==IDENT);
}
if (SYM==VARSYM) {
GetSym();
do {
VarDeclaration(LEV,TX,DX);
while (SYM==COMMA) { GetSym(); VarDeclaration(LEV,TX,DX); }
if (SYM==SEMICOLON) GetSym();
else Error(5);
}while(SYM==IDENT);
}
while ( SYM==PROCSYM) {
GetSym();
if (SYM==IDENT) { ENTER(PROCEDUR,LEV,TX,DX); GetSym(); }
else Error(4);
if (SYM==SEMICOLON) GetSym();
else if(SYM==LPAREN)
{
GetSym();
int dx=3;
VarDeclaration(LEV+1,TX,dx);
n++;
while (SYM==COMMA) { GetSym(); VarDeclaration(LEV+1,TX,dx);n++; }
if(SYM!=RPAREN) Form1->printls("错误CALL",200);
else GetSym();
}
else Error(5);
Block(LEV+1,TX,SymSetAdd(SEMICOLON,FSYS));
if (SYM==SEMICOLON) {
GetSym();
TEST(SymSetUnion(SymSetNew(IDENT,PROCSYM),STATBEGSYS),FSYS,6);
}
else Error(5);
}
TEST(SymSetUnion(SymSetNew(RPAREN,SEMICOLON),SymSetAdd(IDENT,STATBEGSYS)), DECLBEGSYS,7);
}while(SymIn(SYM,DECLBEGSYS));
CODE[TABLE[TX0-n].vp.ADR].A=CX;
TABLE[TX0-n].vp.ADR=CX; /*START ADDR OF CODE*/
TABLE[TX0-n].vp.SIZE=DX+n; /*SIZE OF DATA SEGMENT*/
//CX0=CX;
GEN(INI,0,DX+n);
n=0;
STATEMENT(SymSetUnion(SymSetNew(SEMICOLON,ENDSYM),FSYS),LEV,TX);
GEN(OPR,0,0); /*RETURN*/
TEST(FSYS,SymSetNULL(),8);
ListCode(CX0);
} /*Block*/
//---------------------------------------------------------------------------
//通过过程基址求上一层过程的基址
int BASE(int L,int B,int S[]) {
int B1=B; /*FIND BASE L LEVELS DOWN*/
while (L>0) { B1=S[B1]; L=L-1; }
return B1;
} /*BASE*/
//---------------------------------------------------------------------------
//解释程序
void Interpret() {
const STACKSIZE = 500;
int P,B,T; /*PROGRAM BASE TOPSTACK REGISTERS*/
INSTRUCTION I;
int S[STACKSIZE]; /*DATASTORE*/
Form1->printfs("\n~~~~~~~开始运行 PL0程序 ~~~\n");
fprintf(FOUT,"~~~ RUN PL0 ~~~\n");
T=0; B=0; P=0;
S[0]=0; S[1]=0; S[2]=0;
do {
I=CODE[P];
P=P+1;
switch (I.F) {
case LIT: S[T]=I.A; T++; break;
case OPR:
switch (I.A) { /*OPERATOR*/
case 0: T=B; P=S[T+2]; B=S[T+1]; break;
case 1: S[T-1]=-S[T-1]; break;
case 2: T--; S[T-1]=S[T-1]+S[T]; break;
case 3: T--; S[T-1]=S[T-1]-S[T]; break;
case 4: T--; S[T-1]=S[T-1]*S[T]; break;
case 5: T--; S[T-1]=S[T-1]/S[T]; break;
case 6: S[T-1]=S[T-1]%2; break;
case 8: T--; S[T-1]=S[T-1]==S[T]; break;
case 9: T--; S[T-1]=S[T-1]!=S[T]; break;
case 10: T--; S[T-1]=S[T-1]<S[T]; break;
case 11: T--; S[T-1]=S[T-1]>=S[T]; break;
case 12: T--; S[T-1]=S[T-1]>S[T]; break;
case 13: T--; S[T-1]=S[T-1]<=S[T]; break;
case 14: Form1->printls("",S[T-1]);
fprintf(FOUT,"%d\n",S[T-1]); T--; break;
case 15: /*Form1->printfs(""); fprintf(FOUT,"\n"); */ break;
case 16: S[T]=InputBox("输入","请键盘输入数字: ", 0).ToInt();
Form1->printls("? ",S[T]); fprintf(FOUT,"? %d\n",S[T]);
T++; break;
case 17: S[T]++; break; //
case 18: S[T]--; break;
}
break;
case LOD: S[T]=S[BASE(I.L,B,S)+I.A];T++; break;
case STO: T--; S[BASE(I.L,B,S)+I.A]=S[T]; break;
case CAL: /*GENERAT NEW Block MARK*/
S[T]=BASE(I.L,B,S); S[T+1]=B; S[T+2]=P;
B=T; P=I.A;
break;
case INI: T=T+I.A; break;
case JMP: P=I.A; break;
case JPC: T--;
if (S[T]==0) P=I.A; break;
case PUSH: T--; S[T+I.A+3]=S[T]; break;
case STOPAR: S[T+(int)I.A]=S[T]; T--; break;
case STOARR: S[BASE(I.L,B,S)+(int)I.A+(int)S[(T-1)]]=S[T]; T--; break; //+++++对数组的存储 S[T-1]放入了偏移地址
case LODARR: S[T]=S[BASE(I.L,B,S)+(int)I.A+(int)S[T]]; break; //+++++对数组的读取 第二个S[T]是放入偏移地址的
case LODVAR: S[T]=S[BASE(I.L,B,S)+(int)S[T]]; break; //+++++对地址变量的读取
case STOVAR: S[BASE(I.L,B,S)+(int)S[(T-1)]]=S[T]; T--; T--; break; //+++++对地址变量的存储
} /*switch*/
}while(P!=0);
Form1->printfs("~~~ PL0程序运行完毕 ~~~");
fprintf(FOUT,"~~~ END PL0 ~~~\n");
} /*Interpret*/
//--------------------------------------------------------------------
// 主函数(程序入口)
void __fastcall TForm1::ButtonRunClick(TObject *Sender) {
for (CH=' '; CH<='^'; CH++) SSYM[CH]=NUL; //62
//设置字符符号
SSYM['*']=TIMES;
SSYM['/']=SLASH;
SSYM['(']=LPAREN;
SSYM[')']=RPAREN;
SSYM['=']=EQL;
SSYM[',']=COMMA;
SSYM['.']=PERIOD;
SSYM[';']=SEMICOLON;
//设置保留字名字
strcpy(KWORD[ 1],"BEGIN");
strcpy(KWORD[ 2],"CALL");
strcpy(KWORD[ 3],"CONST");
strcpy(KWORD[ 4],"DO");
strcpy(KWORD[ 5],"DOWNTO"); //downto
strcpy(KWORD[ 6],"ELSE"); //else
strcpy(KWORD[ 7],"END");
strcpy(KWORD[ 8],"FOR"); //for
strcpy(KWORD[ 9],"IF");
strcpy(KWORD[10],"ODD");
strcpy(KWORD[11],"PROCEDURE");
strcpy(KWORD[12],"PROGRAM");
strcpy(KWORD[13],"READ");
strcpy(KWORD[14],"RETURN"); //return
strcpy(KWORD[15],"THEN");
strcpy(KWORD[16],"TO"); //to
strcpy(KWORD[17],"VAR");
strcpy(KWORD[18],"WHILE");
strcpy(KWORD[19],"WRITE");
//设置保留字符号
WSYM[ 1]=BEGINSYM;
WSYM[ 2]=CALLSYM;
WSYM[ 3]=CONSTSYM;
WSYM[ 4]=DOSYM;
WSYM[ 5]=DOWNTOSYM;//downto
WSYM[ 6]=ELSESYM; //else
WSYM[ 7]=ENDSYM;
WSYM[ 8]=FORSYM; //for
WSYM[ 9]=IFSYM;
WSYM[10]=ODDSYM;
WSYM[11]=PROCSYM;
WSYM[12]=PROGSYM;
WSYM[13]=READSYM;
WSYM[14]=RETURNSYM;//return
WSYM[15]=THENSYM;
WSYM[16]=TOSYM; //to
WSYM[17]=VARSYM;
WSYM[18]=WHILESYM;
WSYM[19]=WRITESYM;
//设置指令名称
strcpy(MNEMONIC[LIT],"LIT"); strcpy(MNEMONIC[OPR],"OPR");
strcpy(MNEMONIC[LOD],"LOD"); strcpy(MNEMONIC[STO],"STO");
strcpy(MNEMONIC[CAL],"CAL"); strcpy(MNEMONIC[INI],"INI");
strcpy(MNEMONIC[JMP],"JMP"); strcpy(MNEMONIC[JPC],"JPC");
strcpy(MNEMONIC[PUSH],"PUSH");
DECLBEGSYS=(int*)malloc(sizeof(int)*44);
STATBEGSYS=(int*)malloc(sizeof(int)*44);
FACBEGSYS =(int*)malloc(sizeof(int)*44);
//设置符号集
for(int j=0; j<44; j++) {
DECLBEGSYS[j]=0; STATBEGSYS[j]=0; FACBEGSYS[j] =0;
}
//设置声明开始符号集
DECLBEGSYS[CONSTSYM]=1;
DECLBEGSYS[VARSYM]=1;
DECLBEGSYS[PROCSYM]=1;
//设置语句开始符号集
STATBEGSYS[BEGINSYM]=1;
STATBEGSYS[CALLSYM]=1;
STATBEGSYS[IFSYM]=1;
STATBEGSYS[WHILESYM]=1;
STATBEGSYS[WRITESYM]=1;
//设置因子开始符号集
FACBEGSYS[IDENT] =1;
FACBEGSYS[NUMBER]=1;
FACBEGSYS[LPAREN]=1;
//打开程序文件并保存运行结果
if ((FIN=fopen((Form1->EditName->Text+".PL0").c_str(),"r"))!=0) {
FOUT=fopen((Form1->EditName->Text+".COD").c_str(),"w");
Form1->printfs("=== 编译 PL0程序 ===");
fprintf(FOUT,"=== COMPILE PL0 ===\n");
ERR=0;
CC=0; CX=0; LL=0; CH=' ';
GetSym();
if (SYM!=PROGSYM) Error(0);
else {
GetSym();
if (SYM!=IDENT) Error(0);
else {
GetSym();
if (SYM!=SEMICOLON) Error(5);
else GetSym();
}
}// PROGSYM->名字->;-->
Block(0,0,SymSetAdd(PERIOD,SymSetUnion(DECLBEGSYS,STATBEGSYS)));
if (SYM!=PERIOD) Error(9); //.........
if (ERR==0) Interpret();
else {
Form1->printfs("PL/0程序出现错误");
fprintf(FOUT,"ERROR IN PL/0 PROGRAM");
}
fprintf(FOUT,"\n");
fclose(FOUT);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -