/* 语法、语义分析程序 */
  int block(int lev, /* 当前分程序所在层 */
       int tx, /* 名字表当前尾指针 */
       bool* fsys /* 当前模块后跟符号集合 */
       )
  {
   int i;
   int dx; /* 名字分配到的相对地址 */
   int tx0; /* 保留初始tx */
   int cx0; /* 保留初始cx */
   bool nxtlev[symnum]; /* 在下级函数的参数中,
              符号集合均为值参,但由于使用数租实现,
              传递进来的是指针,为防止下级函数改变
              上级函数的集合,开辟新的空间传递给
              下级函数,之后所有的nxtlev都是这样 */

   dx=3;
   tx0=tx; /* 记录本层名字的初始位置 */
   table[tx].adr=cx;
   gendo(jmp,0,0);
   if(lev>levmax)error(32);
   do
   {
    if(sym==constsym) /*常量声明符号,开始处理常量声明 */
    {
     getsymdo;
     do

     {
      constdeclarationdo(&tx,lev,&dx); /* dx的值会被constdeclaration改变,使用指针 */
      while(sym==comma)
      {
       getsymdo;
       constdeclarationdo(&tx,lev,&dx);
      }
      if(sym==semicolon)
      {
       getsymdo;
      }
      else error(5);
     }
     while(sym==ident);
    }
    if(sym==varsym) /*变量声明符号,开始处理变量声明 */
    {
     getsymdo;
     do
     {
      vardeclarationdo(&tx,lev,&dx);
      while(sym==comma)
      {
       getsymdo;
       vardeclarationdo(&tx,lev,&dx);
      }
      if(sym==semicolon)
      {
       getsymdo;
      }
      else error(5);
     }
     while(sym==ident);
    }
    while(sym==procsym) /*过程声明符号,开始处理过程声明 */
    {
     getsymdo;
     if(sym==ident)
     {
      enter(procedur,&tx,lev,&dx); /* 记录过程名字 */
      getsymdo;
     }
     else error(4); /* procedure后应为标识符 */
     if(sym==semicolon)
     {
      getsymdo;
     }
     else error(5); /* 漏掉了分号 */
     memcpy(nxtlev,fsys,sizeof(bool)*symnum);
     nxtlev[semicolon]=true;
     if(-1==block(lev+1,tx,nxtlev))return -1; /* 又进入一层分程序 */
     if(sym==semicolon)
     {
      getsymdo;
      memcpy(nxtlev,statbegsys,sizeof(bool)*symnum);
      nxtlev[ident]=true;
      nxtlev[procsym]=true;
      testdo(nxtlev,fsys,6);
     }
     else error(5); /* 漏掉了分号 */
     }
     memcpy(nxtlev,statbegsys,sizeof(bool)*symnum);
     nxtlev[ident]=true;
     testdo(nxtlev,declbegsys,7);
    }
    while(inset(sym,declbegsys)); /* 直到没有声明符号 */
    code[table[tx0].adr].a=cx; /* 开始生成当前过程代码 */
    table[tx0].adr=cx; /* 当前过程代码地址 */
    table[tx0].size=dx; /* 声明部分中每增加一条声明都会给dx增加1,
            声明部分已经结束,dx就是当前过程数据的size */
    cx0=cx;
    gendo(inte,0,dx); /* 开辟数据段 */
    if(tableswitch) /* 输出名字表 */
    {
     printf("TABLE:\n");
     if(tx0+1>tx)printf(" NULL\n");
     for(i=tx0+1;i<=tx;i++)
     {
      switch(table[i].kind)
      {
       case constant:
       printf(" %d const %s ",i,table[i].name);
       printf("val=%d\n",table[i].val);
       fprintf(fas," %d const %s ",i,table[i].name);
       fprintf(fas,"val=%d\n",table[i].val);
       break;
       case variable:
       printf(" %d var %s ",i,table[i].name);
       printf("lev=%d addr=%d\n",table[i].level,table[i].adr);
       fprintf(fas," %d var %s ",i,table[i].name);
       fprintf(fas,"lev=%d addr=%d\n",table[i].level,table[i].adr);
       break;
       case procedur:
       printf(" %d proc %s ",i,table[i].name);
       printf("lev=%d addr=%d size=%d\n",table[i].level,table[i].adr,table[i].size);
       fprintf(fas," %d proc %s ",i,table[i].name);
       fprintf(fas,"lev=%d addr=%d size=%d\n",table[i].level,table[i].adr,table[i].size);
       break;
      }
     }
     printf("\n");
    }