- 课程名称:编程语言原理与编译
- 实验项目:期末大作业
- 专业班级:
- 学生学号:
- 学生姓名:
- 实验指导教师:
- 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 | √ |