內容簡介
本書提供了詳盡清晰的算法,主推在實踐中學習編譯器構造的相關技術,同時提供了配合教材使用的教學網站、參考資料以及源碼下載。不僅可以作為計算機專業本科生或研究生的參考教材,同時也適合相關領域的軟體工程師、系統分析師等作為參考資料。
圖書目錄
第1章 概述 1
1.1 編譯的歷史 1
1.2 編譯器可以做什麼 3
1.2.1 編譯器生成的機器代碼 3
1.2.2 目標代碼格式 5
1.3 解釋器 6
1.4 語法和語義 7
1.4.1 靜態語義 8
1.4.2 運行時語義 8
1.5 編譯器的組織結構 10
1.5.1 掃描器 11
1.5.2 分析器 12
1.5.3 類型檢查器(語義分析) 12
1.5.4 翻譯器(程式綜合) 12
1.5.5 符號表 13
1.5.6 最佳化器 13
1.5.7 代碼生成器 13
1.5.8 編譯器開發工具 14
1.6 程式設計語言和編譯器設計 14
1.7 計算機體系結構和編譯器設計 15
1.8 編譯器設計的考慮事項 16
1.8.1 調試(開發)編譯器 16
1.8.2 最佳化編譯器 17
1.8.3 可重定向編譯器 17
1.9 集成開發環境 18
練習 18
第2章 一個簡單的編譯器 21
2.1 ac語言的非形式化定義 21
2.2 ac語言的形式化定義 22
2.2.1 語法規範 22
2.2.2 詞法單元規範 24
2.3 一個簡單編譯器中的階段 25
2.4 掃描 25
2.5 分析 27
2.5.1 分析過程的預測 27
2.5.2 產生式的實現 28
2.6 抽象語法樹 29
2.7 語義分析 31
2.7.1 符號表 31
2.7.2 類型檢查 32
2.8 代碼生成 34
練習 36
第3章 掃描--理論和實踐 38
3.1 掃描器概述 38
3.2 正則表達式 40
3.3 示例 42
3.4 有限自動機和掃描器 43
3.4.1 確定性的有限自動機 44
3.5 掃描器生成工具Lex 46
3.5.1 定義Lex中的詞法單元 47
3.5.2 字元類 48
3.5.3 使用正則表達式來定義詞法單元 49
3.5.4 使用Lex進行字元處理 51
3.6 其他掃描器生成工具 53
3.7 構造掃描器的實際注意事項 53
3.7.1 處理標識符和字面常量 54
3.7.2 使用編譯命令和列出源碼行 57
3.7.3 掃描器的終止 58
3.7.4 向前看多個字元 58
3.7.5 性能上的考慮 60
3.7.6 詞法錯誤恢復 61
3.8 正則表達式和有限自動機 63
3.8.1 把正則表達式轉換為NFA 64
3.8.2 創建DFA 64
3.8.3 有限狀態機的化簡 66
3.8.4 把有限自動機轉換為正則表達式 68
3.9 本章小結 71
練習 72
第4章 文法和分析 77
4.1 上下文無關文法 77
4.1.1 最左推導 79
4.1.2 最右推導 79
4.1.3 分析樹 80
4.1.4 其他類型的文法 81
4.2 上下文無關文法的屬性 81
4.2.1 簡化的文法 82
4.2.2 二義性 82
4.2.3 語言定義中的錯誤 83
4.3 擴展文法的轉換 83
4.4 分析器和識別器 84
4.5 文法分析的算法 86
4.5.1 文法表示 87
4.5.2 推導空字元串 88
4.5.3 First集合 89
4.5.4 Follow集合 92
練習 94
第5章 自頂向下分析 98
5.1 概述 98
5.2 LL(k)文法 99
5.3 遞歸下降的LL(1)分析器 102
5.4 表格驅動的LL(1)分析器 103
5.5 如何獲得LL(1)文法 105
5.5.1 公共前綴 106
5.5.2 左遞歸 106
5.6 非LL(1)的語言 107
5.7 LL(1)分析器的屬性 109
5.8 分析表的表示方法 110
5.8.1 精簡方法 111
5.8.2 壓縮方法 112
5.9 語法錯誤的恢復和修復 114
5.9.1 錯誤恢復 114
5.9.2 錯誤修復 115
5.9.3 LL(1)分析器中的錯誤檢查 115
5.9.4 LL(1)分析器中的錯誤恢復 116
練習 117
第6章 自底向上分析 121
6.1 概述 121
6.2 移進-規約分析器 122
6.2.1 LR分析器和最右推導 123
6.2.2 把LR分析看做是編織過程(knitting) 123
6.2.3 LR分析引擎 125
6.2.4 LR分析表 125
6.2.5 LR(k)分析 128
6.3 LR(0)分析表的構造 129
6.4 衝突診斷 133
6.4.1 二義性文法 135
6.4.2 非LR(k)的文法 137
6.5 衝突解決方法和分析表的構造 138
6.5.1 SLR(k)分析表的構造 138
6.5.2 LALR(k)分析表的構造 141
6.5.3 LALR傳播圖 143
6.5.4 LR(k)分析表的構造 147
本章小結 151
練習 151
第7章 語法制導翻譯 158
7.1 概述 158
7.1.1 語義動作和語義值 158
7.1.2 綜合和繼承屬性 159
7.2 自底向上的語法制導翻譯 160
7.2.1 示例 161
7.2.2 規則克隆 163
7.2.3 強加語義動作 164
7.2.4 進一步的文法重組 164
7.3 自頂向下的語法制導翻譯 166
7.4 抽象語法樹 168
7.4.1 具體和抽象語法樹 168
7.4.2 高效的抽象語法樹數據結構 168
7.4.3 創建抽象語法樹的基礎結構 169
7.5 抽象語法樹的設計和構造 171
7.5.1 設計 171
7.5.2 構造 173
7.6 左值和右值的抽象語法樹結構 175
7.7 抽象語法樹的設計模式 177
7.7.1 結點的類層次結構 177
7.7.2 訪問者模式 178
7.7.3 反射的訪問者模式 179
本章小結 182
練習 182
第8章 符號表和聲明處理 186
8.1 構造符號表 186
8.1.1 靜態作用域 187
8.1.2 符號表的接口 188
8.2 塊結構的語言和作用域 189
8.2.1 處理作用域 189
8.2.2 使用一個還是多個符號表 190
8.3 基本的實現技術 191
8.3.1 添加和查找名稱 191
8.3.2 名字空間 193
8.3.3 一種高效的符號表實現方法 194
8.4 高級特性 196
8.4.1 記錄和類型名 196
8.4.2 重載和類型層次結構 197
8.4.3 隱式聲明 198
8.4.4 導出和導入命令 198
8.4.5 查找規則的修改 199
8.5 聲明處理的基礎 199
8.5.1 符號表中的屬性 199
8.5.2 類型描述符的結構 200
8.5.3 使用抽象語法樹進行類型檢查 201
8.6 變數和類型聲明 203
8.6.1 簡單變數聲明 203
8.6.2 類型名稱的處理 204
8.6.3 類型聲明 204
8.6.4 複雜的變數聲明 207
8.6.5 靜態數組類型 208
8.6.6 結構和記錄類型 209
8.6.7 枚舉類型 210
8.7 類和方法的聲明 212
8.7.1 類聲明的處理 213
8.7.2 方法聲明的處理 215
8.8 類型檢查簡介 217
8.8.1 簡單標識符和字面常量 219
8.8.2 賦值語句 220
8.8.3 表達式檢查 220
8.8.4 複雜名稱的檢查 221
本章小結 224
練習 225
第9章 語義分析 229
9.1 控制結構的語義分析 229
9.1.1 可達和終止分析 231
9.1.2 if語句 232
9.1.3 While、Do和Repeat循環 234
9.1.4 for循環 236
9.1.5 break、continue、return和goto語句 238
9.1.6 switch和case語句 243
9.1.7 異常處理 246
9.2 方法調用的語義分析 251
9.3 本章小結 256
練習 256
第10章 中間表示形式 261
10.1 概述 261
10.1.1 示例 262
10.1.2 中端 263
10.2 Java虛擬機 265
10.2.1 概述和設計原則 265
10.2.2 類檔案的內容 266
10.2.3 JVM指令 267
10.3 靜態單賦值形式 275
10.3.1 重命名和φ-函式 276
練習 277
第11章 面向虛擬機的代碼生成 279
11.1 代碼生成的Visitor 279
11.2 類和方法聲明 280
11.2.1 類聲明 282
11.2.2 方法聲明 283
11.3 MethodBodyVisitor 284
11.3.1 常量 284
11.3.2 局部存儲的引用 284
11.3.3 靜態引用 285
11.3.4 表達式 285
11.3.5 賦值 286
11.3.6 方法調用 287
11.3.7 域引用 289
11.3.8 數組引用 290
11.3.9 條件執行 290
11.3.10 循環 291
11.4 LHSVisitor 292
11.4.1 局部引用 293
11.4.2 靜態引用 293
11.4.3 域引用 293
11.4.4 數組引用 294
練習 295
第12章 運行時支持 298
12.1 靜態分配 298
12.2 棧分配 299
12.2.1 類和struct中的域訪問 300
12.2.2 在運行時訪問活動記錄 301
12.2.3 處理類和對象 302
12.2.4 處理多個作用域 303
12.2.5 程式塊級的分配 305
12.2.6 關於活動記錄的其他內容 306
12.3 數組 309
12.3.1 靜態的一維數組 309
12.3.2 多維數組 313
12.4 堆管理 315
12.4.1 分配機制 315
12.4.2 釋放機制 317
12.4.3 自動垃圾回收 318
12.5 基於區域的記憶體管理 323
練習 324
第13章 目標代碼生成 330
13.1 位元組碼的翻譯 331
13.1.1 記憶體地址的分配 332
13.1.2 數組和對象的分配 333
13.1.3 方法調用 335
13.1.4 位元組碼翻譯的例子 337
13.2 表達式樹的翻譯 338
13.3 暫存器分配 342
13.3.1 On-the-Fly暫存器分配 342
13.3.2 使用圖著色法的暫存器分配 344
13.3.3 基於優先權的暫存器分配 349
13.3.4 過程間暫存器分配 350
13.4 代碼調度 351
13.4.1 代碼調度的改進 354
13.4.2 全局和動態的代碼調度 355
13.5 自動的指令選擇 356
13.5.1 使用BURS進行指令選擇 358
13.5.2 使用Twig進行指令選擇 359
13.5.3 其他方法 360
13.6 窺孔最佳化 361
13.6.1 窺孔最佳化的層次 361
13.6.2 窺孔最佳化的自動生成 364
練習 364
第14章 程式最佳化 370
14.1 概述 370
14.1.1 為什麼要進行最佳化 371
14.2 控制流分析 375
14.2.1 控制流圖 376
14.2.2 程式和控制流結構 378
14.2.3 直接過程調用圖 378
14.2.4 深度優先生成樹 379
14.2.5 支配關係 382
14.2.6 簡單的支配算法 383
14.2.7 快速的支配算法 385
14.2.8 支配邊界 393
14.2.9 區間 395
14.3 數據流分析簡介 403
14.3.1 可用表達式 404
14.3.2 活躍變數 406
14.4 數據流框架 407
14.4.1 數據流求值圖 408
14.4.2 交格 409
14.4.3 轉換函式 411
14.5 求值 412
14.5.1 疊代 412
14.5.2 初始化 414
14.5.3 終止問題和快速框架 415
14.5.4 分配式框架 418
14.6 常量傳播 419
14.7 SSA形式 422
14.7.1 添加? -函式 424
14.7.2 重命名 424
練習 427
參考文獻 436
縮略語 443