警告??:這將是一個又臭又長的系列教程,教程結(jié)束的時候,你將擁有一個除了性能差勁、擴展性差、標準庫不完善之外,其他方面都和官方相差無幾的 Lua 語言解釋器。說白了,這個系列的教程實現(xiàn)的是一個玩具語言,僅供學習,無實用性。請謹慎 Follow,請謹慎 Follow,請謹慎 Follow。
前言
編譯原理是計算機科學的一個重要且復雜的知識體系。這個系列教程也只是你入門前的墊腳石。但即使如此,也并不代表這個教程就很簡單,如果決定開始,請堅持到底。這是一個認真嚴肅的教程(咳咳),它不像網(wǎng)絡(luò)上的其他類似教程,要么實現(xiàn)一個“高級計算器”就完事了,要么語法分析還沒講完,就太監(jiān)了。也不像其他的 Lua 源碼閱讀類的指導教程,去教你怎么閱讀并理解官方實現(xiàn)的 Lua 解釋器的源碼。但我相信完成本教程后再去讀官方實現(xiàn)的源代碼,也會輕松很多。
本教程將從零開始,一磚一瓦的構(gòu)建出一個完整的解釋器。不使用任何自動化的工具,也不使用任何第三方庫,從詞法分析到虛擬機,全部親力親為。我們將要實現(xiàn)的語言起名為 SLua,意思是 Simple Lua。
前置要求
本教程并不是面向編程初學者的,你至少需要滿足以下要求才可以繼續(xù)閱讀:
本教程使用的編程語言為 Google 出品的 Go 語言。Go 語言上手非常容易,如果你有過其他任何語言的編程經(jīng)驗,請花幾個小時閱讀這篇教程:墻外多語言版、墻內(nèi)中文版。
本教程的定位不是教科書,因此不會過多的提及關(guān)于編譯原理的理論性的內(nèi)容,而更加注重實踐。所以,這要求你至少要知道編譯過程流水線的基本步驟以及每個步驟的作用,比如:詞法分析、語法分析、虛擬機等。
既然要實現(xiàn) Lua 語言的解釋器,自然要求你熟悉 Lua 語言,即使沒有用它寫過項目,至少要熟悉 Lua 語言的語法及語言特性。
面向人群
- 如果你很想知道腳本語言的解釋器的工作原理,請繼續(xù)閱讀。
- 如果你不僅想知道工作原理,還想親自實現(xiàn)一個,請繼續(xù)閱讀。
- 如果你學完學校開設(shè)的編譯原理課程,除了學會了 LEX 和 YACC,其余的還是一無所知,請繼續(xù)閱讀。
開發(fā)方式
我們不準備從一開始就著手實現(xiàn)一個完完整整的解釋器,支持所有的 Feature,這樣無疑會顧此失彼,也會極大的拉高教程的閱讀門檻。所以我們會先抽取 Lua 中一些最最基本的特性,實現(xiàn)一個可以工作的原型。在原型之上,我們再不斷添加特性,直到完成為止。
在第一個版本中,我們會將一些比較重要的 Feature 都砍掉,將目光集中在整個流程的實現(xiàn)上。
所以,第一個版本將:
- 不支持 Table
- 不支持函數(shù)和閉包
- 不支持 for 循環(huán)語句
- 不支持 repeat...until 循環(huán)語句
- 不支持多行注釋和多行字符串
閹割的差不多了,看看還剩下什么:
- 變量的聲明及賦值(全局變量和局部變量)
- do ... end 代碼塊
- if ... elseif ... else ... end 分支語句
- while 循環(huán)語句
- 單行注釋
- 單行形式的字符串
- 各種單目和雙目的運算符
編譯流程
SLua 的編譯共分為以下幾個階段:
- 詞法分析:將用戶輸入的文本形式的源代碼分解為一個 Token 列表
- 語法分析:將詞法分析的輸出作為輸入,生成無語義信息的抽象語法樹(AST)
- 語義分析:完善 AST 中的語義相關(guān)的信息
- 代碼生成:根據(jù) AST 生成字節(jié)碼
- 虛擬機:解釋并執(zhí)行字節(jié)碼
- 標準庫:提供系統(tǒng)級的實用函數(shù)
教程的章節(jié)安排也和編譯流程保持一致。
獲取源代碼
代碼已托管到 Github 上:SLua,每一個階段的代碼我都會創(chuàng)建一個 release,你可以直接下載作為參照。雖然提供了源代碼,但并不建議直接復制粘貼,因為這樣學到的知識會很容易忘記。
剛開始玩 Github 和簡書,所以沒有任何粉絲和關(guān)注量(哭),如果你覺得這篇教程有幫助,請不要吝嗇給文章點個喜歡,給 Github 上的項目點個 Star。如果能 Follow 一下簡書和 Github 的賬號就更好啦,我也會更加有動力將這個系列寫下去。:)