- 课程名称:编程语言原理与编译
- 实验项目:期末大作业
- 专业班级:
- 学生学号:
- 学生姓名:
- 实验指导教师:
- github
这是一个编译原理大作业,主要基于microC完成的,这个之所以取名为Cuby,主要是在看《计算的本质》这本书的时候,发现Ruby是一门非常好玩有趣的语言,相比C++的错综复杂来说,Ruby是一个集成了优雅与复杂的语言,比如在irb下:
>> 3.times{puts("Hello world")}
Hello world
Hello world
Hello world
=> 3
>>我看到这门语言的时候我就惊呆了,居然语言还可以这样玩。而C++却令人反胃,实在是太恶心了,虽然说C++给你提供了所有你想用的,但是学习成本高,任何东西都感觉不伦不类的。
Ruby是一门完全面向对象的编程语言,我尝试去实现面向对象的功能,本来取名叫Yuby,奈何实现面向对象实在太难了,我光是看JVM的指令集就很困难了,还要实现一大堆类库,实在太过于困难了,中途也下过Ruby的源代码,是用C写成的。最后还是放弃了实现面向对象的功能,选择结合microC与Ruby的语法方面作为我们大作业的方向。
我们打算完善microC并加入Ruby 的 语法,最后如果还有时间的话能够完成面向对象的一个类(最后还是没时间了)。
-
前端:由
F#语言编写而成CubyLex.fsl生成的CubyLex.fs词法分析器。CubyPar.fsy生成的CubyPar.fs语法分析器。AbstractSyntax.fs定义了抽象语法树Assembly.fs定义了中间表示的生成指令集Compile.fs将抽象语法树转化为中间表示
-
后端:由
Java语言编写而成Machine.java生成Machine.class虚拟机与Machinetrace.class堆栈追踪
-
测试集:测试程序放在
testing文件夹内 -
库:
.net支持FsLexYacc.Runtime.dll
-
fslex --unicode CubyLex.fsl
生成CubyLex.fs词法分析器 -
fsyacc --module CubyPar CubyPar.fsy
生成CubyPar.fs语法分析器与CubyPar.fsi -
javac Machine.java
生成虚拟机 -
fsi -r FsLexYacc.Runtime.dll AbstractSyntax.fs CubyPar.fs CubyLex.fs Parse.fs Assembly.fs Compile.fs ParseAndComp.fs
可以启用fsi的运行该编译器。 -
在
fsi中输入:
open ParseAndComp;; -
之后则可以在
fsi中使用使用:-
fromString:从字符串中进行编译 -
fromFile:从文件中进行编译 -
compileToFile:生成中间表示
-
例子:
compileToFile (fromFile "testing/ex(struct).c") "testing/ex(struct).out";;
#q;;
fromString "int a;"生成中间表示之后,便可以使用虚拟机对中间代码进行运行得出结果:
虚拟机功能:
java Machine运行中间表示java Machinetrace追踪堆栈变化
例子:
java Machine ex11.out 8
java Machinetrace ex9.out 0- 变量定义
- float 类型
- FOR循环
- do - while
- 类似C的switch-case
-
当没有break时,匹配到一个case后,会往下执行所以case的body
-
若当前没有匹配的case时,不会执行body,会一直往下找匹配的case
-
之前的实现是递归匹配每个case,当前类似C语言的switch-case实现上在label的设立更为复杂一些。
-
例子:
int main(){ int i=0; int n=1; switch(n){ case 1:i=n+n; case 5:i=i+n*n; } }
-
运行栈追踪:
-
- break功能
- continue 功能
- 结构体功能:
-
简介:加入了C中的结构体功能,可以嵌套数组
-
首先,先创建结构体定义表,用来查找,结构体定义表中包含结构体的总体大小,名字,以及变量和偏移量。然后查找结构体变量表,加入该变量到varEnv中,访问成员时,便可以通过
.运算符,通过偏移值转化为简单指令集。 -
例子:
struct student{ int number; int number2; char name[5]; float id; }; int main(){ struct student hello; hello.number = 10; hello.id = 234; hello.name[4] = 'c'; hello.name[0] = 'a'; print hello.number; print hello.name[4]; }
-
- JVM
-
try-catch:
- 简介:
- 除0异常捕获:
- 虚拟机运行时的除0异常
- 出现显式的除0时THROW 异常
- 寄存器添加:
- hr: 保存当前异常在栈中的地址,用于追踪需要处理的异常
- 指令添加:
- PUSHHDLR,保存catch中的异常种类,需要跳转的位置以及hr入栈
- POPHDLR ,与PUSHHDLR对应
- THROW ,用于丢出异常,从hr开始找匹配
- 例子:
- 除0异常捕获:
- 目前做了有关除0异常的内容,由于没有异常类,暂且通过字符串的方式作为异常种类,将异常编号匹配。解决了运行时try-catch变量环境的问题,解决了异常处理时栈环境变化带来的空间影响。能够正常的匹配到异常。
int main() { try{ int a=0; int n=5; n=n/a; } catch("ArithmeticalExcption") { n=0; print n; } }
- 运行时堆栈:
- 简介:
| 功能 | 对应文件 | 优 | 良 | 中 |
|---|---|---|---|---|
| 变量声明定义 | ex(init).c | √ | ||
| 自增、自减 | ex(selfplus).c | √ | ||
| for循环 | ex(for).c | √ | ||
| 三目运算符 | ex(ternary).c | √ | ||
| do-while | ex(dowhile).c | √ | ||
| while | ex(while).c | √ | ||
| range循环 | ex(range).c | √ | ||
| break | ex(break).c | √ | ||
| continue | ex(continue).c | √ | ||
| switch-case | ex(switch).c | √ | ||
| float 类型 | ex(float).c | √ | ||
| char 类型 | ex(chars).c | √ | ||
| struct结构体 | ex(struct).c | √ | ||
| try-catch | ex(exception).c | √ | ||
| 虚拟机类型支持 | Machine.java | √ | ||
| 虚拟机异常 | exception | √ |
.png)
1.png)
2.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)

.png)