前言
生成抽象語法樹之后,下一步要做的就是對其進行分析,這個過程就稱為語義分析,在此步驟我們需要做的有
- 變量引用的消解
- 類型名稱的消解
- 類型定義檢查
- 表達式的有效性檢查
- 靜態(tài)類型檢查
以上的五個過程的執(zhí)行順序有著一定的限制.就是類型名稱的消解是類型定義檢查的前提,而表達式的有效性檢查在前三個過程結(jié)束前是不能執(zhí)行的,介于它們執(zhí)行順序的關(guān)系,可以由下圖表示

變量引用的消解
變量引用的消解是指將所有變量和它們的定義關(guān)聯(lián)起來,例如變量a可能是全局變量a,也可能是靜態(tài)變量a,還可能是局部變量a,為了消除這種不確定性,我們對它們進行和定義的關(guān)聯(lián).
具體操作就是給變量節(jié)點對象增加變量定義的屬性.
類型名稱的消解
在有的語言中,類型名稱TypeRef和類型實體Type是分開處理的,原因是TypeRef可以理解為類型的聲明,Type則是類型的實現(xiàn),我們有可能在實現(xiàn)之前就使用了這種類型.所以才會區(qū)分處理.
這里的消解,是將TypeRef和Type進行關(guān)聯(lián).通過一個TypeTable的對象去管理它們的對應(yīng)關(guān)系.
類型定義的檢查
類型定義的檢查是檢查在定義類型時使用了不符合邏輯的定義聲明,比如
- 包含 void 的數(shù)組、結(jié)構(gòu)體、聯(lián)合體
- 成員重復(fù)的結(jié)構(gòu)、聯(lián)合體
- 循環(huán)定義的結(jié)構(gòu)體、聯(lián)合體
1和2的實現(xiàn)非常簡單,這里就不贅述了,3可以這樣來理解,結(jié)構(gòu)體或者聯(lián)合體對其他類型是引用可以看做是一個有向使用,相互之前的關(guān)系可以做成一個圖


如果存在閉環(huán),則存在循環(huán)定義.
檢測有向圖中的閉環(huán)的算法
要檢測有向圖是否存在閉環(huán),可以使用如下算法.
- 選擇任意一個節(jié)點并標注為
查找中 - 沿著邊依次訪問所有與該節(jié)點相鄰的節(jié)點
- 如果訪問到的節(jié)點沒有標注任何狀態(tài),則將節(jié)點標注為
查找中;如果標注了``查找結(jié)束,則不做任何處理,返回之前的節(jié)點;如果標注為查找中`,則說明存在閉環(huán). - 從當(dāng)前的節(jié)點重復(fù)步驟2和3,如果已經(jīng)沒有可訪問的相鄰節(jié)點,則將該節(jié)點標注為
查找結(jié)束,并沿原路返回. - 按照上述流程對所有節(jié)點進行處理,如果沒有遇到
查找中狀態(tài)的節(jié)點,就說明不存在閉環(huán).
表達式有效性檢測
表達式需要檢測的問題有
為無法賦值的表達式賦值(例:1 = 2 + 2)
使用非法的函數(shù)名調(diào)用函數(shù)(例:"string"("%d\n", i))
操作數(shù)非法的數(shù)組引用(例:1[0])
操作數(shù)非法的成員引用(例:1.memb)
操作數(shù)非法的指針間接引用(例:1->memb)
對非指針的對象取值(例:*1)
對非左值的表達式取地址
靜態(tài)類型檢查
語言的操作都對操作數(shù)的類型有所限制.例如結(jié)構(gòu)體之間無法用 + 進行 加法運算,指針和數(shù)值之間無法用 * 進行乘法運算,將數(shù)組傳遞給參數(shù)類型為 int 型的函數(shù)會出現(xiàn)莫名其妙的結(jié)果.
對允許的操作數(shù)類型進行限制,例如 * 操作只適用于類型相同的數(shù)值之間,在編譯過程中檢查是否符合這樣的限制的處理就是靜態(tài)類型檢查(static type checking).
靜態(tài)類型檢測的隱式類型轉(zhuǎn)換
二元運算 * 只允許在相同類型的整數(shù)之間進行,但是如果在不同類型的數(shù)值之間進 行 * 運算,為了能夠正常運算,編譯器會自動對操作數(shù)的類型進行轉(zhuǎn)換.這樣的轉(zhuǎn)換就稱為隱式類型轉(zhuǎn)換(implicit conversion).
例如,當(dāng)int類型的值和long類型的值進行乘法運算時, 編譯器會將兩個操作數(shù)統(tǒng)一為 long 類型.
另外,在一些不得不強行轉(zhuǎn)換為特定類型的情況下也會發(fā)生隱式類型轉(zhuǎn)換.
例如,當(dāng) return 返回值的類型和函數(shù)返回值的類型不一致時,必須轉(zhuǎn)換為函數(shù)返回值的類型
賦值運算時必須轉(zhuǎn)換為和左值一致的類型等。顯式聲明的函數(shù)返回值或變量類型無法輕易改變,因此 只能利用隱式轉(zhuǎn)換來改變值的類型。
在靜態(tài)類型檢查過程中也會實施隱式類型轉(zhuǎn)換