《兩周自制腳本語言》讀后感 @阿貍不歌

? ? ? 乘著春節(jié)假期閑來無事娃殖,準備挑戰(zhàn)一下有點難度的事情,試著寫一門腳本語言吏饿。沒有任何依據(jù),要想憑空造一門腳本語言蔬浙,那是幾乎不可能的事情猪落,所以首先要解決的是參考資料的問題——龍??(Compilers: Principles,Techniques,and Tools)、虎??(Modern Compiler Implementation in C)畴博、鯨??(Advanced Compiler Design and Implementation)三書是編譯原理的三大經(jīng)典笨忌,可是看看這幾本書的個頭以及有限的假期,看來只能等以后再來啃他們了俱病。到亞馬遜和京東上搜索“自制語言”官疲,出來的結(jié)果全是圖靈出的:《兩周自制腳本語言》、《自制編程語言》亮隙、《自制編譯器》途凫,而且與設計腳本語言有關的中文書似乎只此一本——《兩周自制腳本語言

英文書里倒是也有一本2016年新出的關于自制腳本語言的書《Writing An Interpreter In Go》,粗看了一下覺得不錯溢吻,也列為參考資料维费。


選好參考資料,以兩周做為時間參考坐標煤裙,我的自制腳本之旅就開始啟動了:

第一天:來掩完,我們一起做些什么吧?

? ? ? 翻開之后,發(fā)現(xiàn)第一天的內(nèi)容好像少的讓我有些吃驚硼砰,只有9頁且蓬,真的要花一天才能讀完嗎??? 當然內(nèi)容雖少卻是提綱挈領的一章,里面介紹了要設計一門腳本語言必備的基礎概念:什么是機器語言题翰、什么是匯編語言恶阴、解釋器和編譯器有什么區(qū)別等等……最重要的是介紹了我們要設計一門編程語言必不可少的結(jié)構(gòu)—— 如下圖所示:

首先是源代碼,程序員每天都要打交道的東西豹障。既然是“自制”冯事,那么現(xiàn)在這個語言要靠自己設計了,這是語言設計師的天地血公,語法(風格)任由我來設定昵仅,比如:

? ? ? ? ? ? ? ? ? ? ? 令 年齡 = 1;

? ? ? ? ? ? ? ? ? ? ? 令 名字 = "我的姓名";

? ? ? ? ? ? ? ? ? ? ? 令 運算結(jié)果 = 10 乘以 (20除以2);

/*上面這三行看上去雖然和程序員們?nèi)粘4蚪坏赖母鞣N語言不那么一樣,但是應該還是能看懂的吧??*/

第二步,是詞法分析(Lexing)摔笤,我們需要實現(xiàn)一個詞法分析器(被稱為lexical analyzer 或 lexer ?也有叫scanner的)够滑,把上面這些語句進一步拆分成特定的“符號”,比如把“令 年齡 = 1;” 拆分為“令”吕世、“年齡”彰触、“=”、“1”命辖、“;”况毅,這個拆分的結(jié)果被稱為Token。

第三步尔艇,是語法分析(Parsing)尔许,我們需要實現(xiàn)一個語法分析器(即Parser),語法分析器的作用就是把前面一步詞法分析(Lexing)獲取的Token進一步的解析并生成抽象語法樹(abstract syntax tree或者縮寫為AST)漓帚,這是每個編程語言(不論是解釋型的還是編譯型的)都少不了的部分母债。

第四步,則是腳本語言與編譯型語言的分野處尝抖,通過Parser拿到抽象語法樹(AST)后,如果你要通過編譯器(Compiler)生成機器碼后再運行迅皇,那么你搞的就是編譯型語言昧辽,如果你是要通過解釋器(Interpreter)直接執(zhí)行,那么你搞的就是腳本語言登颓。如果我既搞了編譯器搅荞,又搞了解釋器,那算什么呢 —— 其實這真的沒有問題框咙,只要你手上已經(jīng)有了抽象語法樹(AST)咕痛,那你可以同時把兩者都給實現(xiàn)了??。

第一章雖然只有短短9頁喇嘱,但是把整本書的內(nèi)容做了高度的概括茉贡,并且在第7-9頁列出了按天(章)劃分的學習計劃,劇透一下者铜,其實本書要完整看完并不是14天腔丧,最后還有5章(天)是用于自學的,按照作者建議的閱讀順序是:先讀完第 2~8 章作烟,之后是第 15愉粤、16 章,若還有時間拿撩,再讀第 11 章和第 13 章衣厘。


第一步:設計語言風格

既然是自制腳本語言,那么我并不打算完整的跟著本書作者后面亦步亦趨压恒,而是從一開始就確立了本次實戰(zhàn)的語言風格:中文型——除了通用操作符(+影暴、-怖亭、*、/坤检、=兴猩、;等)之外,關鍵字都用中文??:

變量賦值在上面已經(jīng)舉例了早歇,下面就舉一些例子:


流程控制語句:

若(年齡>18){

? ? ?打印("年齡已經(jīng)符合要求");

}否則{

? ? 打印("歲數(shù)還小");

}


循環(huán)語句1:

令 總數(shù) = 0;

當(總數(shù)<1000){

? ? ? ?打印(總數(shù));

? ? ? ?總數(shù)++;

}


循環(huán)語句2:

令 數(shù)組 = [1,2,3,4,5];

在 數(shù)組 遍歷 i,v {

? ? ? 打印("第" + i + "個數(shù)組元素是:" + v); ??

}


第二步:設計詞法分析器(Lexing)

? ? ? 在確定了語言風格之后倾芝,其實詞法分析器就不是很困難了,說起來就是把每一行里哪些是關鍵字(比如“令”箭跳、“遍歷”晨另、“在”、“當”谱姓、“若”借尿、“否則”)、哪些是變量(如“i”屉来、“v”路翻、“年齡”等)、哪些是操作符(如“+”茄靠、“-”茂契、“*"、“/”慨绳、“=”)掉冶、哪些是分隔符(如“{”、“}”脐雪、“;”等)并且分門別類厌小,這些被分析出來的元素統(tǒng)稱為Token。

至于如何找出Token战秋,方法其實并不限定璧亚,這取決于第一步你的語言風格是如何設計的,常見的分析方法:(1)用正則表達式分析获询,本書第三章用的是這個方法涨岁。

(2)正則表達式能夠表述非常復雜的字符串模式匹配邏輯,但它并非萬能吉嚣,所以本書又在第十五章提供了一個“手工詞法分析器”的方法梢薪,將正則表達式分析方法改寫為自動機方法,具體流程見下圖



第三步:設計語法分析器(Parsing)

? ? ? 我們在第二步獲得Token之后尝哆,就要通過語法分析器(Parser)將Token解析為抽象語法樹(abstract syntax tree秉撇,即AST),如果學過編譯原理,那么你不會對AST感到陌生琐馆,如果不熟悉的話规阀,應該好好閱讀一下第4章:用于表示程序的對象。

? ? ? 在計算機科學中瘦麸,抽象語法樹谁撼,是源代碼的抽象語法結(jié)構(gòu)的樹狀表現(xiàn)形式,這里特指編程語言的源代碼滋饲。樹上的每個節(jié)點都表示源代碼中的一種結(jié)構(gòu)厉碟。之所以說語法是“抽象”的,是因為這里的語法并不會表示出真實語法中出現(xiàn)的每個細節(jié)屠缭。比如箍鼓,嵌套括號被隱含在樹的結(jié)構(gòu)中,并沒有以節(jié)點的形式呈現(xiàn)呵曹;而類似于if-condition-then這樣的條件跳轉(zhuǎn)語句款咖,可以使用帶有兩個分支的節(jié)點來表示。

例如我們要用一個抽象語法樹表示一個表達式: 13+x*2

會得到下面的??樹狀圖:


? ? ? ? 了解完抽象語法樹的概念后奄喂,我們將正式開始語法分析器的設計铐殃。在第二步,我們已經(jīng)通過詞法分析器(Lexer)分解為了單詞序列砍聊。而語法分析器(Parser)的任務是將這些單詞序列與語法規(guī)則定義的模式進行匹配背稼,并構(gòu)造出如上圖那樣的抽象語法樹。

? ? ? ?在語法設計的時候玻蝌,你設計的表達式越復雜,則在語法分析的時候词疼,面臨的困難就越大俯树,所以從語言使用者的角度來看,我還是喜歡設計簡潔的語言贰盗。

? ? ? 其實對于搞出語法分析器還有另一種辦法许饿,那就是借助語法分析器的生成器(Parser Generator),例如yacc, bison 或者 ANTLR舵盈,這些都是比較完善的生成器陋率,可以大大降低工作量以及減少bug。

? ? ? 當然本著我們要自己搞一套的理念??秽晚,本書中仍然提供了手寫語法分析器的過程以及代碼瓦糟。自己手寫語法分析器的過程,當然是對語法分析的一次極有價值的實踐赴蝇,所以嘛菩浙,從玩票的角度,我們?nèi)匀粦搱猿质謱慞arser????。


第四步:設計解釋器并執(zhí)行程序(Evaluation)

? ? ? ? 如第一天教程所介紹的劲蜻,我們拿到抽象語法樹(AST)之后陆淀,要編譯還是解釋就取決于我們的需求了,當然先嬉,有興趣的話兩者都可以實現(xiàn)轧苫,編譯器的設計請參看圖靈的自制編譯器一書。

? ? ? 言歸正傳疫蔓,從抽象語法樹(AST)到通過求值(Evaluate)得到結(jié)果含懊,其實有很多種策略,根據(jù)策略的不同鳄袍,執(zhí)行效率也會有較大的差別绢要,最簡單的策略就是本書中提到的遍歷抽象語法樹解釋法(A Tree-Walking Interpreter),即從抽象語法樹的根節(jié)點開始遍歷該樹直至葉節(jié)點拗小,并計算各節(jié)點的內(nèi)容重罪。

? ? ? 我們的語法樹的每個節(jié)點都需要具備相應的求值(eval)方法。eval方法將計算與以該節(jié)點為根的子樹對應的語句哀九、表達式及子表達式剿配,并返回執(zhí)行結(jié)果。因此阅束,只要調(diào)用抽象語法樹的根節(jié)點對象的eval方法呼胚,就能完整執(zhí)行該語法樹對應的程序。eval方法將遞歸調(diào)用該節(jié)點的子節(jié)點的eval方法息裸,并根據(jù)它們的返回值計算自身的返回值蝇更,最后將結(jié)果返回給調(diào)用者。


遍歷抽象語法樹的節(jié)點

? ? 說到關鍵之處呼盆,本書作者引入了一個其自己開發(fā)的“GlounJ”的系統(tǒng)來實現(xiàn)解釋器年扩。當然,我們也完全可以拋開“GlounJ”系統(tǒng)來完成自己的解釋器访圃。


總結(jié):

? ? ? 本書到第6章厨幻,其實已經(jīng)把一個初步的腳本語言設計完成,并且涉及到了開發(fā)一門腳本語言所需要的基礎知識和概念腿时,后面的7-10章則陸續(xù)介紹了如何引入函數(shù)况脆、面向?qū)ο蟆?shù)組的方法批糟,進一步的豐富了腳本語言格了,使其具有圖靈完備性。第11-14章則進一步討論如何優(yōu)化解釋器的性能:優(yōu)化變量讀寫性能跃赚、優(yōu)化對象操作性能笆搓、設計中間代碼解釋器性湿、添加靜態(tài)類型等等。第15-19章則從另一種角度出發(fā)满败,以不同的方式實現(xiàn)了腳本語言的第2肤频、3、4步算墨,反映了解決問題的不同思路宵荒。?

? ? ?總的來說,如果你要是想設計并實現(xiàn)一門腳本語言净嘀,而又需要中文教材的話报咳,本書是你目前的唯一選擇??。至于缺點嘛挖藏,我覺得就是大段的代碼邊上沒有注釋暑刃,啃起來有點費勁,要是能有一個帶注釋的版本會更好膜眠!

? ? 最后岩臣,感謝圖靈帶給我們的這本好書,下一次宵膨,我將挑戰(zhàn)自制編程語言自制編譯器??

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末架谎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子辟躏,更是在濱河造成了極大的恐慌谷扣,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捎琐,死亡現(xiàn)場離奇詭異会涎,居然都是意外死亡,警方通過查閱死者的電腦和手機瑞凑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門在塔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拨黔,你說我怎么就攤上這事〈铝ぃ” “怎么了篱蝇?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長徽曲。 經(jīng)常有香客問我零截,道長,這世上最難降的妖魔是什么秃臣? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任涧衙,我火速辦了婚禮哪工,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘弧哎。我一直安慰自己雁比,他們只是感情好,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布撤嫩。 她就那樣靜靜地躺著偎捎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪序攘。 梳的紋絲不亂的頭發(fā)上茴她,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機與錄音程奠,去河邊找鬼丈牢。 笑死,一個胖子當著我的面吹牛瞄沙,可吹牛的內(nèi)容都是我干的己沛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼帕识,長吁一口氣:“原來是場噩夢啊……” “哼泛粹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肮疗,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤晶姊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后伪货,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體们衙,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年碱呼,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒙挑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡愚臀,死狀恐怖忆蚀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情姑裂,我是刑警寧澤馋袜,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站舶斧,受9級特大地震影響欣鳖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜茴厉,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一泽台、第九天 我趴在偏房一處隱蔽的房頂上張望什荣。 院中可真熱鬧,春花似錦怀酷、人聲如沸稻爬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽因篇。三九已至,卻和暖如春笔横,著一層夾襖步出監(jiān)牢的瞬間竞滓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工吹缔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留商佑,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓厢塘,卻偏偏與公主長得像茶没,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子晚碾,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容