- 自己動手構建編程語言:如何設計編譯器、解釋器和DSL
- (美)克林頓·L.杰弗瑞
- 2765字
- 2024-05-11 19:44:54
Preface前言
雖然高級語言的開發已經有60年之久,但編程仍然非常困難。隨著硬件不斷進步,軟件規模不斷增長,軟件復雜性也越來越高,而編程語言的進步則要慢得多。為特定用途創建新的編程語言是解決這種軟件危機的一劑良藥。
本書主要研究如何構建一種新的編程語言。書中將介紹編程語言設計方面的主題,并重點介紹編程語言實現。本書的新穎之處在于將傳統的編譯器-編譯器工具(Flex和BYACC)與兩種更高級的實現語言融合。一種非常高級的語言(Unicon)可以像黃油一樣穿透編譯器的數據結構和算法,而另一種主流的現代語言(Java)則展示了如何在更典型的生產環境中實現相同的代碼。
有一個問題直到我上完大學編譯器課程都沒有真正理解:編譯器只是編程語言實現的一部分。更高級的語言,包括大多數較新的語言,都有一個運行時系統令其編譯器相形見絀。為此,本書的后半部分花了大量篇幅介紹語言運行時系統的各個方面,從字節碼解釋器到垃圾收集。
本書讀者對象
本書面向對發明編程語言或開發領域特定語言(Domain-Specific Languages, DSL)感興趣的軟件開發人員。學習編譯器構建課程的計算機科學系學生也會發現這本書非常適合作為語言實現的實用指南,可以為理論教材提供有益補充。為了更好地學習本書知識,讀者需要具有中等高級語言(如Java或C++)知識水平和使用經驗。
本書主要內容
第1章討論何時構建編程語言,以及何時設計函數庫或類庫。本書的讀者大都想構建自己的編程語言,或者想設計一個庫。
第2章介紹如何精確定義編程語言,這在試圖構建編程語言之前了解是非常重要的。這包括語言的詞法和語法特征以及語義的設計,好的語言設計通常盡可能多地使用熟悉語法。
第3章介紹詞法分析,包括正則表達式表示法及UFlex和JFlex這兩個工具。最后,我們將打開源代碼文件,逐個字符地讀取源代碼,并將其內容作為標記(token)流報告。標記流由源文件中的單個單詞、運算符和標點符號組成。
第4章介紹語法分析,包括上下文無關文法及iyacc和BYACC/J這兩個工具。我們將學習如何對文法中阻撓解析的問題進行調試,并在出現語法錯誤時報告錯誤。
第5章介紹語法樹。解析過程的主要副產品是構造表示源代碼邏輯結構的樹數據結構,樹節點的構造發生在對每個文法規則執行的語義動作中。
第6章展示如何構造符號表,將符號插入其中,并使用符號表來識別兩種語義錯誤:未聲明的變量和非法重新聲明的變量。為了理解可執行代碼中的變量引用,必須跟蹤每個變量的范圍和生存期。這是通過輔助語法樹的表數據結構實現的。
第7章對類型檢查進行介紹,這是大多數編程語言所面臨的主要任務。類型檢查可以在編譯時或運行時執行。本章將介紹對基本類型(也稱為原子或標量類型)進行靜態編譯時類型檢查的常見情況。
第8章介紹如何對Java Jzero子集中的方法調用的數組、參數和返回類型執行類型檢查。當涉及多個或復合類型時,類型檢查更困難。當必須檢查具有多個參數類型的函數,或者必須檢查數組、哈希表、類實例或其他復合類型時,就是這種情況。
第9章通過剖析由Jzero語言編寫的示例,介紹如何生成中間代碼。在生成要執行的代碼之前,大多數編譯器將語法樹轉換為與機器無關的中間代碼指令列表。此時將處理控制流的關鍵方面,例如標簽和goto指令的生成。
第10章介紹將語法分析的信息合并到IDE中,以便解決提供語法著色和有關語法錯誤的視覺反饋時所遇到的一些挑戰。編程語言不僅需要編譯器或解釋器,還需要開發人員的工具生態系統。這個生態系統包括調試器、聯機幫助或集成開發環境。本章是一個來自Unicon IDE的Unicon示例。
第11章介紹設計指令集和執行字節碼的解釋器。一種新的領域特定語言可能包括主流CPU不直接支持的高級域編程特性。為許多語言生成代碼的最實用方法是為抽象機器生成字節碼,其指令集直接支持域,然后通過解釋該指令集來執行程序。
第12章繼續介紹代碼生成,從第9章中提取中間代碼,并從中生成字節碼。從中間代碼到字節碼的轉換需要遍歷一個巨大的鏈表,將每個中間代碼指令轉換為一個或多個字節碼指令。通常,這是一個遍歷鏈表的循環,每個中間代碼指令都有不同的代碼塊。
第13章介紹如何為x64生成本機代碼。一些編程語言需要本機代碼來實現其性能要求。本機代碼生成類似于字節碼生成,但更復雜,涉及寄存器分配和內存尋址模式。
第14章介紹如何通過添加內置在語言中的運算符和函數來支持領域特定語言的高級特性。領域特定語言的高級特性通常最好由內置在語言中的運算符和函數來表示,而不是庫函數。添加內置函數可能會簡化編程語言,提高其性能,或者在語言語義中產生副作用,否則這些副作用是很難或不可能產生的。本章中的示例來自Unicon,因為它是比Java更高級的語言,并且在其內置函數中實現了更復雜的語義。
第15章介紹何時需要新的控制結構,并提供使用字符串掃描處理文本和渲染圖形區域的控制結構示例。前幾章中的通用代碼涵蓋了基本的條件和循環控制結構,但領域特定語言通常具有獨特或自定義的語義,它們為此引入了新的控制結構。添加新的控制結構比添加新的函數或運算符要困難得多,但這使得領域特定語言值得開發,而不僅僅是編寫類庫。
第16章介紹兩種方法,我們可以使用這些方法在編程語言中實現垃圾收集。內存管理是現代編程語言最重要的內容之一,所有很酷的編程語言都具有通過垃圾收集進行自動內存管理的特性。本章提供兩種方法來在編程語言中實現垃圾收集,包括引用計數以及標記-清理垃圾收集。
第17章對書中介紹的主要內容進行回顧,并啟發我們深思。本章主要介紹可以從這本書中學到的東西,并給出延伸閱讀建議。
附錄A介紹的Unicon編程語言知識是以幫助你理解書中使用的Unicon示例。大多數示例都同時給出了Unicon和Java版本,但Unicon版本通常更短,更容易閱讀。
附錄B提供部分章節知識要點。
如何充分利用這本書
為了學習、理解本書的內容,讀者應該是Java或類似語言的中級或高級程序員,理解面向對象語言的C語言程序員也行。

本書中關于安裝和使用這些工具的說明稍微有些分散,以減少大家學習起步階段的工作量,這些工具的安裝和使用說明在第3章和第5章介紹。如果你在技術上很有天賦,那么你可以在macOS上運行所有這些工具,但在本書的寫作過程中我并沒有使用或測試過。
下載示例代碼文件
你可以從GitHub下載本書的示例代碼文件,網址為https://github.com/Packt-Publishing/Build-Your-Own-Programming-Language。代碼更新將在GitHub存儲庫中進行。
彩色圖像下載
我們還提供了一個PDF文件,其中包含本書中使用的屏幕截圖和彩色圖表,你可以從https://static.packt-cdn.com/downloads/9781800204805_ColorImages.pdf下載。
排版約定
本書中使用了如下排版約定。
文本中的代碼:表示文本中的代碼文字、數據庫表名、文件夾名、文件名、文件擴展名、路徑名、虛擬URL、用戶輸入和Twitter句柄。例如:“必須將相應的Java main()放在類中。”
代碼塊設置如下:

當我們希望提醒讀者注意代碼塊的特定部分時,會將相關行或對象設置成粗體,例如:

命令行輸入或輸出都寫成如下形式:

粗體:表示我們在屏幕上看到的新術語、重要單詞或短語。例如,菜單或對話框中的單詞以粗體顯示。例如:“選擇管理面板中的系統信息。”
提示或重要說明
提示或重要說明以文本框顯示。
- Java EE 6 企業級應用開發教程
- 高效微控制器C語言編程
- Offer來了:Java面試核心知識點精講(原理篇)
- Access 2010數據庫基礎與應用項目式教程(第3版)
- Visual C++串口通信技術詳解(第2版)
- Kotlin Standard Library Cookbook
- Responsive Web Design by Example
- Linux Device Drivers Development
- Learning SciPy for Numerical and Scientific Computing(Second Edition)
- .NET 3.5編程
- 劍指Java:核心原理與應用實踐
- 零代碼實戰:企業級應用搭建與案例詳解
- C++從入門到精通(第6版)
- Android移動應用項目化教程
- DB2SQL性能調優秘笈