⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unit1.cpp

📁 编译原理的详细修改和实验报告。。修改了PL0语言的一些功能。。增加了一部分功能。里面有详细报告。。可供参详
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		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 + -