農林漁牧網

您現在的位置是:首頁 > 林業

編譯器入門,語義分析

2022-02-02由 閒聊程式碼 發表于 林業

語義型別是什麼

語義分析,是語法分析與中間程式碼生成之間的過渡步驟,是基於抽象語法樹AST的進一步分析,主要是3個方面:

1,型別檢查和自動型別轉換,

對抽象語法樹的每一個節點的輸入進行型別檢查。

在型別不一致時新增自動型別轉換(type cast),必要時給出warnning資訊。

無法自動型別轉換的,給出error資訊。

確定該節點的輸出結果型別,用於父節點的型別分析,依次遞迴。

2,常量表達式的計算,

常量表達式的結果在這裡提前算出來,用一個常數代替,減少後續環節的運算量,提高生成的目的碼的效率。

例如,int sec = 60 * 60,

替換為,int sec = 3600,

這樣在生成機器碼的時候就不需要使用乘法指令,直接一個mov指令把常數3600

賦值給sec就行了。

3,運算子過載和函式過載,

已經完成了型別檢查的情況下,在這裡是可以確定具體選擇哪一個過載函式的,把它轉換為對過載函式的呼叫。

例如有個Mat矩陣類,該類有幾個加法運算的過載函式,那麼在這裡就可以確定輸入引數是不是含有矩陣,是2個矩陣相加還是矩陣加上一個常數,etc。

把這個加法運算子,轉化為對Mat類的對應函式的呼叫。

虛擬函式呼叫是沒法在這裡確定的,因為基類指標的具體子類型別是動態的,只能執行時查詢它的虛擬函式表獲得實際呼叫的函式。

語義分析,是遞迴遍歷AST樹,並對它的節點進行分析。

從語義分析開始,後續的所有分析都是以AST樹的節點為基礎的,不同的階段使用的分析函式不同而已。

所以,我們可以這麼設計AST節點的資料結構:

struct ast_node_s

{

int type; 節點型別

struct ast_node_s* parent; 父節點

struct ast_node_s** childs; 子節點列表

int nb_childs; 子節點個數

uint32_t flags;

各種標示,例如常量、常量字面值等等

} ;

父節點和子節點列表,是構成整個AST樹的基礎。

運算子的優先順序,也是體現在生成語法樹時,誰是子節點,誰是父節點,子節點的優先順序更高。

節點型別,就是節點的語義,標示著該用哪個函式去處理當前節點。

在語義分析階段,和三地址碼生成階段,選擇的處理函式是不同的。

當然,不同型別的節點,選擇的處理函式也是不同。

我們可以根據當前的分析階段和節點型別,去相應的函式表裡查詢對應的函式,並呼叫它。

過了語法分析之後,終於不再有那種互相交織著的遞迴呼叫了,不那麼擰巴了:(

以後都是對語法樹的遍歷,或者三地址序列的遍歷。

編譯器入門,語義分析