我是个编程初学者, 会C语言和一点点C++, 对基本的数据结构和算法有一定的了解, 不精通. 我对编译原理蛮有兴趣的, 于是就下定决定要写一个编译器. 终于在2015年暑假, 花了1个月的时间, 完成了<计算机系统要素>这本书中的编译器项目.
这本书介绍了一门语言jack, 这是一门简单的面向对象语言, 书中只是简单地对这门语言的规范作了点介绍而已, 没有任何代码指导. 仅仅有一些测试数据, 由于我之前学了点编译原理方面的知识, 于是我就参考这本书, 慢慢地完成了jack语言编译器.
我对书中的jack语言规范作了一些改进, 使这门语言更加简洁美观, 同时也增加了一些难度.
最后, 我把这门语言移植到了x86平台下.
下面是一个简单的示例:
1 class Main 2 { 3 function void main() 4 { 5 String s; 6 7 Output.printString("Hello, world!"); 8 Output.println(); 9 10 Output.printString("What's your name?"); 11 Output.println(); 12 s = Input.readLine(); 13 Output.printString("Your name is: "); 14 Output.printString(s); 15 Output.println(); 16 17 return; 18 } 19 20 }
执行 ./jackc Main.jack 就可以把这段源程序编译成Main.vm虚拟机代码文件:
1 function Main.main 1 2 push constant 13 3 call String.new 1 4 push constant 72 5 call String.appendChar 2 6 push constant 101 7 call String.appendChar 2 8 push constant 108 9 call String.appendChar 2 10 push constant 108 11 call String.appendChar 2 12 push constant 111 13 call String.appendChar 2 14 push constant 44 15 call String.appendChar 2 16 push constant 32 17 call String.appendChar 2 18 push constant 119 19 call String.appendChar 2 20 push constant 111 21 call String.appendChar 2 22 push constant 114 23 call String.appendChar 2 24 push constant 108 25 call String.appendChar 2 26 push constant 100 27 call String.appendChar 2 28 push constant 33 29 call String.appendChar 2 30 call Output.printString 1 31 pop temp 0 32 call Output.println 0 33 pop temp 0 34 push constant 17 35 call String.new 1 36 push constant 87 37 call String.appendChar 2 38 push constant 104 39 call String.appendChar 2 40 push constant 97 41 call String.appendChar 2 42 push constant 116 43 call String.appendChar 2 44 push constant 39 45 call String.appendChar 2 46 push constant 115 47 call String.appendChar 2 48 push constant 32 49 call String.appendChar 2 50 push constant 121 51 call String.appendChar 2 52 push constant 111 53 call String.appendChar 2 54 push constant 117 55 call String.appendChar 2 56 push constant 114 57 call String.appendChar 2 58 push constant 32 59 call String.appendChar 2 60 push constant 110 61 call String.appendChar 2 62 push constant 97 63 call String.appendChar 2 64 push constant 109 65 call String.appendChar 2 66 push constant 101 67 call String.appendChar 2 68 push constant 63 69 call String.appendChar 2 70 call Output.printString 1 71 pop temp 0 72 call Output.println 0 73 pop temp 0 74 call Input.readLine 0 75 pop local 0 76 push constant 14 77 call String.new 1 78 push constant 89 79 call String.appendChar 2 80 push constant 111 81 call String.appendChar 2 82 push constant 117 83 call String.appendChar 2 84 push constant 114 85 call String.appendChar 2 86 push constant 32 87 call String.appendChar 2 88 push constant 110 89 call String.appendChar 2 90 push constant 97 91 call String.appendChar 2 92 push constant 109 93 call String.appendChar 2 94 push constant 101 95 call String.appendChar 2 96 push constant 32 97 call String.appendChar 2 98 push constant 105 99 call String.appendChar 2 100 push constant 115 101 call String.appendChar 2 102 push constant 58 103 call String.appendChar 2 104 push constant 32 105 call String.appendChar 2 106 call Output.printString 1 107 pop temp 0 108 push local 0 109 call Output.printString 1 110 pop temp 0 111 call Output.println 0 112 pop temp 0 113 push constant 0 114 return
执行./jack Main.vm 即可看到运行结果:
是不是觉得非常酷? 我发现很多人虽然学了编译原理, 但是如果要实际动手去写一个编译器, 却不知道如何下手. 以后我会慢慢更新我的博客, 来介绍如何写一个编译器!
另外, 学过编译原理的人都知道, 有一些自动生成工具, 比如flex, bison等, 可以自动帮你完成很大部分的工作. 但是我的编译器不会借助于这些工具, 而是全手工编写的.
当时写的完整编译器代码在这里: https://github.com/Xiang1993/jack-compiler
其实这个编译器其实有很多的bug的, 因为比较忙, 所以一直都没有修复. 注释也比较少, 而且代码也写得很丑, 于是我决定重新写一遍! 新的编译器代码会放在这里: https://github.com/Xiang1993/new_jack_compiler 我会慢慢更新的!
由于快要毕业了, 以后工作了之后时间也应该不会很多, 所以我的文章可能更新地比较慢!