從今天開始研究開發自己的編程語言Ocelot,從《自製編譯器》出發,然後再自己不斷完善功能並優化。 編譯器前端簡單,就不深入研究了,直接用現成的一款工具叫JavaCC,它可以生成抽象語法樹,抽象語法樹是生成中間代碼的關鍵,而中間代碼又是生成後端代碼的關鍵。 整個編譯器代碼採用java語言編寫,主要功 ...
從今天開始研究開發自己的編程語言Ocelot,從《自製編譯器》出發,然後再自己不斷完善功能並優化。
編譯器前端簡單,就不深入研究了,直接用現成的一款工具叫JavaCC,它可以生成抽象語法樹,抽象語法樹是生成中間代碼的關鍵,而中間代碼又是生成後端代碼的關鍵。
整個編譯器代碼採用java語言編寫,主要功能是對JavaCC生成的抽象語法樹進行語義分析、優化,最後生成優化後的彙編代碼,然後再用彙編器對彙編代碼彙編生成機器碼,最後再用命令鏈接生成Linux可執行文件,就可以直接在Linux上運行了。
整個編譯器採用的語法基本上都是C語言的語法,去除掉一些語法成C語言簡化版,而且原項目並無優化。我想做的是在原項目的基礎上對其各種優化並使其支持垃圾回收。- -!有的玩了。
抽象語法樹和其節點都是繼承自Node類。介紹一下Node 類群的繼承層次:
再來通過一個簡單的helloworld小demo來查看抽象語法樹的結構,demo如下所示:
int main(int argc, char **argv) { int i, j = 5; if (i) { return (j * 1 - j); } else { exit(1); } }
編譯器項目運行後生成的抽象語法樹如下所示:
<<AST>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:1) variables: functions: <<DefinedFunction>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:1) name: "main" isPrivate: false params: parameters: <<Parameter>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:1) name: "argc" typeNode: int <<Parameter>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:1) name: "argv" typeNode: char** body: <<BlockNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:2) variables: <<DefinedVariable>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:3) name: "i" isPrivate: false typeNode: int initializer: null <<DefinedVariable>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:3) name: "j" isPrivate: false typeNode: int initializer: <<IntegerLiteralNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:3) typeNode: int value: 5 stmts: <<IfNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:4) cond: <<VariableNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:4) name: "i" thenBody: <<BlockNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:4) variables: stmts: <<ReturnNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:5) expr: <<BinaryOpNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:5) operator: "-" left: <<BinaryOpNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:5) operator: "*" left: <<VariableNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:5) name: "j" right: <<IntegerLiteralNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:5) typeNode: int value: 1 right: <<VariableNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:5) name: "j" elseBody: <<BlockNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:7) variables: stmts: <<ExprStmtNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:8) expr: <<FuncallNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:8) expr: <<VariableNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:8) name: "exit" args: <<IntegerLiteralNode>> (G:\編譯原理\自製編譯器\源碼\test\hello.cb:8) typeNode: int value: 1
1.<<AST>> 和<<DefinedFunction>> 表示節點的類名。
2.右側所顯示的(G:\編譯原理\自製編譯器\源碼\test\hello.cb:1) 是該節點對應的語法所記載的文件名和行號。
3.縮進表示該節點被前一個節點引用。