编译原理总概述笔记
編譯原理
- 編譯原理
- 程序設計語言分類
- 翻譯
- 編譯
- 解釋
- 編譯的轉換過程
- 兩階段的轉換
- 三階段的轉換
- 編譯程序的工作
- 詞法分析
- 語法分析
- 中間代碼生成
- 優化
- 目標代碼生成
- 表格與表格管理
- 出錯處理
- 語句翻譯實例過程
- 編寫編譯程序方式
編譯原理
是介紹高級程序設計語言變換成計算機硬件所能識別的機器語言,以便計算機進行處理。
程序設計語言分類
- 高級語言
- 匯編語言
- 機器語言
在計算機上如何執行一個高級語言程序?
翻譯
是指能把某種語言的源程序,在不改變語義的條件下,轉換成另一種語言程序—目標語言程序。
編譯
專指由高級語言轉換為低級語言(匯編語言或機器語言),相當于現實中的筆譯。
解釋
接受某高級語言的一個語句輸入,進行解釋并控制計算機執行,馬上得到這句的執行結果,然后再接受下一句。
以源程序作為輸入,不產生目標程序,一邊解釋一邊執行。
優點:直觀易懂,結構簡單,易于實現人機對話。
缺點:效率低,因為不產生目標程序,所以下次要用的話還是要再解釋一遍。
編譯的轉換過程
兩階段的轉換
編譯(compile) — 運行(run)
比如一個Pascal語言源程序a.pas,經過編譯程序進行編譯,轉換成包括機器語言(0和1)的目標代碼的可執行程序a.exe。
三階段的轉換
編譯 — 匯編 — 運行
比如一個C語言源程序a.c,經過編譯程序轉換成匯編語言,再經過匯編程序轉換成目標代碼a.obj或a.exe,此處因為是C語言,所以轉換成的目標代碼為a.obj文件(也是由機器碼構成的)。
接下來就是連接(link)過程,該過程不屬于編譯過程,就是將有關的目標文件彼此相連接,經過連接(link)才將a.obj轉換成a.exe可執行文件。
編譯程序的工作
先看自然語言的翻譯
編譯程序的工作與自然語言的翻譯極為類似。
編譯程序的工作一般分為五或六個步驟(語義分析階段可以再中間代碼生成階段完成):
詞法分析:分析源程序當中的詞寫得對不對。
語法分析:分析句子是什么樣的功能。
語義分析和中間代碼生成:語義分析根據要完成的功能看看這句話的意思對不對,中間代碼生成方便句子轉換成0,1的中間過程,句子到中間代碼很容易,中間代碼到二進制也很容易。
優化:代碼運行的時間空間效率是不是很高,進行優化。
目標代碼生成:最終得到目標代碼。
詞法分析
主要任務是對輸入的源程序字符串進行掃描和分解,識別出一個個的單詞,并轉化成機器比較容易使用的內碼形式。一般內碼可以用二元式(類號,內碼)表示。
通過詞法分析一般可以識別出以下5類單詞:
- 基本字(關鍵字):void,int,float等
- 標識符:a,b,c,d,x,y等
- 整常數:50等
- 運算符:+,*,=等
- 界限符:{},;,()等
描述詞法規則的有效工具是正規式和有限自動機。
正規式是用來確定單詞是不是符合程序語言所要求的規范,用有限自動機來確定。
總之,詞法分析就是掃描源程序字符串,按詞法規則識別出正確的單詞,并轉換成統一規格(類號,內碼)交語法分析使用。
語法分析
該階段的任務就是組詞成句。每一種語言都有一組規則,稱之為語法規則或文法。按照這些文法,可以由單詞組成語法單位,如短語、語句、過程和程序。語法分析就是通過語法分解,確定整個輸入串是否能構成語法上正確的句子和程序等。
賦值語句的語法規則寫成Backus-Naur-Form式,簡稱BNF。其形式是A::=B|C,也就是將A定義為B或C。比如:<句子>::=<主><謂><賓>,也就是句子由主語謂語賓語組成。還有其他語句的語法規則,如條件語句、循環語句、過程調用語句等規則。
語法分析有兩種方法:推導(derive)和歸約(reduce)。分別有最左推導、最右推導、最右歸約、最左歸約。
推導是從文法的開始符號開始,按照語法規則,每次選擇某規則右部的一個候選式取代左部直至識別了句子或者找出錯誤為止。比如:采用最右推導語句x:=a+b*50的分析如下:
其中A就是Assignment的縮寫,意思是賦值語句,稱A為規則的開始符號。如果語句的語法錯誤的話,推不到原語句。
語法分析過程也可以用一棵倒著的樹來表示,也就是語法樹。葉子節點從左至右組合起來就是原語句x=a+b*50。
中間代碼生成
主要任務是對語法分析識別出的各類語法范疇,分析其含義,進行和初步翻譯,產生介于源代碼和目標代碼之間的一種代碼。源代碼生成這種代碼很容易,并且這種代碼不依賴于機器但又便于產生依賴于機器的目標代碼。
分為兩階段工作
- 對每種語法范疇進行靜態語義檢查。
- 若語義正確,就進行中間代碼的翻譯。
中間代碼有多種形式:四元式、三元式、逆波蘭式。四元式使用得最廣。
例如將x=a+b*50變成中間代碼,下圖可以看作將數存入寄存器。
由上表該源語句x:=a+b*50轉換成中間代碼形式是:
中間代碼是為后續的優化和目標代碼生成提供方便,因此中間代碼的選擇往往與所采用的優化技術和計算機硬件結構有關。
優化
優化的任務在于對前一階段產生的中間代碼進行加工變換,使得在最后階段能產生出更為高效(省時間、空間)的目標代碼。
比如上面的中間代碼可變換為如下兩句四元式代碼:
T1:=B?50.0T1:=B*50.0T1:=B?50.0 x:=a+T1x:=a+T1x:=a+T1
優化主要包括:刪除公共子表達式、合并已知量、刪除無用賦值、循環優化等。優化所依據的原則是程序的等價變換規則。
例如,把程序段
轉換成四元式和經優化后產生的四元式用下表表示:
顯然,經優化后循環體縮小了,原來要做701條指令現在只做503條指令;原來要做300次加法,200次乘法,現在只做300次加法,2次乘法。編譯程序所產生的目標代碼質量的高低,主要取決于代碼優化程序功能的強弱。
目標代碼生成
這一階段的主要任務是把經過優化的中間代碼轉化成特定機器上的低級語言代碼。轉換過程需涉及具體機器的指令系統以及寄存器分配等硬件功能。
例如,上述經優化后的中間代碼可生成如下用匯編語言表示的目標代碼:
LOAD???????????R2,b
MUL ??????????? R2,50.0
LOAD???????????R1,a
ADD ??????????? R1,R2
STORE ???????R1,x
目標代碼的形式
- 絕對指令代碼:可立即執行的目標代碼。也就是.exe文件。
- 匯編指令代碼:匯編語言程序,需要通過匯編程序匯編后才能運行。
- 可重定位指令代碼:先將各目標模塊連接起來,確定變量、常數在主存中的位置,裝入主存后才能成為可以運行的絕對指令代碼。也就是.obj文件。
表格與表格管理
表格作用:
用以記錄源程序的各種信息以及編譯過程中的各種狀況。
編譯的五個階段都需要與表格打交道,以便后繼階段使用,也即在編譯過程的各個階段都有查造表、填表等功能。
與編譯前三階段有關的表格有:
符號表、常數表、標號表、分程序入口表、中間代碼表等。
-
符號表:登記源程序中的常量名、變量名、數組名、過程名等的性質、定義和引用狀況。
-
常數表:登記源程序中出現的各種類型字面常數(直接量)的值。
-
標號表:登記源程序中出現的標號的定義和引用情況(此表可與符號表合并)。
-
分程序入口表:登記過程的層號、分程序符號表的入口(指分程序結構的語言)等,有時也可以并入符號表。
-
中間代碼表:記錄四元式序列的表。
例如,對下列FORTRAN程序段:
有下列各表:
符號表:記錄了源程序中出現的三個變量名M、N和K的有關性質。
| M | 整型、變量地址 |
| N | 整型、變量地址 |
| K | 整型、變量地址 |
常數表(CT):記錄了常數1和4的值(已經是內部二進制代碼)
| 1 |
| 4 |
入口名表:記錄了子程序名INCWAP的入口地址,即為四元式表的序號1。
| … | … |
| INCWAP | 二目子程序、四元式序號1 |
標號表:記錄了標號10對應的四元式序號4。
| … | … |
| 10 | 四元式序號4 |
四元式序列表:記錄了源程序翻譯成的四元式序列。
| 1 | link | – | – | – |
| 2 | actpar | INCWAP | 1 | M |
| 3 | actpar | INCWAP | 2 | N |
| 4 | + | M | 1 | K |
| 5 | + | N | 4 | M |
| 6 | := | K | – | N |
| 7 | paract | INCWAP | 1 | M |
| 8 | paract | INCWAP | 2 | N |
| 9 | return | – | – | – |
下面解釋各行序號的意義:
表格管理程序用來對表格的構造、查找和更新。對編譯程序而言這只是工具,是事先編制好、供需要時調用的。選擇一種好的表格結構和查找算法對于構造編譯程序來說是至關重要的。這部分在數據結構中學過。
出錯處理
任務是如果源程序有錯誤,編譯程序應設法發現錯誤,并把有關的出錯信息報告給用戶。由出錯處理程序完成。
錯誤類型:
- 語法錯誤:在詞法分析和語法分析階段檢查出來。
- 語義錯誤:一般在語義分析階段檢測。
語句翻譯實例過程
要翻譯的語句為:
position:=initial+rate?60position:=initial+rate*60position:=initial+rate?60
1.經過詞法分析器,得:
id1:=id2+id3?60id1:=id2+id3*60id1:=id2+id3?60
2.經過語法分析器,得:
3.經過語義分析器,得:
4.經過中間代碼生成,得:
temp1:=inttoreal(60)temp1:=inttoreal(60)temp1:=inttoreal(60)temp2:=id3?temp1temp2:=id3*temp1temp2:=id3?temp1temp3:=id2+temp2temp3:=id2+temp2temp3:=id2+temp2id1:=temp3id1:=temp3id1:=temp3
5.經過優化,得:
temp1:=id3?60.0temp1:=id3*60.0temp1:=id3?60.0id1:=id2+temp1id1:=id2+temp1id1:=id2+temp1
6.經過目標代碼生成器,得:
moveid3,R2move \ \ id3,R2move??id3,R2move#60.0,R2move \ \ \#60.0,R2move??#60.0,R2moveid2,R1move\ \ id2,R1move??id2,R1moveR2,R1move \ \ R2,R1move??R2,R1moveR1,id1move \ \ R1,id1move??R1,id1
編寫編譯程序方式
總結
- 上一篇: 如何创建共享打印机路由器如何打印机共享
- 下一篇: 将py文件打包成exe可执行文件