編譯器的相關知識

一、編譯器的概念

編譯器是將一種計算機語言翻譯爲另一種計算機語言的程序。編譯器將源程序(source language) 
編寫的程序作爲輸入,翻譯產生用目標語言(target language)編寫的等價程序。源程序一般爲高級語言(high-level language),如Pascal 或Delphi,而目標語言則是彙編語言或目標機器的目標代碼(object code),有時也稱作機器代碼(machine code) 
源程序→ 編譯器→ 目標程序 
解釋器也是同編譯器一樣的一種語言翻譯程序。它與編譯器的不同之處在於:它立即執行源程序而不是生成目標代碼。從原理上講,任何程序設計語言都可以被解釋或被編譯。 

二、編譯器的組成部分

(1) 掃描程序(scanner

在這個階段編譯器實際閱讀源程序(通常以字符流的形式表示)。掃描程序執行詞法分析(Lexical analysis):它將字符序列收集到稱作記號(token)的有意義單元中,記號同自然語言,如英語中的字詞相似。因此可以認爲掃描程序執行與拼寫相似的任務。

(2) 語法分析程序(parser

語法分析程序從掃描程序中獲取記號形式的源代碼,並完成定義程序結構的語法分析(syntax analysis),這與自然語言中句子的語法分析類似。語法分析定義了程序的結構元素及其關係。通常將語法分析的結果表示爲分析樹( parse tree)或語法樹(syntax tree)。

(3) 語義分析程序(semantic analyzer

程序的語義就是它的“意思”,它與語法或結構不同。程序的語義確定程序的運行,但是大多數的程序設計語言都具有在執行之前被確定而不易由語法表示和由分析程序分析的特徵。這些特徵被稱作靜態語義( static semantic),而語義分析程序的任務就是分析這樣的語義(程序的“動態”語義具有只有在程序執行時才能確定的特性,由於編譯器不能執行程序,所以它不能由編譯器來確定)。一般的程序設計語言的典型靜態語義包括聲明和類型檢查。由語義分析程序計算的額外信息(諸如數據類型)被稱爲屬性( a t t r i b u t e),它們通常是作爲註釋或“裝飾”增加到樹中(還可將屬性添加到符號表中)。

(4) 源代碼優化程序(source code optimizer

編譯器通常包括許多代碼改進或優化步驟。絕大多數最早的優化步驟是在語義分析之後完成的,而此時代碼改進可能只依賴於源代碼。這種可能性是通過將這一操作提供爲編譯過程中的單獨階段指出的。每個編譯器不論在已完成的優化種類方面還是在優化階段的定位中都有很大的差異。

(5) 代碼生成器(code generator

代碼生成器得到中間代碼(IR,並生成目標機器的代碼。儘管大多數編譯器直接生成目標代碼,但是爲了便於理解,本書用彙編語言來編寫目標代碼。正是在編譯的這個階段中,目標機器的特性成爲了主要因素。當它存在於目標機器時,使用指令不僅是必須的而且數據的形式表示也起着重要的作用。例如,整型數據類型的變量和浮點數據類型的變量在存儲器中所佔的字節數或字數也很重要。

三、編譯器相關的術語

(1) 記號(t o k e n

記號通常定義爲枚舉類型的邏輯項。記號有若干種類型,這其中包括了保留字( reserved word),如I FT H E N,它們表示字符串“ i f”和“ t h e n”;第2類是特殊符號( special symbol ),如算術符號加( P L U S)和減(M I N U S),它們表示字符“ +”和“-”。第3類是表示多字符串的記號,如N U MI D,它們分別表示數字和標識符。

(2) 語法樹(syntax tre e

如果分析程序確實生成了語法樹,它的構造通常爲基於指針的標準結構,在進行分析時動態分配該結構,則整棵樹可作爲一個指向根節點的單個變量保存。結構中的每一個節點都是一個記錄,它的域表示由分析程序和之後的語義分析程序收集的信息。

(3) 符號表(symbol table

這個數據結構中的信息與標識符有關:函數、變量、常量以及數據類型。符號表幾乎與編譯器的所有階段交互:掃描程序、分析程序或將標識符輸入到表格中的語義分析程序;語義分析程序將增加數據類型和其他信息;優化階段和代碼生成階段也將利用由符號表提供的信息選出恰當的代碼。因爲對符號表的訪問如此頻繁,所以插入、刪除和訪問操作都必須比常規操作更有效。儘管可以使用各種樹的結構,但雜湊表卻是達到這一要求的標準數據結構。有時在一個列表或棧中可使用若干個表格。

(4) 常數表(literal table

常數表的功能是存放在程序中用到的常量和字符串,因此快速插入和查找在常數表中也十分重要。但是,在其中卻無需刪除,這是因爲它的數據全程應用於程序而且常量或字符串在該表中只出現一次。通過允許重複使用常量和字符串,常數表對於縮小程序在存儲器中的大小顯得非常重要。在代碼生成器中也需要常數表來構造用於常數和在目標代碼文件中輸入數據定義的符號地址。

(5) 中間代碼(intermediate code

根據中間代碼的類型(例如三元式代碼和P -代碼)和優化的類型,該代碼可以是文本串的數組、臨時文本文件或是結構的連接列表。對於進行復雜優化的編譯器,應特別注意選擇允許簡單重組的表示。

(6) 臨時文件(t e m p o r a ry file

計算機過去一直未能在編譯器時將整個程序保留在存儲器中。這一問題已經通過使用臨時文件來保存翻譯時中間步驟的結果或通過“匆忙地”編譯(也就是隻保留源程序早期部分的足夠信息用以處理翻譯)解決了。存儲器的限制現在也只是一個小問題了,現在可以將整個編譯單元放在存儲器之中,特別是在可以分別編譯的語言中時。但是偶爾還是會發現需要在某些運行步驟中生成中間文件。其中典型的是代碼生成時需要反填( b a c k p a t c h)地址。

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