现代编译原理--第四章(语义分析以及源码)

    (转载请注明出处 http://www.cnblogs.com/BlackWalnut/p/4527845.html) 

  写完语义分析的代码后感觉语义分析只是为了进行类型检测(后来才发现,这只是语义分析的一部分)。词法分析注重的是每个单词是否合法,以及这个单词属于语言中的哪些部分。语法分析的上下文无关文法注重的是一个一个的推导式,是将词法分析中得到的单词按照语法规则进行组合。那么,语义分析就是要了解各个推导式之间的关系是否合法,主要体现在推导式中使用的终结符和非终结符之间的关系,也就是它们的类型。所以语义分析注重的一个方面是类型检测。

  为了将上下文无关文法中各种终结符和非终结符联系起来,以及在想要使用它们的时候得到它们相应的类型,我们使用了一种叫做符号表的东西,又称为环境。环境可以理解为对每一个ID建立一个栈,栈中存放的和这个ID相关的一些信息,这些信息称为绑定。使用栈的好处是,可以解决作用域的问题。ID始终对应于栈顶的绑定,每次进入一个新的作用域就将一个作用域标示符压入栈中。这样,在一个新的作用域中定义了一个和老作用域ID相同的变量,类型或者函数时,将新的绑定压入栈中,那么老的绑定就会失效。当出作用域时,将作用域标示符以上的所有绑定都弹出,这样就完成了老绑定的恢复。

  上面介绍的栈式环境,我们称为命令式风格。还有一种称为函数式风格,它的特点是每次都将原来的环境复制一份,将老的保存起来,对新的进行更改。当出作用域时,直接将新的抛弃,然后使用老的。

     为什么只存放变量,类型以及函数的相关信息呢?我们可以看到,一种语言其实包含四个部分类型声明,函数声明,变量声明以及表达式, 前三个就利用内置类型来创造新的东西,而表达式则是使用这些东西所要遵守的规则,这些规则都是由上下文无关文法定义好的。声明和表达式就组成了一个语言的基本部分,我们只能使用这些规则来组织我们创造的东西,最终形成我们的程序。所以在语义分析阶段,我们只用注重各种类型的检测,看看在特定的规则下是否符合要求。

   下面我们来看看tiger中语义分析时要注意的事项。 

     在tiger的语义分析过程中,我们使用了两个环境,值环境和类型环境。其中,值环境用来存放函数声明,变量声明的,类型环境是用来存放类型声明的。之所以使用两个符号表是因为在tiger中我们允许类型和变量,函数名使用相同的ID,但是不允许变量和函数使用相同的ID。并且,在tiger中,为了更快的找到ID所对应的绑定,我们使用了hash表来存储每个ID对应的栈。但是这里有个问题要解决,就是hash可能会造成冲突。例如ID1和ID2同时hash到同一个表项中,那么这个表项对应的栈是谁的?这个时候,我们要在绑定中存放这个绑定对应的ID。我们只要从栈顶开始比较,找到第一个和我们hash的ID相同的绑定,就是我们需要的绑定。

  但是,这样的话,每次查找hash表都要进行字符串的比较,是十分低效的。所以,tiger中symbol.h文件给了另一个hash表,这个hash表的作用是将一个ID映射到一个指针(就是在语法分析中使用函数S_symbol)。那么我们只要将这个指针和绑定压入栈总,比较这个指针就可以确定这个绑定是不是我需要查找的绑定。这是一个十分精巧的设计。

  知道了如何根据ID查找相应的绑定,那么我们来看看这些绑定究竟是什么。

  首先,我们向栈中压入绑定时,绑定其实使用一个void*类型的指针指向的,也就是说,我们不关心压入的绑定是什么,我们只关心压入绑定的地址以及压入到哪个表中(函数s_enter)。在读出(函数s_look)绑定的时候,我们只要把这个地址转换为我们需要的绑定(值绑定或者类型绑定)就可以了。

  对于类型环境,每一个类型ID对应一个Ty_ty_结构体定义的绑定,这个Ty_ty_在Types.h中定义。可以看出这个结构体包含的类型(kind 枚举)是很多,其中要注意的是TY_name这个枚举,这个枚举是所有由 type id = id 这种语句定义的类型。根据不同的类型,我们使用联合中不同变量来解读。后面的几个函数都是根据不同kind来创建不同Ty_ty。但是要注意到,在新建一个类型环境的时候,我们要把int和string两个ID以及对应的绑定压入(S_enter)栈中,这两个是内置类型,必须先入栈。这里的int和string是类型,也就是终结符ID。和词法分析时的INT STRING的概念不同,这两个INT STRING是整型常量和字符型常量,它们的类型是int和string。

  对于值环境,我们使用env.h中的E_enventry 结构体。这个就相对简单许多。

  知道tiger中使用的绑定是什么样子的,就来说说这里面的一些坑。注意到我们使用到很多指针,大部分都是由指针引起的。

     首先,我们在进行类型比较的时候,使用的指针。这里说说为什么,对于 type intary = array of int  以及 type strary = array of string ,如果只intary和strary所对应的绑定的kind来判断,两个都是Ty_array,但是两个的类型确实是不一样的,所以这种只使用kind判断的方式是失效的。所以这个时候我们要看看绑定中联合里的array(这是一个指针)是否一致。我们查看内置类型(int vaid nil sting),它们都是由函数(Ty_Int等)直接返回的指针,查看函数后发现,这些内置类型使用的都是相同的地址。但是其他类型的地址却有可能不同,这时就是下面这个注意事项。

     另外一个需要注意的是,因为在tiger中存在这样的类型定义 type ID1 = ID2 也就是说ID1 是 ID2 的别名,此时ID1中的绑定指向由 Ty_Name 函数返回的一个地址,该函数申请了一块新的内存。如果我们再定义type ID3 = ID2 ,此时使用指针比较ID1 和 ID3,这个时候判断两个类型是不一致的。这显然和tiger的要求的相违背。这个时候我们定义了一个新的函数actrulyTy,这个函数将返回绑定的“真实类型”,这些真是类型只可能是四个内置类型 ,数组类型或者记录类型,同时书中要求返回的任何expty中的Ty_ty必须是“真实类型”。那么,对一下代码进行类型检测就可以得到正确的结果。

  type  recd = { a : int , b : string }
  type  recd1 = recd 
  type  recd2 = recd 
   //测试 recd1 和 recd2 是否相等
    recd1 == recd2

   这里提醒一下,我提供的代码实不支持一下类型检测的

 type recd = { a : int , b : string }
 type recd1 = recd
 type recd2 = recd 
 type recd1ary = array of recd1 
 type recd2ary = array of recd2 
//以下此时将返回false
recd1ary == recd2ary

     其实就是将recd1和recd2 再次进行一次actrulyTy就可以了。总之,两类型比较时,一定要求时“真实类型”。

   还有一个,可能是虎书的作者没有注意到的一个地方(或许是我的代码有问题??)。在使用词法分析器向语法分析器传送ID以及相应的字符串时,我们使用一个变量(在我上一篇文章中讲述bison和flex传值)yylval.sval  ,注意,这个sval是一个指针,指向一个字符串的开头,被指向的这个字符串是yytext。这个yytext字符串在进行词法分析时是会改变的。所以当你在语法分析器中将词法分析器传出的sval作为参数调用S_symbol时,这个sval指向的字符串yytext可能已经改变了(因为语法分析器存在移进以及规约,所以并不是和词法分析器同步工作的)。因此在使用s_symbol时要进行一些调整,如下: 

S_symbol S_Symbol(string Id)
{
    int i = 0 ;
    for ( ;  (Id[i] >= '0' && Id[i] <= '9') || ( Id[i] >= 'a' && Id[i] <= 'z')||( Id[i] >= 'A' && Id[i] <= 'Z') ;++i) ;
    string name = (string)checked_malloc( sizeof(*name) * (i+1)) ;
    int b = sizeof(*name) * (i+1) ;
    memcpy(name , Id , sizeof(*name)*(i)) ;
    name[i] = '\0' ;
    int index= hash(name) % SIZE;
    S_symbol syms = hashtable[index], sym;
    for(sym=syms; sym; sym=sym->next)
    if (streq(sym->name,name)) return sym;
    sym = mksymbol(name,syms);
    hashtable[index]=sym;
    return sym;
}

  代码比较渣渣。。。。同样的调整还出现在处理字符串常量的函数中。

  对于要处理的函数以及记录类型的递归,可以看成时c++中先处理头文件,在处理cpp。也不算太难,但是要注意,保持指针指向正确的位置。

  以下就是这次的部分代码,没有实现当有错误时,显示错误位置的功能。有些代码比较简单,就没有贴出来。这份代码已经经过随书附带的前六个测试用例测试过,没有问题:

      env.h

#ifndef ENV_H_
#define ENV_H_
#include "types.h"
typedef struct E_enventry_ *E_enventry ;
struct E_enventry_ {
    enum { E_varEntry , E_funEntry } kind;
    union
    {
        struct { Ty_ty ty ; } var;
        struct { Ty_tyList formals ; Ty_ty result ;} fun ;
    }u;
};

E_enventry E_VarEntry(Ty_ty ty) ;
E_enventry E_FunEntry(Ty_tyList formals , Ty_ty reslut) ;

S_table E_base_tenv() ;
S_table E_base_venv() ;
Ty_ty actrulyTy(Ty_ty) ; 
bool  isTyequTy( const Ty_ty ,const Ty_ty) ;
void  tyCpy(Ty_ty dec , const Ty_ty src );
#endif

    env.cpp

#include "env.h"
#include <stdio.h>
#include <string.h>
E_enventry E_VarEntry(Ty_ty ty)
{
    E_enventry p = (E_enventry) checked_malloc(sizeof(*p)) ;
   p->kind = E_enventry_::E_varEntry ;
   p->u.var.ty = ty ;
   return p ;
}

E_enventry E_FunEntry(Ty_tyList formals , Ty_ty reslut)
{
    E_enventry p = (E_enventry)checked_malloc(sizeof(*p)) ;
    p->kind = E_enventry_::E_funEntry ;
    p->u.fun.formals = formals ;
    p->u.fun.result = reslut ;
    return p ;
}

Ty_ty  actrulyTy(Ty_ty ty)
{
    if (ty == NULL )
    {
        return NULL ;
    }
    while(ty->kind == Ty_ty_::Ty_name)
    {
       ty = ty->u.name.ty ;
    }
    return ty ;
}

bool isTyequTy(const Ty_ty s1 , const Ty_ty s2)
{
    Ty_ty tmp1 = actrulyTy(s1) ;
    Ty_ty tmp2 = actrulyTy(s2) ;
    bool aryOrRec = (tmp1->kind == Ty_ty_::Ty_array || tmp2->kind == Ty_ty_::Ty_record) ;
    bool isnil = (tmp1->kind == Ty_ty_::Ty_nil || tmp2->kind == Ty_ty_::Ty_nil) ;
    if ( tmp1->kind != tmp2->kind)
    {
        if ( isnil &&  aryOrRec )
        {
             return true ;
        }
        return false ;
    }
    if (aryOrRec)
    {
          if (tmp1 != tmp2 )
          {
              return false ;
          }
    }
    return true ;
}

void tyCpy(Ty_ty dec , const Ty_ty src)
{
    if (dec == NULL || src == NULL )
    {
        assert(0) ;
    }
    memcpy(dec , src , sizeof(*src)) ;
}

sement.h

#ifndef SENMANT_H_
#define SENMANT_H_
#include "types.h"
#include "translate.h"
#include "absyn.h"
struct expty { Tr_exp exp ; Ty_ty ty; };
expty expTy(Tr_exp exp , Ty_ty ty) ;
expty  transVar(S_table venv , S_table tenv , A_var var) ;
expty  transExp(S_table venv , S_table tenv , A_exp exp) ; 
void   transDec(S_table venv , S_table tenv , A_dec dec) ;
Ty_ty  transTy( S_table tenv , A_ty ty) ;
bool  innerIdentifiers( S_symbol sym);
#endif

sement.cpp

#include "semant.h"
#include <assert.h>
#include "env.h"

expty expTy(Tr_exp exp , Ty_ty ty)
{
    expty e ;
    e.exp = exp ; e.ty = ty ;
    return e ;
}

expty  transExp(S_table venv , S_table tenv , A_exp exp)
{
  if (exp == NULL )
  {
      assert(0);
  }
   switch(exp->kind)
   {
   case  A_varExp :
           return transVar(venv , tenv , exp->u.var) ;
   case  A_nilExp :
          return expTy(NULL ,Ty_Nil());
   case  A_intExp :  
          return expTy(NULL , Ty_Int()) ;
   case  A_stringExp :
          return expTy(NULL , Ty_String()) ;
   case  A_callExp :
          {
              E_enventry tmp = (E_enventry)S_look(venv, exp->u.call.func) ;
              if (tmp == NULL)
              {
                  assert(0) ;
              }
              Ty_tyList tylist  = tmp->u.fun.formals ;
              A_expList explist = exp->u.call.args ;
              while (tylist != NULL && explist != NULL)
              {
                  expty exptyp = transExp(venv , tenv , explist->head) ;
                  
                  if (exptyp.ty->kind == Ty_ty_::Ty_nil)
                  {
                      continue ;
                  }
                   if (!isTyequTy(tylist->head , exptyp.ty))
                   {
                       assert(0) ;
                   }
                  tylist = tylist->tail ;  explist = explist->tail ;
              }
              if (tylist != NULL || explist != NULL )
              {
                  assert(0);
              }
              return expTy(NULL , actrulyTy(tmp->u.fun.result)) ; 
          }
   case  A_opExp :
          {
              switch(exp->u.op.oper)
              {
              case A_plusOp   : 
              case A_minusOp  : 
              case A_timesOp  : 
              case A_divideOp : 
              case A_ltOp     : 
              case A_leOp     : 
              case A_gtOp     : 
              case A_geOp     : 
                     {
                         if (transExp(venv , tenv, exp->u.op.left).ty->kind != Ty_ty_::Ty_int)
                             assert(0);
                         if (transExp(venv , tenv, exp->u.op.right).ty->kind != Ty_ty_::Ty_int)
                             assert(0);   
                         return expTy(NULL , Ty_Int()) ;
                     }
              case A_eqOp :
              case A_neqOp: 
                     {
                         expty tmpleft = transExp(venv , tenv, exp->u.op.left) ;
                         expty tmpright = transExp(venv , tenv, exp->u.op.right) ;

                         if (tmpleft.ty->kind == Ty_ty_::Ty_int
                             && tmpright.ty->kind == Ty_ty_::Ty_int)
                             return expTy(NULL , Ty_Int()) ;
                         if (tmpleft.ty->kind == tmpright.ty->kind)
                         {
                             if (tmpleft.ty->kind == Ty_ty_::Ty_record || tmpleft.ty->kind == Ty_ty_::Ty_array)
                             {
                                 if ( tmpleft.ty == tmpright.ty )
                                 {
                                     return expTy(NULL , Ty_Int()) ;
                                 }
                            }
                         }
                         assert(0);
                     }
              }
              assert(0);
          }
   case  A_recordExp :
          {
              Ty_ty tmpty = (Ty_ty)S_look(tenv , exp->u.record.typ) ;
               tmpty = actrulyTy(tmpty) ;
               if (tmpty == NULL )
               {
                   assert(0) ;
               }
              if (tmpty->kind != Ty_ty_::Ty_record )
              {
                  assert(0) ;
              }
              A_efieldList tmpefield = exp->u.record.fields ;
              Ty_fieldList tmpfieldlist = tmpty->u.record ;
              while(tmpefield && tmpfieldlist)
              {    
                  if (tmpefield->head->name != tmpfieldlist->head->name )
                  {
                      assert(0) ;
                  }
                 
                  if (!isTyequTy(transExp(venv , tenv , tmpefield->head->exp).ty
                                 ,tmpfieldlist->head->ty))
                  {
                      assert(0) ;
                  }
                  tmpefield = tmpefield->tail ; tmpfieldlist = tmpfieldlist->tail ;
              }
              if (tmpfieldlist!= NULL || tmpefield != NULL )
              {
                  assert(0) ;
              }
              return expTy(NULL ,tmpty);
          }
   case  A_seqExp :
          {
              A_expList explist = exp->u.seq ;
              if (explist)
              {
                  while(explist->tail)
                  {
                      transExp( venv , tenv , explist->head); 
                      explist = explist->tail ;
                  }
              }
              else
              {
                  return expTy(NULL , Ty_Void());
              }
              return transExp(venv , tenv , explist->head);
          }
   case  A_assignExp :
          {
              expty tmpV = transVar(venv , tenv , exp->u.assign.var) ;
              expty tmpE = transExp(venv , tenv , exp->u.assign.exp);
              if (tmpE.ty->kind != tmpV.ty->kind)
              {
                  assert(0);
              }
              return expTy(NULL , Ty_Void());
          }
   case  A_ifExp :
          {
              expty tmptest = transExp(venv ,tenv , exp->u.iff.test) ; 
              if(tmptest.ty->kind != Ty_ty_::Ty_int)
              {
                  assert(0);
              }
              expty tmpthen = transExp(venv , tenv , exp->u.iff.then) ;
              if (exp->u.iff.elsee != NULL)
              {
                  expty tmpelse = transExp(venv , tenv , exp->u.iff.elsee) ;
                  if ( tmpthen.ty != tmpelse.ty )
                  {
                      assert(0);
                  }
                  return expTy(NULL , tmpelse.ty);
              }
              if (tmpthen.ty->kind != Ty_ty_::Ty_void)
              {
                  assert(0);
              }
              return expTy(NULL , Ty_Void());
          }
   case  A_whileExp : 
          {
              expty test = transExp(venv , tenv , exp->u.whilee.test);
              if (test.ty->kind != Ty_ty_::Ty_int)
              {
                  assert(0) ;
              }
              expty body = transExp(venv , tenv , exp->u.whilee.body);
              if (body.ty->kind != Ty_ty_::Ty_void)
              {
                  assert(0);
              }
              return expTy(NULL , Ty_Void());
          }
   case  A_forExp :
          {
              expty tmplo = transExp(venv , tenv , exp->u.forr.lo);
              expty tmphi = transExp(venv , tenv ,  exp->u.forr.hi);
              S_beginScope(venv);
              S_enter(venv , exp->u.forr.var , E_VarEntry(Ty_Int()));
              expty tmpbody = transExp(venv , tenv, exp->u.forr.body);
              if (tmplo.ty->kind != Ty_ty_::Ty_int || tmphi.ty->kind != Ty_ty_::Ty_int || tmpbody.ty->kind != Ty_ty_::Ty_void)
              {
                  assert(0);
              }
              S_endScope(venv);
              return expTy(NULL , Ty_Void());
          }
   case  A_breakExp :
            return expTy(NULL , Ty_Void());
   case  A_letExp :
          {
              S_beginScope(venv);
              S_beginScope(tenv);
              A_decList declist = exp->u.let.decs ;
              while(declist != NULL)
              {
                  transDec(venv , tenv , declist->head);
                  declist = declist->tail;
              }
              expty tmp ;
              if (exp->u.let.body)
              {
                  tmp = transExp(venv , tenv , exp->u.let.body); 
              }
              else
              {
                  tmp = expTy(NULL , Ty_Void()) ;
              }
              S_endScope(venv);
              S_endScope(tenv);
              return tmp ;
          }
   case  A_arrayExp :
          {
              Ty_ty ty = (Ty_ty)S_look(tenv , exp->u.array.typ);
              ty = actrulyTy(ty);
              if (ty == NULL || ty->kind != Ty_ty_::Ty_array)
              {
                  assert(0);
              }
              expty tynum = transExp(venv , tenv , exp->u.array.size);
              if (tynum.ty->kind != Ty_ty_::Ty_int)
              {
                  assert(0);
              }
              expty tyinit = transExp(venv , tenv, exp->u.array.init) ;
              if (tyinit.ty != ty->u.array )
              {
                  assert(0) ;
              }
              return expTy(NULL , ty);
          }    
   }
   assert(0);
}

expty transVar(S_table venv , S_table tenv , A_var var)
{
     switch(var->kind)
     {
     case  A_simpleVar :
            {
                E_enventry tmp = (E_enventry) S_look(venv , var->u.simple) ;
                if (tmp != NULL && tmp->kind == E_enventry_::E_varEntry)
                {
                    return expTy(NULL , actrulyTy(tmp->u.var.ty)) ;
                }
                assert(0) ;
            }
     case  A_fieldVar :
            {
                expty tmpty = transVar(venv , tenv , var->u.field.var) ;
                if (tmpty.ty->kind != Ty_ty_::Ty_record)
                {
                    assert(0);
                }
                Ty_fieldList fieldList = tmpty.ty->u.record ;
                while( fieldList )
                {
                 if ( fieldList->head->name == var->u.field.sym  )
                 {
                    return expTy(NULL  , actrulyTy(fieldList->head->ty)) ;
                 }
                  fieldList = fieldList->tail ;
                }
                assert(0);
            }
     case  A_subscriptVar :
            {
                expty tmp = transVar(venv , tenv , var->u.subscript.var) ;
                if (tmp.ty->kind != Ty_ty_::Ty_array )
                {
                    assert(0) ;
                }
                expty tmpexp  = transExp(venv , tenv , var->u.subscript.exp) ;
                if (tmpexp.ty->kind != Ty_ty_::Ty_int)
                {
                    assert(0) ;
                }
                return tmp ;
            }    
     }
     assert(0) ;
}

void transDec(S_table venv , S_table tenv , A_dec dec)
{
    switch(dec->kind)
    {
    case  A_functionDec :
           {
               A_fundecList tmpfun = dec->u.function ;
               while(tmpfun)
               {
                   A_fieldList tmpfeldList = tmpfun->head->params ;
                   Ty_tyList tylist = NULL ;
                   while(tmpfeldList)
                   {
                       Ty_ty ty = (Ty_ty)S_look(tenv,tmpfeldList->head->typ);
                       tylist = Ty_TyList(ty , tylist) ;
                       tmpfeldList = tmpfeldList->tail ;
                   }
                   if (innerIdentifiers(tmpfun->head->name))
                   {
                       assert(0) ;
                   }
                   //¿‡À∆”⁄…˘√˜“ª∏ˆ∫Ø ˝ ªπ√ª”–∂®“ÂÀ¸
                   S_enter(venv , tmpfun->head->name , E_FunEntry(tylist , (Ty_ty)S_look(tenv ,tmpfun->head->result))) ;
                   tmpfun = tmpfun->tail ;
               }
               tmpfun = dec->u.function ;
               while(tmpfun)
               {
                    S_beginScope(venv) ;
                   A_fieldList tmpfeldList = tmpfun->head->params ;
                   while(tmpfeldList)
                   {
                       Ty_ty ty = (Ty_ty)S_look(tenv,tmpfeldList->head->typ);
                       if (innerIdentifiers(tmpfeldList->head->name))
                       {
                           assert(0);
                       }
                       S_enter(venv ,tmpfeldList->head->name, E_VarEntry(ty)) ;
                       tmpfeldList = tmpfeldList->tail ;
                   }
                   transExp(venv , tenv , tmpfun->head->body) ;
                   S_endScope(venv) ;
                   tmpfun = tmpfun->tail ;
               }
               return ;
           }
    case  A_typeDec :
           {
               A_nametyList namelist = dec->u.type ;
               while(namelist)
               {
                   if (innerIdentifiers(namelist->head->name))
                   {
                       assert(0) ;
                   }
                   // ¥¶¿Ìµ›πÈ ¿‡À∆”⁄ …˘√˜“ª∏ˆ¿‡–Õ µ´ «ªπ√ª”–∂®“ÂÀ¸
                   S_enter(tenv , namelist->head->name ,Ty_Name(namelist->head->name , NULL)) ;
                   namelist = namelist->tail ;
               }
               namelist = dec->u.type ;
               while(namelist)
               {
                  // ¥¶¿Ìµ›πÈ
                   Ty_ty tmp1 = transTy(tenv , namelist->head->ty ) ;
                   Ty_ty tmp2 = (Ty_ty)S_look(tenv , namelist->head->name) ;
                   
                   if (   tmp1->kind == Ty_ty_::Ty_int 
                       || tmp1->kind == Ty_ty_::Ty_string 
                       || tmp1->kind == Ty_ty_::Ty_nil
                       || tmp1->kind == Ty_ty_::Ty_void)
                   {
                        //如果是内置类型 绑定指向的地方是一个固定的地方 所以 这个时候就不是替换内容那么简单了
                        tmp2 = (Ty_ty)S_changeBind(tenv , namelist->head->name , tmp1);
                        tmp2 = (Ty_ty)freeTy(tmp2) ;
                   }
                   else
                   {
                       tyCpy(tmp2 , tmp1) ;
                       tmp1 = (Ty_ty)freeTy(tmp1) ;
                   }
                   namelist = namelist->tail ;
               }
               namelist = dec->u.type;
               while(namelist)
               {  // 避免出现  type a = b  type b = a 这种没有真实类型的类型定义
                 Ty_ty tmp = (Ty_ty)S_look(tenv , namelist->head->name) ;
                   if (!actrulyTy(tmp))
                   {
                       assert(0) ;
                   }
                   namelist = namelist->tail ;
               }
               return;
           }
    case  A_varDec :
           {
               if(dec->u.var.init == NULL)
               {
                   assert(0) ;
               }
               expty tmp = transExp(venv , tenv , dec->u.var.init) ;
               if( (dec->u.var.typ != NULL) )
               {
                   if ( actrulyTy((Ty_ty)S_look(tenv ,dec->u.var.typ)) != tmp.ty)
                   {
                       assert(0) ;
                   }
               }
               if (innerIdentifiers(dec->u.var.var))
               {
                   assert(0) ;
               }
               S_enter(venv , dec->u.var.var ,E_VarEntry(tmp.ty)) ;
               return;
           }    
    }
   assert(0) ;
}

 Ty_ty transTy(S_table tenv , A_ty ty)
 {
     switch(ty->kind)
     {
     case  A_nameTy :
            {
                if (S_Symbol("int") == ty->u.name)
                {
                    return Ty_Int();
                }
                if (S_Symbol("string") == ty->u.name)
                {
                    return Ty_String();
                }
                Ty_ty tmp = (Ty_ty)S_look(tenv , ty->u.name) ;
                if ( tmp == NULL )
                {
                    assert(0) ;
                }
                return Ty_Name(ty->u.name , tmp) ;
            }
     case  A_recordTy :
            {
                A_fieldList tmpfeldList = ty->u.record ;
                Ty_fieldList tyfdlist = NULL ; 
                while(tmpfeldList)
                {
                    Ty_ty  tmp = (Ty_ty)S_look(tenv , tmpfeldList->head->typ) ;
                    if ( tmp == NULL )
                    {
                        assert(0) ;
                    }
                    if (innerIdentifiers(tmpfeldList->head->name))
                    {
                        assert(0);
                    }
                    tyfdlist = Ty_FieldList(Ty_Field( tmpfeldList->head->name , tmp ) , tyfdlist) ;
                    tmpfeldList = tmpfeldList->tail ;
                }
                return Ty_Record(tyfdlist);
            }
     case  A_arrayTy :
            {
                Ty_ty tmp  = (Ty_ty)S_look(tenv , ty->u.array);
                if ( tmp == NULL )
                {
                    assert(0);
                }
                return Ty_Array(tmp) ;
            }
     }
     assert(0) ;
 }

 bool innerIdentifiers( S_symbol sym)
 {
     if (sym == S_Symbol("int") || sym == S_Symbol("string") )
     {
        return true ;
     }
     return false ;
 }

函数 S_changeBind 相关代码

S_symbol.cpp
void* S_changeBind(S_table t , S_symbol sym , void *value)
{
   return TAB_changeBind(t , sym , value)  ; 
}

S_table.cpp
void* TAB_changeBind( TAB_table t , void * key , void *value )
{
    int index ;
    assert(t&&key) ;
    binder b ;
    void * tmp ;
    index = ((unsigned)key) % TABSIZE ;
    for ( b = t->table[index] ; b ;  b = b->next)
    {
       if (b->key == key )
       {  
           tmp = b->value ;
           b->value = value ;
           return  tmp ;
       }
    }
    return NULL ;
}

 

转载于:https://www.cnblogs.com/BlackWalnut/p/4527845.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作者简介: Andrew W.Appel,美国普林斯顿大学计算机科学系教授,第26届ACM SIGPLAN-SIGACT程序设计原理年会大会执行主席,1998-1999年在贝尔实验室做研究工作。主要研究方向是计算机安全、编译器设计、程序设计语言等。 内容简介: 本书全面讲述了现代编译器的各个组成部分,包括词法分析、语法分析、抽象语法、语义检查、中间代码表示、指令选择、数据流分析、寄存器分配以及运行时系统等。全书分成两部分,第一部分是编译的基础知识,适用于第一门编译原理课程(一个学期);第二部分是高级主题,包括面向对象语言和函数语言、垃圾收集、循环优化、SSA(静态单赋值)形式、循环调度、存储结构优化等,适合于后续课程或研究生教学。书中专门为学生提供了一个用C语言编写的实习项目,包括前端和后端设计,学生可以在一学期内创建一个功能完整的编译器。   本书适用于高等院校计算机及相关专业的本科生或研究生,也可供科研人员或工程技术人员参考。 目录: 第一部分 编译基本原理 第1章 绪论 1 1.1 模块与接口 1 1.2 工具和软件 3 1.3 树语言的数据结构 3 程序设计:直线式程序解释器 7 推荐阅读 9 习题 9 第2章 词法分析 10 2.1 词法单词 10 2.2 正则表达式 11 2.3 有限自动机 13 2.4 非确定有限自动机 15 2.4.1 将正则表达式转换为NFA 16 2.4.2 将NFA转换为DFA 18 2.5 Lex:词法分析器的生成器 20 程序设计:词法分析 22 推荐阅读 23 习题 23 第3章 语法分析 27 3.1 上下文无关文法 28 3.1.1 推导 29 3.1.2 语法分析树 29 3.1.3 二义性文法 30 3.1.4 文件结束符 31 3.2 预测分析 32 3.2.1 FIRST集合和FOLLOW集合 33 3.2.2 构造一个预测分析器 35 3.2.3 消除左递归 36 3.2.4 提取左因子 37 3.2.5 错误恢复 37 3.3 LR分析 39 3.3.1 LR分析引擎 40 3.3.2 LR(0)分析器生成器 41 3.3.3 SLR分析器的生成 44 3.3.4 LR(1)项和LR(1)分析表 45 3.3.5 LALR(1)分析表 46 3.3.6 各类文法的层次 47 3.3.7 二义性文法的LR分析 47 3.4 使用分析器的生成器 48 3.4.1 冲突 49 3.4.2 优先级指导 50 3.4.3 语法和语义 53 3.5 错误恢复 54 3.5.1 用error符号恢复 54 3.5.2 全局错误修复 55 程序设计:语法分析 57 推荐阅读 58 习题 58 第4章 抽象语法 62 4.1 语义动作 62 4.1.1 递归下降 62 4.1.2 Yacc生成的分析器 62 4.1.3 语义动作的解释器 64 4.2 抽象语法分析树 65 4.2.1 位置 67 4.2.2 Tiger的抽象语法 68 程序设计:抽象语法 71 推荐阅读 71 习题 72 第5章 语义分析 73 5.1 符号表 73 5.1.1 多个符号表 74 5.1.2 高效的命令式风格符号表 75 5.1.3 高效的函数式符号表 76 5.1.4 Tiger编译器的符号 77 5.1.5 函数式风格的符号表 79 5.2 Tiger编译器的绑定 79 5.3 表达式的类型检查 82 5.4 声明的类型检查 84 5.4.1 变量声明 84 5.4.2 类型声明 85 5.4.3 函数声明 85 5.4.4 递归声明 86 程序设计:类型检查 87 习题 87 第6章 活动记录 89 6.1 栈帧 90 6.1.1 帧指针 91 6.1.2 寄存器 92 6.1.3 参数传递 92 6.1.4 返回地址 94 6.1.5 栈帧内的变量 94 6.1.6 静态链 95 6.2 Tiger编译器的栈帧 96 6.2.1 栈帧描述的表示 98 6.2.2 局部变量 98 6.2.3 计算逃逸变量 99 6.2.4 临时变量和标号 100 6.2.5 两层抽象 100 6.2.6 管理静态链 102 6.2.7 追踪层次信息 102 程序设计:栈帧 103 推荐阅读 103 习题 103 第7章 翻译成中间代码 106 7.1 中间表示树 106 7.2 翻译为树中间语言 108 7.2.1 表达式的种类 108 7.2.2 简单变量 111 7.2.3 追随静态链 112 7.2.4 数组变量 113 7.2.5 结构化的左值 114 7.2.6 下标和域选择 114 7.2.7 关于安全性的劝告 115 7.2.8 算术操作 116 7.2.9 条件表达式 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值