實現簡易的C語言編譯器(part 5)

? ? ? ? 到這里,我們已經研究了詞法分析中表達式和語句的描述和實現。這一部分,我們接著剖析聲明這一塊內容。

3.3 聲明(declaration)

3.3.1 基本數據類型

? ? ? ? 還是先從最簡單的基本數據類型開始。對于如下的C語言代碼:

int a;
char* b;
int** c;
int add(int x, int y);
int printf(char * format, ...)

由于C語言是強類型語言,聲明必然是以類型符開始的。歸納上面幾條聲明的特點,就得到了關于類型符的描述:

type_specifier : INT
               | CHAR 

? ? ? ? 類型符后面的則稱之為變量。第一條聲明,變量就是一個單獨的標志符;緊接著后面的兩條聲明由于有指針的存在,需要用到前面遞歸的描述方法,直到遇到標志符為止。于是,聲明的變量的描述就可以表述為:

declarator : ID
           | * declarator 

對于最后兩條函數聲明,括號是主要的特征。同時,又有含參數和不含參數的聲明形式,可以擴展標志符的表示范圍,得到下面的描述:

declarator : direct_declarator
           | * declarator 

direct_declarator : ID
                  | direct_declarator ( parameter_type_list ) 
                  | direct_declarator ( )

最終,上面的5條聲明,包括變量或者函數,可以統一描述為:

variable_declaration : type_specifier declarator

和前面的表達式的描述方法非常類似,關鍵是要知道如何歸納抽象。需要說明的是,parameter_type_list就是對函數參數的表示方法,本質上也是變量的聲明,只是可以用逗號隔開,進行多次聲明:

parameter_type_list : variable_declaration
                    | parameter_type_list, variable_declaration

? ? ? ? 這樣,我們便得到了聲明的最終表達形式:

declaration : variable_declaration ; 

? ? ? ? 對于C語言中的基本數據類型的分析就到此為止。接著,我們繼續分析C語言中另外三種非常重要并且也非常常用的數據類型:數組,結構體和枚舉。

3.3.2 數組(Array)

? ? ? ? 這里,我們只討論最簡單的一維數組。在C語言中,我們這樣聲明數組:

int arr[3];
int arr[] = {1, 2};

? ? ? ? 先不考慮賦值操作(后面我們統一分析),有沒有發現,數組的聲明和函數的聲明結構很類似,唯一的區別是圓括號和方括號。因此,只需要補充上面的描述:

direct_declarator : ID
                  | direct_declarator ( parameter_type_list ) 
                  | direct_declarator ( )
                  | direct_declarator [ const_expression ] 
                  | direct_declarator [ ]

這里,我們引入了const_expression,顧名思義,就是值為常數的表達式,可以簡單描述為:

const_expression : primary_expression

因為數組定義必須首先分配固定大小的內存,我們會在生成匯編代碼的時候詳細地研究這一塊內容。

3.3.3 結構體(Structure)

? ? ? ? 結構體也是一種特殊的數據類型,主要的聲明方式為:

struct Point {
    int x;
    int y;
};
struct Point point;

可以發現,結構體的聲明和基本數據結構的聲明類似,如果對應起來,就是這里是以struct 結構體名字開頭,然后是變量名。也就是說,我們只需要再單獨定義一種針對結構體的類型符即可,得到:

type_specifier : INT
               | CHAR 
               | struct_specifier

仔細分析結構體大括號的內部結構,其實就是由普通的數據類型的聲明或者可能存在的嵌套的結構體聲明組成的集合。因此,可以描述為:

struct_specifier : struct STRUCT_ID 
                 | struct STRUCT_ID { struct_declaration_list }

struct_declaration_list : struct_declaration
                        | struct_declaration_list  struct_declaration

struct_declaration : type_specifier declarator ;

為了和普通變量名的區別開來,這里引入了STRUCT_ID來單獨表示結構體的名字,它和變量名是有區別的。

3.3.4 枚舉(Enumerate)

? ? ? ? 熟悉了結構體的描述,枚舉也就大同小異了,我們常用的聲明方式如下:

enum COLOR { RED, BLUE = 2, YELLOW };
enum { Mon, Wed, Fri } week;
enum COLOR color;

? ? ? ? 仿照結構體的描述,更新后的類型符為:

type_specifier : INT
               | CHAR 
               | struct_specifier
               | enum_specifier

對于枚舉聲明中大括號內部的結構,再結構體的描述基礎上,稍微變通一下,就可以得到下面的描述:

enum_specifier : enum ENUM_ID
               | enum ENUM_ID { enum_declarator_list }

enum_declarator_list : ENUM_MEMBER_ID
                     | enum_declarator_list, ENUM_MEMBER_ID

同樣的,引入ENUM_ID來單獨表示枚舉名。由于枚舉成員變量需要是一個常值,再引入ENUM_MEMBER_ID進行表示。

? ? ? ? 至此,我們將表達式、語句和聲明用我們自己規定的結構進行了抽象描述,完成了語法分析第一步的工作。再進入第二步內容的時候,我們看一看有沒有什么遺漏的地方。當時存在,比如說在聲明變量的同時進行初始化,也就是常說的: 定義

3.3.5 變量定義(Definition)

? ? ? ? 在C語言中,允許我們采用如下的方式進行變量的聲明:

int a = 1, *b;
char str[] = {'a', 'b', 'c'};
struct Point point = {0, 0};

即聲明的同時進行變量的定義,也就是需要增加對變量進行賦值的描述。同時可以采用逗號分隔,聲明多個變量,這種情況前面我們已經處理過了,只需要轉換成_list形式即可。于是,補充之后對描述為:

declaration : type_specifier init_declarator_list ;

init_declarator_list : init_declarator
                     | init_declarator_list, init_declarator

init_declarator : declarator 
                | declarator = initializer

initializer : expression
            | { initializer_list }

initializer_list : initializer
                 | initializer_list, initializer

? ? ? ? 看上去還是很好理解的,那么函數呢?C語言中,函數的定義為:

int printf(char * format, ...)
{
    ...
}

熟能生巧,一步到位:

function_definition : type_specifier declarator compound_statement

? ? ? ? 至此,我們將會處理到的C語言結構已經全部用抽象的結構描述完畢。但是,對于一個完整的C編譯器來說,還有很多內容沒有涉及到。本質上來說,這些忽略的內容也是很好用抽象結構表示的,只是越往后,它們涉及的工作量將會非常多。因此,這里將其省略,只保留了相對來說易于理解和處理的部分,便于抓住對編譯器的宏觀認識和理解。
? ? ? ? 這些描述目前都還只是零散的表示。為方便后續處理,需要將這些內容全部聯系起來,我們將在下一部分詳細研究。

實現簡易的C語言編譯器(part 0)
實現簡易的C語言編譯器(part 1)
實現簡易的C語言編譯器(part 2)
實現簡易的C語言編譯器(part 3)
實現簡易的C語言編譯器(part 4)
實現簡易的C語言編譯器(part 6)
實現簡易的C語言編譯器(part 7)
實現簡易的C語言編譯器(part 8)
實現簡易的C語言編譯器(part 9)
實現簡易的C語言編譯器(part 10)
實現簡易的C語言編譯器(part 11)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,250評論 6 530
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 97,923評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,041評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,475評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,253評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,801評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,882評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,023評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,530評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,494評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,639評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,177評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,890評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,289評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,552評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,242評論 3 389
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,626評論 2 370

推薦閱讀更多精彩內容

  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學習記錄文檔,今天18年5月份再次想寫文章,發現簡書還為我保存起的...
    Jenaral閱讀 2,798評論 2 9
  • 注:這是第三遍讀《C語言深度解剖》,想想好像自從大學開始就沒讀完過幾本書,其中譚浩強的那本《C語言程序設計(第四版...
    HavenXie閱讀 1,742評論 1 6
  • 謹記 什么是價值?或許沒有多少人能夠明白,其實價值并不是實際存在的,它應該是一種體現,比如為城市點綴最美好的一面而...
    長風留言閱讀 2,486評論 0 15
  • 記住了,今天是你與過去道別的分水嶺 忘記煩惱,忘卻所有憂傷 不要去貪戀太多, “不要去關注靈魂” 你只去關注你的親...
    一池清荷_ce0e閱讀 699評論 0 11
  • 吻到了秋天的額頭 樹葉泛黃俯沖大地 平靜的絲綢還沒有撕裂 輕松反射陽光的溫暖 不必故作匆忙慌張 坐在塔影下 被美麗...
    團結巷徐閱讀 175評論 0 0