這個系列算做我本身的學習筆記,到如今已經有十三篇了,加上這篇一共十四篇。一步一步的從詞法分析到語法分析、語義分析,再到代碼生成,準備在這一篇作一個總結收尾和一個這個系列之前文章的索引。html
(另外,因爲我如今的這個主題不能對markdown的一級標題做目錄,因此這個系列文章的目錄都是有問題的)java
從零寫一個編譯器(一):輸入系統和詞法分析markdown
對於C語言的一個快速排序
void quicksort(int A[10], int p, int r) { int x; int i; i = p - 1; int j; int t; int v; v = r - 1; if (p < r) { x = A[r]; for (j = p; j <= v; j++) { if (A[j] <= x) { i++; t = A[i]; A[i] = A[j]; A[j] = t; } } v = i + 1; t = A[v]; A[v] = A[r]; A[r] = t; t = v - 1; quicksort(A, p, t); t = v + 1; quicksort(A, t, r); } } void main () { int a[10]; int i; int t; printf("before quick sort:"); for(i = 0; i < 10; i++) { t = (10 - i); a[i] = t; printf("value of a[%d] is %d", i, a[i]); } quicksort(a, 0, 9); printf("after quick sort:"); for (i = 0; i < 10; i++) { printf("value of a[%d] is %d", i, a[i]); } }
就直接在控制檯輸出
會在當前目錄生成一個C2Bytecode.j字節碼文件,再通過字節碼的彙編器就能夠在JVM上運行
.class public C2Bytecode .super java/lang/Object .method public static main([Ljava/lang/String;)V sipush 10 newarray int astore 0 sipush 0 istore 2 sipush 0 istore 1 getstatic java/lang/System/out Ljava/io/PrintStream; ldc "before quick sort:" invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V getstatic java/lang/System/out Ljava/io/PrintStream; ldc " " invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V sipush 0 istore 2 loop0: iload 2 sipush 10 if_icmpge branch0 sipush 10 iload 2 isub istore 1 aload 0 iload 2 iload 1 iastore aload 0 iload 2 iaload istore 3 iload 2 istore 4 getstatic java/lang/System/out Ljava/io/PrintStream; ldc "value of a[" invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V getstatic java/lang/System/out Ljava/io/PrintStream; iload 4 invokevirtual java/io/PrintStream/print(I)V getstatic java/lang/System/out Ljava/io/PrintStream; ldc "] is " invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V getstatic java/lang/System/out Ljava/io/PrintStream; iload 3 invokevirtual java/io/PrintStream/print(I)V getstatic java/lang/System/out Ljava/io/PrintStream; ldc " " invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V iload 2 sipush 1 iadd istore 2 goto loop0 branch0: aload 0 sipush 0 sipush 9 invokestatic C2Bytecode/quicksort([III)V getstatic java/lang/System/out Ljava/io/PrintStream; ldc "after quick sort:" invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V getstatic java/lang/System/out Ljava/io/PrintStream; ldc " " invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V sipush 0 istore 2 loop2: iload 2 sipush 10 if_icmpge branch4 aload 0 iload 2 iaload istore 3 iload 2 istore 4 getstatic java/lang/System/out Ljava/io/PrintStream; ldc "value of a[" invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V getstatic java/lang/System/out Ljava/io/PrintStream; iload 4 invokevirtual java/io/PrintStream/print(I)V getstatic java/lang/System/out Ljava/io/PrintStream; ldc "] is " invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V getstatic java/lang/System/out Ljava/io/PrintStream; iload 3 invokevirtual java/io/PrintStream/print(I)V getstatic java/lang/System/out Ljava/io/PrintStream; ldc " " invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V iload 2 sipush 1 iadd istore 2 goto loop2 branch4: return .end method .method public static quicksort([III)V sipush 0 istore 5 sipush 0 istore 6 iload 1 sipush 1 isub istore 6 sipush 0 istore 7 sipush 0 istore 3 sipush 0 istore 4 iload 2 sipush 1 isub istore 4 iload 1 iload 2 if_icmpge branch1 aload 0 iload 2 iaload istore 5 iload 1 istore 7 loop1: iload 7 iload 4 if_icmpgt ibranch1 aload 0 iload 7 iaload iload 5 if_icmpgt ibranch2 iload 6 sipush 1 iadd istore 6 aload 0 iload 6 iaload istore 3 aload 0 iload 6 aload 0 iload 7 iaload iastore aload 0 iload 7 iload 3 iastore ibranch2: iload 7 sipush 1 iadd istore 7 goto loop1 ibranch1: iload 6 sipush 1 iadd istore 4 aload 0 iload 4 iaload istore 3 aload 0 iload 4 aload 0 iload 2 iaload iastore aload 0 iload 2 iload 3 iastore iload 4 sipush 1 isub istore 3 aload 0 iload 1 iload 3 invokestatic C2Bytecode/quicksort([III)V iload 4 sipush 1 iadd istore 3 aload 0 iload 3 iload 2 invokestatic C2Bytecode/quicksort([III)V branch1: return .end method .end class
通常用有限狀態自動機或者手工編寫來實現,這一步輸出的是token序列
主要分爲自頂向下和自底向上的語法分析,通常有遞歸降低,LL(1),LR(1),LALR(1)幾種方法實現。這一步輸出的是語法樹
語義分析主要任務是生成符號表,而且發現不符合語義的語句,這一步輸出的仍是AST
這裏通常會生成一個與平臺無關的較爲貼近底層的中間語言(IR),這一步輸入AST,輸出的是IR
這個編譯過程在第一篇的時候就有提起,如今主要想總結的是解釋執行和代碼生成部分,也就是遍歷AST的過程
首先抽象語法樹AST的構造就像是把全部代碼分割成一塊一塊,可是其中塊和塊之間又有邏輯關係,而後把它們組成一棵樹
正是有這顆樹咱們才得以對代碼進行邏輯的解釋,從葉子節點開始,再存儲處理後的信息,傳遞至父節點
好比對於a = 0節點,咱們先遞歸至子節點,求出a和0的值而且保存在本身的節點,而父節點a = 0就能夠利用子節點的信息來對a賦值,好比若是是生成代碼的話,a = 0這個節點的操做可能就是找到這個存儲這個變量的寄存器,而後生成對這個寄存器賦值的指令
在這個過程有一個很是重要的數據結構,即符號表,不管是直接解釋執行仍是代碼生成都會用到。它的主要用來標識和存儲源代碼的變量、函數等。在符號表中,源程序中的每一個標識符都和它的聲明或使用信息綁定在一塊兒,好比其數據類型、做用域以及內存地址。
一個玩具型編譯器的主體思路是很明確的,可是在實際實現當中須要考慮的細節也不少,因此才讓實現過於繁瑣