編譯器結構

作為系統軟體,編譯器的設計與實現是非常複雜的。對於一個相對複雜的系統,通常的解決方法是將系統分解成若干較小且便於處理的小系統,分別實現後將其組織成一個完整的複雜系統,這就是"分治法"的思想。實際上,計算機科學家正是運用這種思想來設計與實現編譯器、作業系統、網路通信協定等複雜的大型系統軟體的。

基本介紹

  • 中文名:編譯器結構
  • 外文名:Compiler construction
  • 所屬學科:計算機網路
  • 套用領域:系統設計
  • 工作步驟:7步
  • 編寫語言:Pascal語言
介紹,工作過程,端,語言,

介紹

作為系統軟體,編譯器的設計與實現是非常複雜的。對於一個相對複雜的系統,通常的解決方法是將系統分解成若干較小且便於處理的小系統,分別實現後將其組織成一個完整的複雜系統,這就是"分治法"的思想。實際上,計算機科學家正是運用這種思想來設計與實現編譯器、作業系統網路通信協定等複雜的大型系統軟體的。

工作過程

編譯器的翻譯過程是非常複雜的,但就過程本身而言,與自然語言翻譯卻有不少相近之處。例如,把英語句子翻譯為漢語句子時,通常需要經過下列幾個步驟:
1)對句子中的每個英語單詞進行識別。
2)對句子的語法結構進行分析。
3)分析句子的基本含義,進行初步翻譯。
4)修飾譯文,使之更加符合漢語的表達習慣。
5)將譯文整理書寫記錄。
編譯器的工作過程與自然語言翻譯過程比較類似,亦可劃分為五個階段:詞法分析、語法分析、語義分析與中間表示生成、代碼最佳化、代碼生成。
1.詞法分析
詞法分析的任務就是對輸入的源程式進行掃描分析,識別出一個個的單詞(Token),並進行歸類。這裡的"單詞"可以理解為源程式中具有獨立含義的不可分割的字元序列,與自然語言中的單詞概念有一定區別。一般而言,根據程式設計語言的特點,單詞可以分為五類:關鍵字標識符常量運算符、界符。以一個C語言的條件語句為例:
if(aa&&10==0)aa=100;
詞法分析的結果是識別出如下的單詞符號:
關鍵字
界符
標識符
運算符
常量
運算符
if
(
aa
&&
10
==
常量
界符
標識符
運算符
常量
界符
0
)
aa
=
100
;
2.語法分析
語法分析的任務就是在詞法分析的基礎上,根據程式設計語言的語法規則(文法),把單詞流分解成各類語法單位(語法範疇),如"語句"、"表達式"等。理論上講,通過語法分析,編譯器可以準確無誤地判斷輸入源程式是否滿足語言的語法規則。例如,語法分析可以判斷如下語句是錯誤的。
ifaa%%10==9aa=100; for(i<0)i++;
不過,實際情況並非完全如此,這主要與文法定義的細化程度有直接的關係。當程式設計語言的設計人員把文法定義得比較寬泛時,也就意味著依據此語法規則,編譯器不能在語法分析階段發現所有的語法錯誤,只能將錯誤遺留給後續階段處理。表面上看,語法分析並不像詞法分析有直觀的輸出結果,而僅僅完成了輸入源程式的語法判定工作。實際上,語法分析是編譯器前面三個階段(合稱為前端)的主控模組。
3.語義分析與中間表示生成
語義分析與中間表示生成的任務就是在語法分析的基礎上,分析各語法單位的含義,並進行初步的翻譯,即生成中間表示形式。有時,這兩個任務是密不可分的,故通常將其合併為一個階段討論。語義分析主要是檢查輸入源程式的語義是否正確,例如,變數使用前是否定義、同一作用域內變數是否重名等。中間表示生成將根據輸入源程式的語義生成語義等價中間表示形式。中間表示是一種由編譯器設計人員定義、使用的形式,對於用戶是完全透明的。中間表示形式的定義是值得深入研究的,因為它直接決定了編譯器前、後端的設計複雜度,也決定了編譯器前端與目標語言之間的耦合程度。中間表示的形式也非常多,包括四元組、三元組、語法樹、DAG圖等,並不一定是讀者理解的通常的代碼形式。例如,lcc的中間表示就是一種DAG的形式。當然,近似於彙編指令形式的四元組、三元組可能是最為常見的中間表示形式。
4.代碼最佳化
代碼最佳化的任務就是對生成的中間表示進行最佳化處理,得到占用空間較小、執行效率較高的目標代碼。由於中間表示是由計算機自動生成的,不可能像手工編碼那樣精煉,因此,編譯器需要藉助最佳化處理對目標代碼進行精簡。隨著前端技術的相對成熟,最佳化技術逐漸成為編譯技術領域的核心研究課題之一。
5.代碼生成
代碼生成的任務就是將中間表示形式翻譯成目標語言描述的程式代碼。本階段是與目標計算機硬體系統結構密切相關的,其工作也非常複雜,如暫存器的調度、指令的選擇、指令的調度等。並且,這個階段還涉及許多與目標計算機硬體系統有關的最佳化技術,稱為"指令級最佳化"。通常,目標代碼的形式可以是彙編語言代碼、機器語言代碼、其他語言的代碼。早期,目標代碼多為機器語言代碼。然而,隨著彙編器、連結器的成熟,彙編語言代碼逐漸取代了機器語言代碼,成為目標代碼的首選。近年來,隨著虛擬機技術的出現與發展,目標代碼的概念可能還會改變。例如,由於.NET Framework的盛行,許多編譯器(如Delphi .NET、ML、SmallTalk等)都可以生成面向CLR的目標程式。
以上五個階段是一種典型的分類觀點。事實上,並非所有的編譯器都包含這五個階段。例如,有些簡單語言的編譯器完全可以省去中間表示形式,直接生成目標代碼。再如,一些並不苛求最佳化的編譯器完全可以省去最佳化階段。這裡所提及的五個階段只是大多數編譯器的設計經驗而已。除了以上五個階段之外,有些編譯器還包括兩個非常重要的組成部分:符號表管理、出錯處理。
6.符號表管理
符號表是一系列用於記錄各個分析階段所獲取信息(如變數名、作用域、函式形參等)的數據表格,這些表格的維護貫穿於整個編譯過程。顯然符號表的設計和管理是編譯器構造過程中的一項極其重要的任務。
7.出錯處理
對於輸入源程式的各種錯誤,編譯器必須給出比較準確的出錯報告,以便用戶及時準確地定位、修改。編譯過程的每一個階段都可能檢測出錯誤,其中,絕大多數錯誤可以在編譯的前三個階段檢測出來。當然,真正的商用編譯器並不限於此,可能還涉及更複雜的出錯恢復。出錯恢復主要是當編譯器檢測到錯誤之後,儘可能按照語義修正錯誤。注意,出錯恢復的目的並不在於真正修復用戶程式,而只是試圖一次檢測更多的錯誤。當然,這是基於編譯器預測機制實現的。
編譯器結構

根據完成任務不同,可以將編譯器的組成部分劃分為前端(Front End)與後端(Back End)。前端主要指與源語言有關但與目標機無關的部分,包括詞法分析、語法分析、語義分析與中間表示生成。後端主要指與目標機有關的部分,包括代碼最佳化和目標代碼生成等。"端"概念的提出對於編譯技術的發展起到了至關重要的作用,它使編譯器的框架更明晰,更利於集成與構造。

語言

目標代碼是機器語言彙編語言,彙編語言可以通過彙編器生成機器碼。彙編語言的定義取決於CPU的體系架構,目前主要有三種:x86/x64, ARM, MIPS。
中間代碼是虛擬機的機器語言,虛擬機目前主要有四種:CLR, JVM, Parrot, LLVM。CLR用於.Net平台,JVM用於Java語言,這兩個是基於的虛擬機。Parrot用於腳本語言,比如Perl,Python,Ruby等;LLVM用於C、C++等語言,這兩個是基於暫存器的虛擬機。在性能上比較而言,基於暫存器的虛擬機優於基於棧的虛擬機。
標準Pascal語言作為設計藍本,主要有如下幾個原因:
(1)Pascal語言是一門嚴謹且優美的程式設計語言。
(2)Pascal語言功能非常強大,適合各種系統軟體、套用軟體設計。
(3)Pascal語言數據類型非常豐富。例如,集合類型、函式類型、指針類型等。
(4)Pascal語言的語義複雜度不如C語言,故有利於編譯器設計與實現。同時,便於初學者學習理解。
正由於上述優點,Pascal仍然是算法設計的主要描述語言,也是IOI(國際奧林匹克信息學競賽)三種參賽程式設計語言之一。

相關詞條

熱門詞條

聯絡我們