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

📄 pl0.cpp

📁 pl0小型编译器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
         nxtlev[endsym]=true;/* 循环调用语句处理函数,直到下一个符号不是语句开始符号或收到end */
         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); /* 缺少end或; */
       }
       else
       {
        if(sym==whilesym) /* 准备按照while语句处理 */
        {
         cx1=cx; /* 保存判断条件操作的位置 */
         getsymdo;
         memcpy(nxtlev,fsys,sizeof(bool)*symnum);
         nxtlev[dosym]=true; /* 后跟符号为do */
         conditiondo(nxtlev,ptx,lev); /* 调用条件处理 */
         cx2=cx; /* 保存循环体的结束的下一个位置 */
         gendo(jpc,0,0); /* 生成条件跳转,但跳出循环的地址未知 */
         if(sym==dosym)
         {
          getsymdo;
         }
         else error(18); /* 缺少do */
         statementdo(fsys,ptx,lev); /* 循环体 */
         gendo(jmp,0,cx1); /* 回头重新判断条件 */
         code[cx2].a=cx; /* 反填跳出循环的地址,与if类似 */
         }
         memset(nxtlev,0,sizeof(bool)*symnum); /* 语句结束无补救集合 */
         testdo(fsys,nxtlev,19); /* 检测语句结束的正确性 */
        }
       }
      }
     }
    }
   }
   return 0;
}
/* 表达式处理 */
int expression(bool* fsys,int* ptx,int lev) /* 参数意义见block和enter函数 */
{
   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) /* 参数意义见block和enter函数 */
{
   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) /* 参数意义见block和enter函数 */
{
    int i;
    bool nxtlev[symnum];
    testdo(facbegsys,fsys,24); /* 检测因子的开始符号 */
    while(inset(sym,facbegsys)) /* 循环直到不是因子开始符号 */
    {
     if(sym==ident) /* 因子为常量或变量 */
     {
      i=postion(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); /* 缺少右括号 */
      }
      test(fsys,facbegsys,23); /* 因子后有非法符号 */
     }
    }
   }
   return 0;
}
/* 条件处理 */
int condition(bool* fsys,int* ptx,int lev) /* 参数意义见block和enter函数 */
{
   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);
  fclose(fa2);
}
/* 通过过程活动记录基址求上l层过程的基址活动记录 */
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 + -