jacksplwxy

现代编译原理——第四章:语义分析以及源码

  转自: 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 ;
}
复制代码

 

posted on 2018-12-02 11:47  jacksplwxy  阅读(2594)  评论(0编辑  收藏  举报

导航