編譯概覽

詞法分析

詞法分析器讀入一個個的字符,並將他們組合成單詞,也就是程序中最小的有意義的單位。詞法分析器的主要作用就是爲了簡化分析器的工作,它能減小輸入的規模並刪除額外的字符。詞法分析器通常還要刪去註釋,如果需要就生成一個表格,給各個單詞做好行列位置標記,以便後續階段能更容易生成好的診斷信息。

語法分析

語法分析階段會將詞法分析階段得到的單詞組織爲一棵語法分析樹,這棵樹用程序的各個組成部分標明其高層結構。
這些部分的組合方式是通過一組可能遞歸的規則定義的,這樣的一組規則稱爲一個上下文無關文法
我們說這種上下文文法定義了語言的語法形式,因此分析過程也就是做語法分析。

在詞法分析和語法分析的過程中,編譯器需要檢查程序裏的所有單詞是否都構造良好,單詞序列是否符合上下文無關文法所定義的語法。
任何畸形的單詞都應導致掃描器產生錯誤信息,任何不符合語法的單詞序列應該導致語法分析器產生錯誤信息。

語義分析

語義分析也就是確定程序的意義。
編譯的語義分析階段需要識別出什麼時候同一單詞的多個出現引用的是同一個程序實體,並且要保證這些使用的相容性。
在大部分語言裏,語義分析器需要跟蹤標識符和表達式的類型,這既是爲了驗證使用的相容性,也用於指導後面階段中的代碼生成。
爲了支持所需的工作,語義分析器通常構造並維護着一個符號表數據結構,符號表把每個標識符映射到有關它的已知信息。這些信息包括各個標識符的類型信息、內部結構,以及作用域。
利用這一符號表,語義分析器就能貫徹執行許多語義分析規則,這些規則是上下文無關文法和語法分析樹無法表示的。
在許多編譯器裏,語義分析的工作通過一組語義動作子程序的形式表示,當語法分析器識別出自己當時到達了某個產生式裏的一個特定點時,就會去調用其中的某個子程序。
當然,並不是所有語義規則都能在編譯時檢查,能在編譯時檢查的稱爲語言的靜態語義,必須在運行時檢查的就稱爲語言的動態語義。
當編譯器無法靜態地貫徹某些規則時,通常它就會產生一些代碼,讓這些代碼在運行中執行適當的檢查,如果某個檢查失敗,這個程序就會終止或者產生一個異常。
不幸的是,有些規則的貫徹可能帶來極高的、根本無法接受的代價,或者根本就是不可能貫徹的,這時語言的實現有可能根本不去檢查他們。

語法分析樹有時也稱爲具體語法樹,因爲這種樹中的一切都是明示的,完全而又具體,顯示瞭如何根據相應上下無關文法推導出特定的單詞序列。
在我們知道了一個單詞序列爲合法之後,後續的編譯階段就不再需要語法分析樹上的許多信息了。

在靜態檢查語義規則的過程中,語義分析器通常還同時把這種語法分析樹轉換爲一顆抽象語法樹,刪除樹內部的大部分人爲結點。
語義分析器還爲剩下的結點標註有用的信息,例如加入從標識符到對應符號表項的指針。附在特定結點上的標註被稱爲它的屬性。

中間代碼生成

在許多編譯器裏,帶標註的語法樹就是從前端傳遞到後端的中間形式,而在另一些編譯器裏,語義分析器最後還要遍歷這棵樹,生成某種另外的中間形式。
這一形式通常類似於某種特別簡單的理想機器的彙編語言。
對於一組相關的編譯器,幾種語言的前端和爲幾種機器服務的後端可能共享着同一種中間形式。

目標代碼生成

編譯器的代碼生成階段把中間形式翻譯到目標語言。
有了語法樹中所包含的各種信息,生成正確的代碼一般來說並不是很困難的工作。爲了生成彙編或者機器語言,代碼生成器需要整個符號表,給每個變量指定位置;還要遍歷語法樹,生成對這些變量的裝入和保存動作,插入適當的算術運算、檢測和分支。

代碼生成器常常把符號表也保存起來,以便後面的符號排錯程序使用。
例如可以將符號表包含在目標代碼裏,作爲註釋或者其他非執行的部分。

專門針對機器的代碼改進

代碼改進通常被說成是優化,雖然從所有絕對的意義上看,它都很難將任何東西做成最優的。這是編譯過程中一個可選的階段,其目標就是把程序變換到一個新版本,該版本能更有效地計算出同樣的結果——速度更快或者使用的更少的存儲,或者兩方面都更好。

有些改進是與機器無關的,可以在中間形式上通過一些變換完成。
另外一些改進則需要深入瞭解目標機器(瞭解目標語言裏的程序如何執行),必須通過對目標語言的變換完成。
這樣,代碼改進將表現爲編譯過程裏的另外兩個階段,一個在剛剛做完語義分析和中間代碼生成之後,另一個在做完目標代碼生成之後。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章