編譯器,近在咫尺卻又遠在天邊。當我們寫下任何非機器語言**後,我們都需要借助編譯器將這些**變為通過計算機可執行的狀態。但是,就是這樣乙個使用率極高的程式,我們對其卻知之甚少。什麼是編譯器?編譯器對我們的**做了什麼?又是怎麼做的呢?如果你也懷有這些疑問,想要深入編譯器內部一**竟的話,那就隨我一起踏上這趟編譯器實現的旅程吧。
廣義上,編譯器是這樣乙個程式:其讀入a語言**,並輸出b語言**。如下圖所示:
+-------+
a語言** -> | 編譯器 | -> b語言**
+-------+
僅從定義上看,a、b可以是同一種語言。也就是說,如果我們寫了乙個只是具有「複製貼上」功能的程式,其也可以被稱為是乙個編譯器。但顯然,這樣的編譯器是無意義的。在實際中,編譯器的輸入一般是高階語言**,如c語言、python語言等,而編譯器的輸出一般是低階語言**,如組合語言、各種位元組碼等。組合語言**經由組合語言編譯器繼續編譯,最終產生機器語言,以供計算機執行;而位元組碼可由能夠執行此位元組碼的虛擬機器執行。這樣,就完成了乙個程式從編寫到執行的過程。
編譯器的內部並不是乙個整體,而是由多個元件分工合作,共同完成編譯功能。這些元件總體上可被分為兩個部分:編譯器前端和編譯器後端。如下圖所示:
+----------+ +----------+
a語言** -> | 編譯器前端 | -> 中間** -> | 編譯器後端 | -> b語言**
+----------+ +----------+
由於我們寫下的高階語言**並不是編譯器比較喜歡的形式,故編譯器通過編譯器前端讀取、檢查並重新組織源**,使之等價變換為編譯器喜歡的形式,即中間**;一般來說,語法錯誤也由編譯器前端負責檢查。接下來,編譯器後端就拿著中間**進行進一步的檢查、優化,最終生成目標**。
事實上,編譯器前後端又分別可以進一步細分為多個元件,這些元件將在我們接下來的旅程中逐一講述。
在這次旅程的終點,我們將實現乙個名為cmm(即c minus minus)語言的編譯器,這個編譯器的輸出將是由我們自己設計的一套指令集中的指令所構成的指令檔案。所以,我們還將實現一套虛擬機器程式,以執行編譯器輸出的指令檔案。
cmm語言是一門將c語言的語法進行縮減後得到的語言。其主要特點如下:
編譯器實現之旅 第二章 編譯器前端概觀
在這一章的旅程中,我們將要深入編譯器前端一 竟。看看編譯器前端到底由哪些元件組成,其分別又是在做什麼。似乎比我們想象的要簡單,編譯器前端僅由兩個元件組成,詞法分析器與語法分析器。請看下圖 源 詞法分析器 記號流 語法分析器 抽象語法樹 詞法分析器 lexer 是 前端中的前端 作為整個編譯器的第乙個...
編譯器設計 習題第一章
1.瀏覽器接收html檔案,在螢幕上顯示出來,是乙個解釋執行的過程.2.作為編譯器的使用者,我關注以下5個特性,a.1 編譯完成的速度 a.2 編譯時占用的記憶體 a.3 編譯時臨時檔案占用的空間 a.4 錯誤提示是否使用者友好 a.5 使用是否方便 作為編譯器的設計者,我關注以下5個特性,b.1 ...
編譯器實現(六)
語義分析可以分為兩類。第1類是程式的分析,要求根據程式語言的規則建立其正確性,並保證其正確執行。對於不同的語言來說,語言定義所要求的這一類分析的總量變化很大。在lisp和smalltalk這類動態制導的語言中,可能完全沒有靜態語義分析 而在a d a這類語言中就有很強的需求,程式必須提交執行。其他的...