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

📄 编译原理.c

📁 编译原理中PL/0程序的编译过程.用C写的
💻 C
📖 第 1 页 / 共 2 页
字号:
		 case procedur:
			 table[(*ptx)].level=lev;                      /*过程名字*/
			 break;
	 }
 }
 /*
  *查找名字的位置
  *找到则返回在名字表中的位置,否则返回0
  *
  *idt:要查找的名字
  *tx:当前名字表尾指针
  */
int position(char *idt,int tx)
{
	int i;
	strcpy(table[0].name,idt);
	i=tx;
	while(strcmp(table[i].name,idt)!=0)
	{
		i--;
	}
	return i;
}
/*
 *常量声明处理
 */
int constdeclaration(int *ptx,int lev,int *pdx)
{
	if(sym==ident)
	{
		getsymdo;
		if(sym==eql||sym==becomes)
		{
			if(sym==becomes)
			{
				error(1);           /*把=写成了 := */
			}
			getsymdo;
			if(sym==number)
			{
				enter(constant,ptx,lev,pdx);
				getsymdo;
			}
			else
			{
				error(2);                      /*常量说明=后应市数字*/
			}
		}
		else
		{
			error(3);                    /*常量说明标识后应是=*/
		}
	}
	else
	{
		error(4);                 /*const后应是标识*/
	}
	return 0;
}
/*
 *变量声明处理
 */
int vardeclaration(int* ptx,int lev,int* pdx)
{
	if(sym==ident)
	{
		enter(variable,ptx,lev,pdx);//填写名字表
		getsymdo;
	}
	else
	{
		error(4);                  /*var后应是标识符*/
	}
	return 0;
}
/*
 *输出目标代码清单
 */
void listcode(int cx0)
{
	int i;
	if(listswitch)
	{
		for(i=cx0;i<cx;i++)
		{
			printf("%d %s %d %d\n",i,mnemonic[code[i].f],code[i].l,code[i].a);
			fprintf(fa,"%d %s %d %d\n",mnemonic[code[i].f],code[i].l,code[i].a);
		}
	}
}
/*
 *语句处理
 */


/*
 *表达式处理
 */
int statement(bool *fsys, int *ptx, int lev)
{
int i,cx1,cx2;
bool nxtlev[symnum];

if(sym==ident){
    i=position(id,*ptx);
    if(i==0){
     error(11);
    }
    else{
     if(table[i].kind!=variable){
      error(12);
      i=0;
     }
     else{
      getsymdo;
      if(sym==becomes){
       getsymdo;
      }
      else{
       error(13);
      }
      memcpy(nxtlev,fsys,sizeof(bool)*symnum);
      expressiondo(nxtlev,ptx,lev);
      if(i!=0){
       gendo(sto,lev-table[i].level,table[i].adr);
      }
     }
    }
}
else{
    if(sym==readsym){
     getsymdo;
     if(sym!=lparen){
      error(34);
     }
     else{
      do{
       getsymdo;
       if(sym==ident){
        i=position(id,*ptx);
       }
       else{
        i=0;
       }
       if(i==0){
        error(35);
       }
       else{
        gendo(opr,0,16);
        gendo(sto,lev-table[i].level,table[i].adr);
       }
       getsymdo;
      }while(sym==comma);
     }
     if(sym!=rparen){
      error(33);
      while(!inset(sym,fsys)){
       getsymdo;
      }
     }
     else{
      getsymdo;
     }
    }
    else{
     if(sym==writesym){
      getsymdo;
      if(sym==lparen){
       do{
        getsymdo;
        memcpy(nxtlev,fsys,sizeof(bool)*symnum);
        nxtlev[rparen]=true;
        nxtlev[comma]=true;
        expressiondo(nxtlev,ptx,lev);
        gendo(opr,0,14);
       }while(sym==comma);
       if(sym!=rparen){
        error(33);
       }
       else{
        getsymdo;
       }
      }
      gendo(opr,0,15);
     }
     else{
      if(sym==callsym){
       getsymdo;
       if(sym!=ident){
        error(14);
       }
       else{
        i=position(id,*ptx);
        if(i==0){
         error(11);
        }
        else{
         if(table[i].kind==procedur){
          gendo(cal,lev-table[i].level,table[i].adr);
         }
         else{
          error(15);
         }
        }
        getsymdo;
       }
      }
      else{
       if(sym==ifsym){
        getsymdo;
        memcpy(nxtlev,fsys,sizeof(bool)*symnum);
        nxtlev[thensym]=true;
        nxtlev[dosym]=true;
        conditiondo(nxtlev,ptx,lev);
        if(sym==thensym){
         getsymdo;
        }
        else{
         error(16);
        }
        cx1=cx;
        gendo(jpc,0,0);
        statementdo(fsys,ptx,lev);
        code[cx1].a=cx;
       }
       else{
        if(sym==beginsym){
         getsymdo;
         memcpy(nxtlev,fsys,sizeof(bool)*symnum);
         nxtlev[semicolon]=true;
         nxtlev[endsym]=true;
         statementdo(nxtlev,ptx,lev);
         while(inset(sym,statbegsys)||sym==semicolon){
          if(sym==semicolon){
           getsymdo;
          }
          else{
           error(10);
          }
          statementdo(nxtlev,ptx,lev);
         }
         if(sym==endsym){
          getsymdo;
         }
         else{
          error(17);
         }
        }
        else{
         if(sym==whilesym){
          cx1=cx;
          getsymdo;
          memcpy(nxtlev,fsys,sizeof(bool)*symnum);
          nxtlev[dosym]=true;
          conditiondo(nxtlev,ptx,lev);
          cx2=cx;
          gendo(jpc,0,0);
          if(sym==dosym){
           getsymdo;
          }
          else{
           error(18);
          }
          statementdo(fsys,ptx,lev);
          gendo(jmp,0,cx1);
          code[cx2].a=cx;
         }
         else{
          memset(nxtlev,0,sizeof(bool)*symnum);
          testdo(fsys,nxtlev,19);
         }
        }
       }
      }
     }
    }
}
return 0;
}
 int expression(bool *fsys,int *ptx,int lev)
 {
	 enum symbol addop;                   /*用于保存正负号*/
	 bool nxtlev[symnum];                 
	 if(sym==plus||sym==minus)            /*开头的正负号,此时当前表达式被看作一个正的
		                                    或负的项*/
	 {
		 addop=sym;                       /*保存开头的正负号*/
		 getsymdo;
		 memcpy(nxtlev,fsys,sizeof(bool)*symnum);
		 nxtlev[plus]=true;
		 nxtlev[minus]=true;
		 termdo(nxtlev,ptx,lev);         /*处理项*/
		 if(addop==minus)
		 {
			 gendo(opr,0,1);              /*如果开头为符号生成取负指令*/
		 }
	 }
	 else                                 /*此时表达式被看作项的加减*/
	 {
		 memcpy(nxtlev,fsys,sizeof(bool)*symnum);      
		 nxtlev[plus]=true;
		 nxtlev[minus]=true;
		 termdo(nxtlev,ptx,lev);               /*处理项*/
	 }
	 while(sym==plus||sym==minus)
	 {
		 addop=sym;
		 getsymdo;
		 memcpy(nxtlev,fsys,sizeof(bool)*symnum);
		 nxtlev[plus]=true;
		 nxtlev[minus]=true;
		 termdo(nxtlev,ptx,lev);            /*处理项*/
		 if(addop==plus)
		 {
			 gendo(opr,0,2);                /*生成加法指令*/
		 }
		 else
		 {
			 gendo(opr,0,3);               /*生成减法指令*/
		 }
	 }
	return 0;
 }
/*
 *处理项
 */
 int term(bool *fsys,int *ptx,int lev)
 {
	 enum symbol mulop;
	 bool nxtlev[symnum];                        /*用于保存乘除法符号*/
	 memcpy(nxtlev,fsys,sizeof(bool)*symnum);
	 nxtlev[times]=true;
	 nxtlev[slash]=true;
	 factordo(nxtlev,ptx,lev);                    /*处理因子*/
	 while(sym==times||sym==slash)
	 {
		 mulop=sym;
		 getsymdo;
		 factordo(nxtlev,ptx,lev);
		 if(mulop==times)
		 {
			 gendo(opr,0,4);                    /*生成乘法指令*/
		 }
		 else
		 {
			 gendo(opr,0,5);                   /*生成除法指令*/
		 }
	 }
	 return 0;
 }
 /*
  *因子处理
  */
int factor(bool *fsys,int *ptx,int lev)
{
	int i;
	bool nxtlev[symnum];
	testdo(facbegsys,fsys,24);
	while(inset(sym,facbegsys))
	{
		if(sym==ident)
		{
			i=position(id,*ptx);
			if(i==0)
			{
				error(11);
			}
			else
			{
				switch(table[i].kind)
				{
				     case constant:                                /*名字为常量*/
						 gendo(lit,0,table[i].val);                /*直接把常量的值入栈*/              
						 break;
                     case variable:                                        /*名字为变量*/
						 gendo(lod,lev-table[i].level,table[i].adr);       /*找到变量地址并将其入栈*/
						 break;
                     case procedur:                                 /*名字为过程*/
						 error(21);                                  /*不能为过程*/
						 break;
				}
			}
			getsymdo;
		}
		else
		{
			if(sym==number)                /*因子为数*/
			{
				if(num>amax)
				{
					error(31);
					num=0;
				}
				gendo(lit,0,num);
				getsymdo;
			}
			else
			{
				if(sym==lparen)         /*因子为表达式*/
				{
					getsymdo;
					memcpy(nxtlev,fsys,sizeof(bool)*symnum);
					nxtlev[rparen]=true;
					expressiondo(nxtlev,ptx,lev);
					if(sym==rparen)
					{
						getsymdo;
					}
					else
					{
						error(22);       /*缺少右括号*/
					}
				}
				testdo(fsys,facbegsys,23); /*因子后有非法符号*/
			}
		}
	}
	return 0;
}
/*
 *条件处理
 */
int condition(bool *fsys,int *ptx,int lev)
{
	enum symbol relop;
	bool nxtlev[symnum];
	if(sym==oddsym)                  /*准备按照odd运算处理*/
	{
		getsymdo;
		expressiondo(fsys,ptx,lev);
		gendo(opr,0,6);               /*生成odd指令*/
	}
	else
	{
		/*逻辑表达式处理*/
		memcpy(nxtlev,fsys,sizeof(bool)*symnum);
		nxtlev[eql]=true;
		nxtlev[neq]=true;
		nxtlev[lss]=true;
		nxtlev[leq]=true;
		nxtlev[gtr]=true;
		nxtlev[geq]=true;
		expressiondo(nxtlev,ptx,lev);
		if(sym!=eql && sym!=neq &&sym!=lss && sym!=leq && sym!=gtr && sym!=geq)
		{
			error(20);
		}
		else
		{
			relop=sym;
			getsymdo;
			expressiondo(fsys,ptx,lev);
			switch(relop)
			{
			    case eql:
					gendo(opr,0,8);
					break;
				case neq:
					gendo(opr,0,9);
					break;
                case lss:
					gendo(opr,0,10);
					break;
				case geq: 
					gendo(opr,0,11);
					break;
				case gtr:
					gendo(opr,0,12);
					break;
                case leq:
					gendo(opr,0,13);
					break;
			}
		}
	}
	return 0;
}
/*
 *解释程序
 */
void interpret()
{
	int p,b,t;               /*指令指针,指令基址,栈顶指针*/
	struct instruction i;      /*存放当前指令*/
	int s[stacksize];          /*栈*/
	printf("start pl0\n");
	t=0;
	b=0;
	p=0;
	s[0]=s[1]=s[2]=0;
	do
	{
		i=code[p];         /*读当前指令*/
		p++;
		switch(i.f)        
		{   
		  case lit:         /*将a的值取到栈顶*/
		      s[t]=i.a;
			  t++;
			  break;
		  case opr:         /*数学,逻辑运算*/
			  switch(i.a)
			  {
			    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:
				    printf("%d",s[t-1]);
				    fprintf(fa2,"%d",s[t-1]);
				    t--;
				    break;
                case 15:
				    printf("\n");
				    fprintf(fa2,"\n");
				    break;
			    case 16:
				    printf("?");
				    fprintf(fa2,"?");
				    scanf("%d",&(s[t]));
				    fprintf(fa2,"%d\n",s[t]);
				    t++;
				    break;
			  }
		      break;
		      case lod:                         /*取向对当前过程的数据基地址为a的内存的值取到栈顶*/
			      s[t]=s[base(i.l,s,b)+i.a];
			      t++;
			      break;
              case sto:                          /*栈顶的值取到相对当前过程的数据基地址为a的地址*/
			      t--;
			      s[base(i.l,s,b)+i.a]=s[t];
			      break;
              case cal:                        /*调用子过程*/
			      s[t]=base(i.l,s,b);           /*将父过程基地址入栈*/
			      s[t+1]=b;                     /*将本过程基地址入栈,此两项用于base函数*/
			      s[t+2]=p;                     /*将当前指令指针入栈*/
			      b=t;                           /*改变基地址指针值为新过程的基地址*/
			      p=i.a;                         /*眺转*/
			      break;
              case inte:                       /*内存分配*/
			      t+=i.a;
			      break;
              case jmp:                        /*直接跳转*/
			      p=i.a;
			      break;
              case jpc:                         /*条件跳转*/
			      t--;
			      if(s[t]==0)
				  {
					  p=i.a;
				  }
			      break;
        }
	}while(p!=0);
}
/*通过过程基址求上一层的基址*/
int base(int l,int *s,int b)
{
	int b1;
	b1=b;
	while(l>0)
	{
		b1=s[b1];
		l--;
	}
	return b1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -