1. 程式人生 > >《編譯器設計》讀書筆記——上下文相關分析

《編譯器設計》讀書筆記——上下文相關分析

static 拓撲排序 成員 依賴 基本特性 操作數 使用 重載 存儲

將每條語句放到實際的上下文中進行考慮,從而檢測類型和約定方面的錯誤,這種分析一般被稱為“上下文相關分析”(context-sensitive analysis),以區別於語法分析,或者稱為"語義推敲"(semantic elaboration)。

概述

被編譯的程序中的某個名字x,在編譯器能夠為涉及x的計算輸出可執行的目標機代碼之前,以下問題是須被回答的:

  • x中存儲了什麽種類的值?
  • x有多大呢?
  • 如果x是一個過程,它需要獲得哪些參數呢?
  • 對於x的值來說,其生命周期有多長?
  • 誰負責分配x的空間(並初始化它)?

編譯器必須根據源語言的規則和源程序,推導出這些問題的答案及其它信息,但這些問題中有許多(如果不是全部)都超出了上下文無關語法,為了解決這些問題,編譯器必須深入研究程序的語義,詞法分析和語法分析處理的只是程序的形式,而語義分析則進入了上下文相關分析

的領域。

類型

一種抽象範疇,規定了其所有成員共有的性質。常見的類型包括整數,列表和字符串。

類型系統

一些類型是程序設計語言預定義的,其他的類型則是程序員構建的。程序設計語言中類型的集合,以及使用類型來規定程序行為的規則,總稱為類型系統(type system)。

類型系統的目標

與上下文無關語法相比,利用類型系統可以在更精確的層次上規定程序的行為。

  1. 確保運行時的安全性

     安全性是使用強類型語言的一個重要原因,如果語言的實現能夠保證在程序執行之前捕獲大多數類型相關的錯誤,這將簡化程序本身的設計和實現。
     如果一個語言中每個表達式都能分配一個無歧義的類型,這種語言稱為強類型語言。
     如果每個表達式都可以在編譯時確定類型,我們稱這種語言為靜態類型的(statically typed),如果某些表達式只能在運行時確定類型,稱這種語言為動態類型的(dynamically typed)。
     還有另兩種語言:無類型語言,如匯編代碼或BCPL語言;和弱類型語言,及類型系統較為貧乏的語言。
  2. 提高表達力

     具有良好結構的類型系統允許語言設計者更精確地規劃程序的行為,從而可以加入一些上下文無關語法不可能表示的特性,比如運算符重載(operator overloading)。
  3. 生成更好的代碼

     設計完善的類型系統為編譯器提供了程序中每個表達式的詳細信息,通常利用這一信息進行轉換可以生成更高校的代碼。
  4. 類型檢查

     為避免運行時類型檢查的開銷,編譯器必須分析程序,為每個名字和表達式分配一種類型。它必須檢查這些類型,以確保類型在相應上下文中的使用是合法的。
     總而言之,這些活動通常稱為類型檢查,不過這是個誤稱,它將類型推斷和識別類型相關錯誤的不同活動放在了同一個名稱下。

類型系統的組件

  1. 基礎類型

     用於表示下述數據種類中的一些或全部:數字,字符和布爾值。
     幾乎所有的語言都包含了一些功能,用於根據其基礎類型來構建更復雜的類型。
  2. 復合類型和構造類型

     基礎類型通常對硬件直接處理的數據提供了足夠的抽象,但其通常不足以表示程序所需的信息。
     為復合或聚合對象構建新類型的能力,是許多程序設計語言的一個基本特性。
  3. 類型等價性

     用於判斷兩種不同類型聲明是否等價的機制,一般認為有兩種通用的方法,
     一種是名字等價性(name equivalence, 該規則斷言兩個類型等價的充分必要條件是二者同名),
     另一種是結構等價性(structural equivalence, 該規則斷言兩個類型等價的充分必要條件是二者有相同的結構)。
  4. 用於推斷的規則

     一般來說,用於推斷類型的規則會對每個運算符規定操作數類型和結果類型之間的映射。類型推斷規則可以指出類型錯誤。
  5. 推斷表達式的類型

     推斷類型的目標是為程序中出現的每個表達式分配一個類型。這要求所有變量都有生命,所有的常量都可以推斷出類型,而所有函數的類型信息都是可以獲得的。在簡單情形下,表達式的類型推斷可以從表達式的結構直接承襲而來。
  6. 類型推斷的過程間相關問題

     表達式的類型推斷固有地依賴於形成可執行程序的其他過程。

屬性語法框架

屬性語法(attribute grammar)是用於上下文相關分析的一種形式化機制,也稱為屬性化的上下文無關語法(attributed context-free grammar)。其包含了一個上下文無關語法,外加一組規定了某些計算的規則,每個規則都通過其它屬性的值定義了一個值或屬性

綜合屬性

完全根據結點本身的屬性,其子結點的屬性和常量定義的屬性

繼承屬性

完全根據結點本身的屬性,其兄弟結點的屬性及其父結點的屬性(外加常量)定義的屬性。

求值的方法

  1. 動態方法

     這種技術使用特定的屬性化語法分析樹的結構,來確定求值次序。一種相關的方案是建立屬性依賴關系圖,對其拓撲排序,使用拓撲次序對屬性進行求值。
  2. 無關方法

     在這一類方法中,求值的次序與屬性語法和特定的屬性化語法分析樹都是無關的。這種風格的求值方法包括:從左到右重復多趟(直到所有屬性的值都確定為止),從右到左重復多趟和從左到右與從右到左交替多趟處理。
  3. 基於規則的方法

     依賴於對屬性語法的靜態分析,來構造出一個求值次序。

有環的屬性語法會導致有環的屬性依賴關系圖,若編譯器使用屬性語法,那麽它必須以適當的方式處理環。

特設語法制導轉換

在這種方案中,編譯器編寫者提供在語法分析時需要執行的代碼片段。每個片段,即操作都直接關聯到語法中的某個產生式。每次語法分析器發現自身處於語法中的特定位置時,都會調用對應的操作,以完成相應的任務。

《編譯器設計》讀書筆記——上下文相關分析