符號表和型別系統的程式碼實現
前幾節,我們討論的符號表和型別系統的基本原理,這一節,我們看看如何從程式碼上實現前面我們探討的內容,畢竟,實踐才是檢驗真理的唯一標準,我們仍然基於前面說過的宣告語句:
long int *x, y;
看看,在對該語句的語法解析過程中,如何構造相應的符號表,以及對變數x,y構造他們的型別系統。我們將重走一遍上面語句的語法解析流程,在解析過程中,我將把符號表和型別系統的實現邏輯穿插其中。
語法解析流程及符號表和型別系統的實現
1:解析器首先做一次shift操作,將long讀入,然後返回一個TYPE標籤。
2: 通過 type_specifier -> TYPE, 進行一次reduce操作,此時,我們生成一個Specifier物件,這樣,在解析堆疊頂部的是非終結符type_specifier,在屬性堆疊上,對應的是Specifier物件:
上圖左邊對應的是解析堆疊,右邊對應的是屬性堆疊。
3: 接著是根據表示式type_or_class -> type_specifier, specifiers->type_or_class, 連續進行兩次reduce操作,這兩次reduce不需要進行任何操作,只需要把第一次生成的Specifier物件傳達到相應屬性堆疊上就可以,於是,這兩次reduce後,解析堆疊和屬性堆疊的對應關係如下:
4:讀取int, 進行一次shift操作,把int對應的標籤TYPE,傳入解析器.
5:根據type_specifier->TYPE,做一次reduce操作,同時生成對應的Specifier物件, 於是解析堆疊和屬性堆疊情形如下:
6: 接著根據表示式type_or_class -> type_specifier, 做reduce操作,同時把前一步驟的Specifier物件傳入屬性堆疊的對應位置:
7: 根據表示式表示式 specifiers ->specifiers type_or_class 做reduce操作,這次reduce的同時,我們需要將生成的兩個specifier合成一個,完成後解析堆疊和屬性堆疊的情況如下:
8: 根據opt_specifiers -> specifiers 做一次reduce操作:
9:接下來是連續兩次shift操作,把*對應的標籤START和變數x對應的標籤NAME,依次讀入解析器。
10:根據表示式 new_name -> NAME, 進行reduce操作,同時生成一個Symbol物件
10. 根據表示式var_decl -> new_name 進行reduce操作,這次操作不生成新的物件,只是把上面生成的symbol物件轉移到對應的屬性堆疊:
11:接下來是根據表示式 var_decl -> STAR var_decl做reduce操作,此時由於遇到表示指標的*號,因此要生成一個Declarator物件:
12: 根據表示式ext_decl->var_decl, ext_decl_list->ext_decl 做reduce操作:
13: 讀入逗號,將其對應的標籤輸入解析器
14: 讀入變數y, 將它對應的標籤NAME, 讀入解析器
15: 像讀入x時,一樣,生成對應的Symbol物件,然後根據表示式var_decl->new_name, ext_decl->var_decl 進行reduce操作後,堆疊情形如下:
16: 根據表示式 ext_decl_list -> ext_decl_list COMMA ext_decl 進行reduce,由於x, y屬於同一個作用域,因此此時要將x ,y 對應的Symbol物件連線起來:
17:讀入分號,並把它的Token輸入解析器
18: 根據表示式ext_def->opt_specifiers ext_decl_list SEMI 做reduce操作,此時,把最早建立的Specifier加入到每個Symbol 物件的型別列表中:
然後再把Symbol佇列中的每一個Symbol物件新增到符號表中,那麼整個符號表和型別系統的建立過程就算結束了。