(写博客是提醒自己挖了坑一定要填)

github地址https://github.com/lucyTheSlayer/orange
<https://github.com/lucyTheSlayer/orange>

趁着空闲时间,准备学习自己搞一套编程语言出来,就命名为Orange。

Orange的最终目标是python的简化版,具有oop的支持(希望能坚持到这步)


于是翻出好几年前的老书《编译原理及实践》,照着书后源码就是一顿敲。书中的TINY语言格式是在是太丑了,所以必须对其源码进行相应的修改,主要是增加了几个关键词,把REPEAT语句改成了现代感更强的WHILE等。目前Orange的代码样例如下:
apple := 200; banana := 100;#ohoh123 if(apple<banana){ orange := apple*banana;
banana := 12*apple - 32; } i := 10; while(i>0){ write i; i := i - 1; }

这里面的赋值号为:=,这种老式的方式也让人看了很难受,留待以后(真的有以后吗?)再改吧。

目前的进度是能把上述代码转换为字节码,但由于解释器还没搞,所以到底这字节码对不对还不好说。以下是整个编译过程的简记:

1)lexer 词法分析

该模块负责从文件中读取源码,并将其以token的形式返回给上层parser使用,于是上述代码经过lexer后变成以下形式。
ID, name= apple := NUM, val= 200 ; ID, name= banana := NUM, val= 100 ;
reserved word: if ( ID, name= apple < ID, name= banana ) { ID, name= orange :=
ID, name= apple * ID, name= banana ; ID, name= banana := NUM, val= 12 * ID,
name= apple - NUM, val= 32 ; } ID, name= i := NUM, val= 10 ; reserved word:
while ( ID, name= i > NUM, val= 0 ) { reserved word: write ID, name= i ; ID,
name= i := ID, name= i - NUM, val= 1 ; }
当然,词法分析器不是一下子便将所有内容全部token化,而是需要parser主动调用获取token。

2)parser 语法分析

语法分析是最重要的一环,此处采用的是自顶向下的方法,它将源代码转换为一棵语法树。
Assign to : apple Const: 200 Assign to : banana Const: 100 If Op: < Id: apple
Id: banana Assign to : orange Op: * Id: apple Id: banana Assign to : banana Op:
- Op: * Const: 12 Id: apple Const: 32 Assign to : i Const: 10 While Op: > Id: i
Const: 0 Write Id: i Assign to : i Op: - Id: i Const: 1
3)语义分析

有了语法树,就可以为所欲为了,在这一步建立了符号表,以及在此做类型检查,譬如c语言里的int a =
"abc"这种具有明显的类型错误,那再这一步就必须检查出来了。


Building Symbol Table... Symbol table: Variable Name Location Line Numbers
banana 1 2 3 4 5 orange 2 4 i 3 7 8 9 10 10 apple 0 1 3 4 5 Checking Types...
Type Checking Finished
4)代码生成

这是最激动人心的时刻,也是编译器部分最终成果的展示部分。最终我的Orange源代码转变为了以下字节码
* TINY Compilation to TM Code * File: hello.orangebc * Standard prelude: 0: LD
6,0(0) load maxaddress from location 0 1: ST 0,0(0) clear location 0 * End of
standard prelude. * -> assign * -> Const 2: LDC 0,200(0) load const * <- Const
3: ST 0,0(5) assign: store value * <- assign * -> assign * -> Const 4: LDC
0,100(0) load const * <- Const 5: ST 0,1(5) assign: store value * <- assign *
-> if * -> Op * -> Id 6: LD 0,0(5) load id value * <- Id 7: ST 0,0(6) op: push
left * -> Id 8: LD 0,1(5) load id value * <- Id 9: LD 1,0(6) op: load left 10:
SUB 0,1,0 op < 11: JLT 0,2(7) br if true 12: LDC 0,0(0) false case 13: LDA
7,1(7) unconditional jmp 14: LDC 0,1(0) true case * <- Op * if: jump to else
belongs here * -> assign * -> Op * -> Id 16: LD 0,0(5) load id value * <- Id
17: ST 0,0(6) op: push left * -> Id 18: LD 0,1(5) load id value * <- Id 19: LD
1,0(6) op: load left 20: MUL 0,1,0 op * * <- Op 21: ST 0,2(5) assign: store
value * <- assign * -> assign * -> Op * -> Op * -> Const 22: LDC 0,12(0) load
const * <- Const 23: ST 0,0(6) op: push left * -> Id 24: LD 0,0(5) load id
value * <- Id 25: LD 1,0(6) op: load left 26: MUL 0,1,0 op * * <- Op 27: ST
0,0(6) op: push left * -> Const 28: LDC 0,32(0) load const * <- Const 29: LD
1,0(6) op: load left 30: SUB 0,1,0 op - * <- Op 31: ST 0,1(5) assign: store
value * <- assign * if: jump to end belongs here 15: JEQ 0,17(7) if: jmp to
else 32: LDA 7,0(7) jmp to end * <- if * -> assign * -> Const 33: LDC 0,10(0)
load const * <- Const 34: ST 0,3(5) assign: store value * <- assign * -> while
* -> Op * -> Id 35: LD 0,3(5) load id value * <- Id 36: ST 0,0(6) op: push left
* -> Const 37: LDC 0,0(0) load const * <- Const 38: LD 1,0(6) op: load left 39:
SUB 0,1,0 op > 40: JLT 0,2(7) br if false 41: LDC 0,1(0) true case 42: LDA
7,1(7) unconditional jmp 43: LDC 0,0(0) false case * <- Op * while: jump to end
belongs here * -> Id 45: LD 0,3(5) load id value * <- Id 46: OUT 0,0,0 write ac
* -> assign * -> Op * -> Id 47: LD 0,3(5) load id value * <- Id 48: ST 0,0(6)
op: push left * -> Const 49: LDC 0,1(0) load const * <- Const 50: LD 1,0(6) op:
load left 51: SUB 0,1,0 op - * <- Op 52: ST 0,3(5) assign: store value * <-
assign 53: LDA 7,-19(7) jmp back to loop 44: JEQ 0,8(7) while: jmp to end * <-
while * End of execution. 54: HALT 0,0,0


okay,看起来很cool,虽然书中作者采用的这种汇编语言格式看上去还是很不爽(个人推崇python的字节码样式),但现在是学习阶段,先学,后面再改成我自己喜欢的格式(真的有后面吗?)。

这里面while语句的字节码是我自己生成的,不知道对不对,一切都得等vm机码完才知道(真的码的完吗?)了。





此文只是我个人娱乐所用,当然如果你不幸浏览到这,发现什么也没get到,很气,那么在这,我推荐《编译原理及实践》这本书,跟着书中源码走一遍,很多都豁然开朗了。一切的技术,plz
read the fucking source code!



友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信