(写博客是提醒自己挖了坑一定要填)
github地址https://github.com/lucyTheSlayer/orange
趁着空闲时间,准备学习自己搞一套编程语言出来,就命名为Orange。
Orange的最终目标是python的简化版,具有oop的支持(希望能坚持到这步)
于是翻出好几年前的老书《编译原理及实践》,照着书后源码就是一顿敲。书中的TINY语言格式是在是太丑了,所以必须对其源码进行相应的修改,主要是增加了几个关键词,把REPEAT语句改成了现代感更强的WHILE等。目前Orange的代码样例如下:
apple := 200;
banana := 100;#ohoh123
if(apple0){
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!