因爲方纔才獲悉博客園文章默認不放在首頁的, 原創文章主要經過隨筆顯示, 因此將文章遷移到隨筆;html
這篇帖子將後續更新, 歡迎關注! 這段時間要忙着春招實習, 因此項目更新會慢一點,
語言組織也會比較隨意, 畢竟時間有限, 沒辦法太過雕琢琢磨前端
致親愛的讀者: 我的的文字組織和寫文章的功底屬實通常, 寫的也比較趕時間, 因此係列文章的文字可能比較粗糙, 不免有詞不達意或者寫的很迷惑抽象的地方 若是您看了有疑問或者以爲我寫的實在亂七八糟, 這個很抱歉, 確實是個人問題, 您若是有不懂的地方 的地方或者發現個人錯誤(文字錯誤, 邏輯錯誤或者知識點錯誤都有可能), 能夠直接留言, 我看到都會回覆您!
因爲時間緣由, 目前測試並不完善, 因此推薦以下方式根據您的目的進行閱讀 若是您是學習用, 建議您先將整個項目clone到本地, 而後把感興趣的章節刪除/移動, 本身對照着重寫 模塊, 書寫完每一步測試一下可否正常運行(在指定的路徑去讀取源碼測試可否編譯成功並在命令行執行 java Application(類名) 嘗試可否輸出指望結果, 我沒有研究Junit對編譯器輸出class文件進行測試, 因此目前可能須要您手動測試) 按照以上步驟, 等您將全部模塊重寫一遍, 大概也對這個系列的脈絡有深入理解了! 若是您重頭開始重寫, 每每可能因爲出現某些低級錯誤致使長時間debug才找獲得錯誤, 因此對於初學者, 推薦採用本身補寫替換模塊的 方式 對於但願貢獻代碼的朋友或者對Cva感興趣的朋友, 歡迎貢獻您的源碼與看法, 或者對於該系列一些錯誤/ bug願意提出指正的朋友, 您能夠留言或者在github發issue, 我看到後必定及時處理!
寫在前面java
文章目錄git
先修技能/工具程序員
Cva文法-grammar推導式github
說明面試
Cva程序樣例後端
從屏幕前的你搜索到這篇博文開始, 咱們就要開始一篇實現本身的JVM語言系列了, 目前國外有大佬作了
一個Enkel語言, 還有翻譯教程, 不過恕我直言教程太跳了, 不少細節語焉不詳, 也多是翻譯的緣由,
因此我但願寫一個國人的自制JVM語言系列教程, 在這之間我已經完成了github項目, 語言已經能實現不少
基本的Java的特性(方法, 循環, 簡單的面向對象與繼承), 你能夠直接使用之, 在此基礎上構建你的項目,
或者你們能夠一塊兒提交修改, 讓Cva成爲一個更棒的語言咱們將其名字暫定爲Cva, 開始也有想過比較霸氣的alloy,
可是看到這好像已是一個語言了, 固然, 目前咱們的語言這麼菜, 也很差意思叫Alloy(其實叫Cva都是我臉皮厚,
哈哈架構
爲何叫Cva, 其實我一開始的設想是這個語言的最終目的是兼容C(希望吧, 畢竟C的類型系統和不少糟粕仍是不必學着),
目前是至關小至關菜的一個子集, 畢竟C的語法仍是至關複雜, 如今畢業找工做的壓力比較大, 因此這個項目
真正對C兼容仍是有很長的路要走的jvm
不過人嘛, 夢想老是要有的, 寫一個編譯器有一個本身的語言何不是不少程序員年少的夢想? 爲了寫這個語言,
筆者從去年11月開始嘗試了不少方法, 有github上其餘同窗的大做業, 有讀龍書虎書鯨書, <兩週自制腳本語言>,
有網易雲Coding 迪斯尼的自底向上, 前先後後推翻了不少方案, 改了不少版本, (說實話自底向上真的太抽象了,
至關勸退), 最終完成這個項目卻不過區區十來天, 主要是過年那段時間, 天天廢寢忘食地寫代碼提交,
常常半夜構思想的睡覺都睡不着, 通過長時間的積累
最終算是勉強完成了一個差強人意的版本把, 在這裏因爲春招臨近的緣故, 筆者不得不收心去準備春招實習面試,
因此把這個項目的教程寫完後可能就暫時中止更新, 至於再見的時間? 我也不清楚, 多是春招結束放蕩的大四
(可是萬一要提早去公司實習幹活呢?), 因此有點遙遙無期的意味
不過這些文章會將一個編譯器從0到1的實現過程, 儘量簡單易懂地展示給你們, 當你讀完這個系列的文章,
理解了編譯器(其實本文基本都是前端, 後端基本都被JVM作完了, 後面我可能會寫一個自制JVM系列,
不過在這以前仍是先推出自制操做系統和實現TCP/IP協議棧系列吧)加上我前期調教好的代碼,相信即便你是小白,
也能快速定製本身的需求, 快速書寫出一個本身的語言!
比較熟練的JavaSE基礎便可
JDK1.8及以上版本, 源碼中有大量利用了Java8函數式特性的地方
jasmin彙編器, 在github倉庫的lib目錄下
Grammar 推導式
Program -> pkg com.company.proj; // 包名目前是無關緊要的. 沒啥用 -> call com.company.somepkg; // 導包目前也是擺設, 無關緊要 -> EntryClass(入口類, 擁有main方法, 位置是任意的) | EntryMethod | ClassDeclList EntryClass -> class Entry(默認爲Application) { retType main() { StatementList } } ClassDeclList -> ClassDecl | ClassDecl ClassDeclList ClassDecl -> class Identifier { VarDeclList MethodDeclList } | class Identifier : Identifier { VarDeclList MethodDeclList } VarDeclList -> VarDecl | VarDecl VarDeclList | VarDecl -> Type Identifier; MethodDeclList -> MethodDecl | MethodDecl MethodDeclList | MethodDecl -> Type Identifier (FormalList) { VarDeclList StatementList return Expr; } FormalList -> Type Identifier // formal就是形參, args; | Type Identifier, FormalList | Type -> int -> boolean -> string ... 其餘的目前還不支持 -> Identifier StatementList -> Statement | Statement StatementList | Statement -> { StatementList } // 多條語句構成Block, 要加上大括號限定域; | if (Expr) Statement else Statement | while (Expr) Statement // write 也能夠是writeln, writef, writef目前不支持; | write(Expr); | Identifier = Expr; Expr -> Expr Op Expr | Expr.Identifier(ExprList) | IntegerLiteral | Identifier | this | new Identifier() | Const ...(包括const int, true, false) | !Expr | (Expr) Op -> + | - | * | / | % | < | > | & | | | ^ | >> | << | >>> | && ExprList -> Expr | Expr, ExprList | Identifier -> [A-Za-z_][A-Za-z0-9_]* IntegerLiteral -> [0-9]+ LineComment -> // the total line is comment
int
boolean
兩種基本類型, 進階類型支持 string
支持自定義的類類型public
), 支持繼承(若無顯式父類聲明,Object
類型), 但不支持顯式調用父類方法if/if-else
while
for
的分支和循環控制, 支持方法調用)+
-
*
/
%
&&
=
.
!
<
++
--
&
|
^
>>
<<
>>>
等其餘運算符{
}
(
)
;``,
比較運算支持 <
, 邏輯運算支持 &&
!
//
行註釋以及 /* ... */
塊註釋class Entry { /** * This is the entry point of the program; */ int main(string[] args) { echo "Hello, CvaWorld\n"; // 打印整形 statement println(new FibCalcer().compute(10)); return 0; } } class FibCalcer { int compute(int num) { int total; if ( num < 1) { // 花括號是能夠不要的, 可是咱們的代碼要遵照阿里巴巴Cva規範(滑稽); total = 1; } else { total = num * (this.compute(num - 1)); } // 目前不支持提早 return, 挺遺憾的; return total; } }
固然, main方法也有野的寫法, 但目前Cva僅支持將main方法這麼寫
int main(string[] args) { echo "Hello, CvaWorld\n"; return 0; }
即main類不須要定義, 只須要聲明main方法便可, 固然, 這不過是語法糖一顆, 編譯時會自動加上默認主類名Application(這樣會出現的名稱衝突問題暫時還沒解決)