1. 程式人生 > >現代編譯原理——第四章:語義分析以及原始碼

現代編譯原理——第四章:語義分析以及原始碼

  轉自: 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 ;
}
複製程式碼