自製程式語言基於C語言

自製程式語言基於C語言

《自製程式語言 基於C語言》作者鄭鋼,畢業於北京大學,百度高級工程師。

本書是一本專門介紹自製程式語言的圖書,書中深入淺出地講述了如何開發一門程式語言,以及運行這門程式語言的虛擬機。本書主要內容包括:腳本語言的功能、詞法分析器、類、對象、原生方法、自上而下算符優先、語法分析、語義分析、虛擬機、內建類、垃圾回收、命令行及調試等技術。

本書適合程式設計師閱讀,也適合對程式語言原理感興趣的計算機從業人員學習。

基本介紹

  • 書名:自製程式語言 基於C語言
  • 又名:火龍書
  • 作者:鄭鋼
  • ISBN:9787115487377
  • 頁數:438
  • 定價:89
  • 出版社:人民郵電出版社
  • 出版時間:2018-09
  • 開本:16開
推薦序,目錄,

推薦序

很高興能成為本書的首 批讀者,也很高興能為本書寫推薦序。
剛拿到本書手稿時,從書名上我意識到這是對我胃口的書。果然,整書閱對以後,收穫頗多。如今程式設計師的開發成本已經很低了,項目中有各種成熟的框架和庫可供選擇和使用,但還有人能靜下心來研究編譯器這么底層的技術,實屬難得。本書猶如一把火炬,點燃了技術人內心對開發的熱情。
依稀記得2010年年初在百度與鄭剛初次見面的情景,那時他工作之餘的時間基本都用在向各個技術專家請教、討論各類技術問題上,他是我帶過的人中最勤奮的人之一。時間荏苒,一分耕耘一分收穫,看到他今天的成長,尤感欣慰。
本書講述了一門腳本語言(sparrow)的開發過程,這是一本“步步為營”式的書籍,延續了他編寫《作業系統真象還原》的風格,手把手地教讀者從零實現一門語言,從原理到實踐每一步都有實際的代碼和詳盡的原理說明,通過運行書中各小節中的代碼,讀者可以很輕鬆地掌握各個細節,因此本書的學習曲線並不陡峭,甚至很平坦。另外,值得欣喜的是,本書所編寫的腳本語言並不是用Java、C++等入門難度略大的語言實現的,而是用C語言,這是我們學習編程的基礎語言。也就是說,本書並不需要專業的開發經驗即可上手學習。另外,在實現過程中並未用到複雜的庫函式或系統調用, 可以負責地說,本書已經將學習成本降到最低。
C語言是一種面向過程的語言,如何用一種面向過程的語言去實現一種面向對象的語言很有意思。另外,PHP和Perl語言雖然也實現了類,但它們其實是一種面向過程的語言,並不是純粹的面向對象語言,而sparrow語言是一種純粹的面向對象語言,它在設計之初就採用對象的方式來處理腳本語言中類的成員和方法,這仿佛讓我們看到了面向對象程式語言的基因。眾所周知,當今最流行的腳本語言應屬Python,Python也是用C語言實現的,也許你很好奇Python的內部原理,但是想到它將近有 4 萬行的原始碼時,也許甚至不想看它的源程式了。那么研讀本書中的sparrow語言會是一種更好的選擇,其源碼不足7100行,閱讀過程輕鬆愉快,但可以學到系Python這種語言的實現原理。
對於腳本語言來說,兩個重要方面就是垃圾回收和運行環境。垃圾回收就是我們平時所說的GC(Garbage Collection)。有了GC,程式設計師不需要手工釋放所分配的對象,可以使精力專注於業務邏輯而不用擔心記憶體泄漏問題。在sparrow語言中同樣實現了GC,通過此部分代碼你可以看到GC 的原理,以及哪些對象才能被回收。 運行時環境就是腳本語言中的虛擬機,即VM(如Java語言的JVM也是一種VM)。腳本語言是通過虛擬機才能運行的,如何把編譯器生成的操作碼轉換為實際的代碼行為,這裡面的工作對大多數人來說很神秘。相信各位在源碼中一探究竟之後會發現:GC和VM這兩個神秘的黑盒子不過如此。另外,也許程式設計師最感興趣的就是執行緒,關於執行緒在用戶態下是如何實現的、執行緒如何實現調度,本書將告訴你答案。總之,但凡涉獵,開卷有益。
每個程式設計師都有實現屬於自己程式語言的夢想,說其是夢想,原因是實現的難度很大......這種情況一直持續到本書的出現。本書講的是純粹的技術“乾貨”,符合鄭剛一貫的寫作風格,這是他靜心寫出來的東西,內容滿滿,很值得閱讀。
於曉聲
滴滴系統部技術高級總監

目錄

第0章 一些可能令人迷惑的問題 1
0.0 成功的基石不是堅持,而是“不放棄” 1
0.1 你懂程式語言的“心”嗎 2
0.2 程式語言的來歷 2
0.3 語言一定要用更底層的語言來編寫嗎 2
0.4 編譯型程式和腳本程式的異同 8
0.5 腳本語言的分類 10
0.6 為什麼CPU要用數字而不是字元串作為指令 11
0.7 為什麼腳本語言比編譯型語言慢 11
0.8 既然腳本語言比較慢,為什麼大家還要用 12
0.9 什麼是中間代碼 12
0.10 什麼是編譯器的前端、後端 13
0.11 詞法分析、語法分析、語義分析和生成代碼並不是串列執行 13
0.12 什麼是符號表 14
0.13 什麼是關係中的閉包 14
0.14 什麼是程式中的閉包 15
0.15 什麼是字母表 16
0.16 什麼是語言 17
0.17 正規式就是正則表達式 17
0.18 什麼是正規(表達)式和正規集 17
0.19 什麼是有窮自動機 18
0.20 有窮自動機與詞法分析的關係 19
0.21 詞法分析用有窮自動機(有窮狀態自動機)的弊端 19
0.22 什麼是文法 20
0.23 BNF和EBNF,非終結符和終結符,開始符號及產生式 21
0.24 什麼是句型、句子、短語 23
0.25 什麼是語法分析 24
0.26 語法分析中的推導和歸約為什麼都要最“左” 25
0.27 什麼是語義分析 26
0.28 什麼是語法制導 27
0.29 詞法分析器吃的是lex,擠出來的是token 27
0.30 什麼是“遍” 28
0.31 文法為什麼可以變換 28
0.32 為什麼消除左遞歸和提取左因子 28
0.33 FIRST集、FOLLOW集、LL(1)文法 29
0.34 最右推導、最左歸約、句柄 31
0.35 算符優先分析法 32
0.36 算符優先文法 33
0.37 非終結符中常常定義的因子和項是什麼 33
0.38 什麼是抽象語法樹 33
0.39 編譯器如何使用或實現文法中的產生式 34
0.40 程式計數器pc與ip的區別 35
第 1章 設計一種面向對象腳本語言 36
1.1 腳本語言的功能 36
1.2 關鍵字 37
1.3 腳本的執行方式 38
1.4 “純手工”的開發環境 38
1.5 定義sparrow語言的文法 38
第2章 實現詞法分析器 46
2.1 柔性數組 46
2.2 什麼是位元組序 47
2.3 一些基礎的數據結構(本節源碼stepByStep/c2/a) 48
2.4 定義虛擬機結構(本節源碼stepByStep/c2/b) 56
2.5 實現源碼讀取(本節源碼stepByStep/c2/c) 57
2.6 unicode與UTF-8 59
2.6.1 什麼是unicode 59
2.6.2 什麼是UTF-8 59
2.6.3 UTF-8編碼規則 60
2.6.4 實現UTF-8編碼、解碼(本節源碼stepByStep/c2/d) 61
2.7 實現詞法分析器parser(本節源碼stepByStep/c2/e) 66
2.7.1 lex和token 66
2.7.2 字元串和字元串內嵌表達式 66
2.7.3 單詞識別流程 67
2.7.4 定義token和parser 68
2.7.5 解析關鍵字及獲取字元 71
2.7.6 解析標識符和unicode碼點 73
2.7.7 解析字元串、內嵌表達式、轉義字元 75
2.7.8 跳過注釋和空行 77
2.7.9 獲取token 79
2.7.10 token匹配和初始化parser 84
2.8 構建主程式(本節源碼stepByStep/c2/f) 85
2.9 編譯、測試(本節源碼stepByStep/c2/f) 88
2.9.1 一個簡單的makefile 88
2.9.2 測試paser 92
第3章 類與對象 95
3.1 對象在C語言中的概貌 95
3.2 實現對象頭(本節源碼stepByStep/c3/a) 96
3.3 實現class定義(本節源碼stepByStep/c3/a) 99
3.4 實現字元串對象(本節源碼stepByStep/c3/a) 101
3.5 模組對象和實例對象(本節源碼stepByStep/c3/a) 103
3.6 upvalue、openUpvalue和closedUpvalue 106
3.7 實現函式對象、閉包對象與調用框架(本節源碼stepByStep/c3/a) 107
3.8 完善詞法分析器之數字解析(本節源碼stepByStep/c3/b) 111
3.9 完善詞法分析器之字元串解析和獲取token(本節源碼stepByStep/c3/b) 114
3.10 最終版詞法分析器的功能驗證(本節源碼stepByStep/c3/b) 116
3.11 實現list列表對象(本節源碼stepByStep/c3/c) 118
3.12 range對象(本節源碼stepByStep/c3/c) 121
3.13 遲到的class.c(本節源碼stepByStep/c3/c) 122
3.14 map對象(本節源碼stepByStep/c3/c) 124
3.14.1 哈希表 124
3.14.2 map對象頭檔案及entry 125
3.14.3 衝突探測鏈與偽刪除 126
3.14.4 map對象的實現 128
3.15 執行緒對象(本節源碼stepByStep/c3/c) 134
3.15.1 執行緒、協程淺述 134
3.15.2 運行時棧 137
3.15.3 用戶執行緒的實現 138
第4章 原生方法及基礎實現 142
4.1 解釋器流程(本節源碼stepBystep/c4/a) 142
4.2 符號表 144
4.2.1 模組的符號表 144
4.2.2 類方法的符號表 144
4.2.3 模組變數符號表 146
4.2.4 局部變數符號表 147
4.2.5 常量符號表 147
4.3 方法在運行時棧中的參數 147
4.4 定義模組變數(本節源碼stepByStep/c4/b) 148
4.5 原生方法(本節源碼stepByStep/c4/b) 154
4.5.1 定義裸類 154
4.5.2 定義返回值與方法綁定的宏 155
4.5.3 定義原生方法 157
4.5.4 符號表操作 159
4.5.5 定義類、綁定方法、綁定基類 160
4.6 元類及實現(本節源碼stepByStep/c4/b) 161
4.6.1 meta-class類、class類、object類 161
4.6.2 創建元類,綁定類方法 163
4.7 載入模組(本節源碼stepByStep/c4/c) 164
4.8 虛擬機簡介 166
4.8.1 虛擬機分類及優缺點 166
4.8.2 為什麼要採用虛擬機 168
4.8.3 虛擬機的簡單最佳化 170
4.9 位元組碼 171
第5章 自上而下算符優先——TDOP 177
5.1 自上而下算符優先—TDOP 177
5.2 來自Douglas Crockford的教程 177
5.3 TDOP原理 194
5.3.1 一些概念 194
5.3.2 一個小例子 196
5.3.3 expression的思想 197
5.3.4 while(rbp < token.lbp)的意義 200
5.3.5 進入expression時當前token的類別 201
5.3.6 TDOP總結 202
第6章 實現語法分析與語義分析 204
6.1 定義指令(本節源碼stepByStep/c6/a) 204
6.2 核心腳本(本節源碼stepByStep/c6/a) 206
6.3 寫入指令(本節源碼stepByStep/c6/a) 212
6.4 編譯模組(本節源碼stepByStep/c6/a) 216
6.5 語義分析的本質 218
6.6 註冊編譯函式(本節源碼stepByStep/c6/b) 218
6.7 賦值運算的條件 221
6.8 實現expression及其周邊(本節源碼stepByStep/c6/c) 223
6.9 局部變數作用域管理 228
6.10 變數聲明、中綴、前綴及混合運算符方法簽名(本節源碼stepByStep/c6/d) 229
6.11 解析標識符(本節源碼stepByStep/c6/e) 233
6.11.1 處理參數列表及相關 233
6.11.2 實現運算符和標識符的簽名函式 235
6.11.3 upvalue的查找與添加 239
6.11.4 變數的載入與存儲 242
6.11.5 編譯代碼塊及結束編譯單元 243
6.11.6 各種方法調用 246
6.11.7 標識符的編譯 249
6.12 編譯內嵌表達式(本節源碼stepByStep/c6/f) 256
6.13 編譯bool及null(本節源碼stepByStep/c6/g) 258
6.14 this、繼承、基類(本節源碼stepByStep/c6/h) 259
6.15 編譯小括弧、中括弧及list列表字面量(本節源碼stepByStep/c6/i) 260
6.16 編譯方法調用和map字面量(本節源碼stepByStep/c6/j) 263
6.17 編譯數學運算符(本節源碼stepByStep/c6/k) 266
6.18 編譯變數定義(本節源碼stepByStep/c6/l) 270
6.19 編譯語句 274
6.19.1 編譯if語句(本節源碼stepByStep/c6/m) 274
6.19.2 編譯while語句(本節源碼stepByStep/c6/n) 275
6.19.3 編譯return、break和continue語句(本節源碼stepByStep/c6/o) 280
6.19.4 編譯for循環語句(本節源碼stepByStep/c6/p) 284
6.19.5 編譯代碼塊及單一語句(本節源碼stepByStep/c6/q) 288
6.20 編譯類定義(本節源碼stepByStep/c6/r) 289
6.20.1 方法的聲明與定義 289
6.20.2 構造函式與創建對象 291
6.20.3 編譯方法 293
6.20.4 編譯類定義 296
6.21 編譯函式定義(本節源碼stepByStep/c6/s) 298
6.22 編譯模組導入(本節源碼stepByStep/c6/t) 300
第7章 虛擬機 306
7.1 創建類與堆疊框架(本節源碼stepByStep/c7/a) 306
7.2 upvalue的創建與關閉(本節源碼stepByStep/c7/b) 309
7.3 修正運算元(本節源碼stepByStep/c7/c) 312
7.4 執行指令(本節源碼stepByStep/c7/d) 314
7.4.1 一些基礎工作 314
7.4.2 解碼、解碼、執行(本節源碼stepByStep/c7/d) 316
7.5 運行虛擬機(本節源碼stepByStep/c7/e) 334
第8章 內建類及其方法 337
8.1 Bool類及其方法(本節源碼stepByStep/c8/a) 337
8.2 執行緒類及其方法(本節源碼stepByStep/c8/b) 338
8.3 函式類及其方法和函式調用重載(本節源碼stepByStep/c8/c) 345
8.4 Null類及其方法(本節源碼stepByStep/c8/d) 347
8.5 Num類及其方法(本節源碼stepByStep/c8/e) 348
8.6 String類及其方法(本節源碼stepByStep/c8/f) 355
8.7 List類及其方法(本節源碼stepByStep/c8/g) 369
8.8 Map類及其方法(本節源碼stepByStep/c8/h) 374
8.9 range類及其方法(本節源碼stepByStep/c8/i) 380
8.10 System類及其方法(本節源碼stepByStep/c8/j) 383
8.11 收尾與測試(本節源碼stepByStep/c8/k) 388
第9章 垃圾回收 393
9.1 垃圾回收淺述 393
9.2 理論基礎 395
9.3 標記—清掃回收算法 396
9.4 一些基礎結構(本節源碼stepByStep/c9/a) 397
9.5 實現GC(本節源碼stepByStep/c9/a) 400
9.6 添加臨時根對象與觸發GC 411
第 10章 命令行及調試 415
10.1 釋放虛擬機(本節源碼stepByStep/c10/a) 415
10.2 簡單的命令行界面(本節源碼stepByStep/c10/a) 415
10.3 調試(本節源碼stepByStep/c10/b) 417

相關詞條

熱門詞條

聯絡我們