本科期間發明了個程式語言,和小夥伴一起寫了個編譯器。
世上現有的程式語言都太破了。我要自己設計個語言,做出編譯器。
來證明還可以有更破的。
Shoolang是程序導向的、靜態作用域的、強型別的通用程式語言。通俗講,就是有點像C/C++,但是少了很多的功能,以及多了很少的功能。
Shoo支持多維陣列、遞迴、巢狀函式,可以寫出大部份的基礎演算法。比如氣泡排序,用頭等函式(first class functions)自訂比較方式,來把一堆structs排序:
還能拿去砍Leetcode題,比如解數獨:
按照使用者輸入,畫個字元畫什麽的:
我們有17頁的語言手冊【Shoo語言:從入門到放棄】:
https:// github.com/sam-jay/shoo -lang/blob/master/Language_Reference_Manual.md
作為史上最破,Shoo編譯器有以下特性:
Shoo編譯器由以下幾個模組串在一起——
1)詞法分析(scanner.mll)
將讀入的ASCII碼形式的原始碼轉化成一個個token,比如關鍵詞、數位、字串、運算子、括弧等等。程式碼的註釋會在這一步被舍棄。
2)語法分析(parser.mly)
把上一步產生的token,根據定義好的Shoo語法,轉換成一個抽象語意樹(abstract syntax tree,簡稱AST)。語法糖也在這一步轉化。
3)語意分析(sement.ml)
遍歷AST樹,將其轉換為SAST樹。這個樹的每個節點都是一個包含了多種後設資料的物件(object),在後一步驟有用。
理論上不檢查原始碼是否符合要求也是可以的,我們可以寫一個很暴躁的編譯器,啥也不檢查,二話不說轉成二進制碼,跑崩了誰寫的碼誰背鍋。為了世界的和平,還是好好地檢查錯誤了。
4)中間程式碼的轉換(lift.ml)
Shoolang支持頭等函式(first class functions),所以有對應的模組負責做轉換。其它可能的模組有型別推斷(type inference),那麽再串一個模組做型別的轉換。
Shoo編譯器用SAST節點的後設資料記錄語境資訊,將所有被巢狀的函式上升到全域範圍的同時不改變程式表現。每個語境包含獨有的變量,用關聯地圖(map)儲存。
5)程式碼生成(codegen.ml)
直接對接LLVM模組,把SAST節點轉成更低階的語言。這種方法的前提是,Shoo語言的原始碼和LLVM程式碼存在token層級的一一對應關系。舉個反例,「or」這個運算子在有的語言中有短路效果,於是我們舍棄了短路這個特性。
然後連結C庫(builtins.c),用來輔助完成輸入輸出的一些功能,還有字串相關的操作。最後輸出二進制碼。
關於用OCaml寫編譯器。OCaml定義上下文無關文法(context free grammar)方便得跟開掛一樣,還可以各種調Lex和LLVM模組。
用Ocaml寫也有缺點。很難學。超級煩。但是很有用。你會花很多很多的時間,寫很少很少的碼,來做很多很多事情。
最後,造編譯器推薦看龍書(Compilers: Principles, Techniques, and Tools by Alfred V. Aho, Ravi Sethi, Jeffrey D.Ullman)。裏面啥都有,除了龍。
==============================================
微博@甜菜妍妍,定期更新寫碼日常;
公主號「甜菜妍妍」,非週期性分享寫碼留學找工tips~
相關回答: