从今天起,我们将一起开发一个新的编程语言,它的名字叫做ScrJ(Script Jin)。
之所以不叫JS,是因为它不是JavaScript
注:由于本人并未系统学习过编译原理,所以只是一步步完成一个简单的解释器,不涉及优化等复杂技巧,部分功能实现也不尽完备,望指正
我们的编程语言是一个类似的虚拟机,它由前端和后端组成,这里是百度网盘的提取码:scrj_免费高速下载|百度网盘-分享无限制 (baidu.com)
提取码:scrj
打开以后有两个可执行文件:ide.exe 和 scrj.exe,
scrj.exe就是命令行程序,可以双击运行,也可以设置为.sj文件和.sjast文件的打开方式。
ide.exe是用户界面的集成开发环境,可以在Option选项里切换语言。(好吧,现在只支持ch和en,我应该给他开发一个plugin)
其他操作见readme。
注意,如果我们开发的过程中遇到了问题很正常,结构错误也很正常,失败是成功之母,我们一起改正。
我们的解释器和编译器比较像,采用了编译的结构,但是因为水平太菜,所以把AST(抽象语法树)转为汇编或机器语言的这一部分,我们直接使用虚拟机式的解释执行。
对了,我把优化这个特别重要的内容省掉了,以后会补上。
本语言已实现基础数据结构(int、str、bool、float、list),标准、文件、网络IO,基础运算(算术、逻辑、比较),基础流程控制语句(if...choose...else...、for、repeat、while、break、continue),异常捕捉(try...catch...),异常抛出,指针,子程序(函数、匿名函数),类(类单继承、类多态(暂时还没有开发出类的封装)、Init、Callable)
结构
我们的DIY编程语言的结构是:
词法分析器:wordparser
语法+语义分析器:sentenceparser
(不包括语义检查)
执行器(虚拟机):runner
由于是解释执行,因此不需要语义分析器。
本项目不采用JIT技术。
样例
鸡兔同笼
include sjstd
var a
var b
sjio -> a -> b
a = int(a)
b = int(b)
var chicken = (a * 4 - b) // 2
var rabbit = a - chicken
sjio <- chicken <- " " <- rabbit <- _e
冒泡排序
include sjstd
func sort(array) {
for(var i=0; i<array.len(); i=i+1) {
for(var j=0; j<array.len()-i-1; j=j+1) {
if(array.get(j) > array.get(j+1)) {
var tmp = array.get(j)
array.set(j, array.get(j+1))
array.set(j+1, tmp)
}
}
}
}
var a = []
var l
for(l=0; true; l=l+1) {
var tmp
sjio -> tmp
if(tmp == "q") {
break
}
a.append(int(tmp))
}
sort(a)
for(var i=0; i<l; i=i+1) {
sjio <- a.get(i) <- " "
}
sjio <- _e
快速幂
include sjstd
func quick_pow(a, b) {
if(b == 0) {
return 1
}
choose(b % 2 == 0) {
var tmp = quick_pow(a, b // 2)
return tmp * tmp
}
else {
var tmp = quick_pow(a, b // 2)
return tmp * tmp * a
}
}
var x
var y
sjio -> x -> y
try {
x = int(x)
y = int(y)
sjio <- quick_pow(x, y) <- _e
}
catch("PyLibError") {
sjio <- "类型转换失败,输入的数字非整形。" <- _e
}
类继承
include sjstd
cls Obj {
func init() {
sjio <- "hello" <- _e
}
func hello() {
sjio <- "hello,world" <- _e
}
}
cls Dog: Obj {
func hello() {
sjio <- "dog" <- _e
}
}
cls BadDog: Dog {
func init() {
sjio <- "goodbye" <- _e
}
}
var obj = Dog()
sjio <- obj <- _e
obj.hello()
使用类实现的无穷迭代器
include sjstd
cls Iter {
var v
func init(v) {
this.v = v
}
func main() {
sjio <- this.v <- _e
return Iter(this.v+1)
}
}
var a = Iter(0)
while(a) {
a = a()
}
以上的所有样例都可以使用scrj.exe解释器(Windows平台下)成功运行。可将其保存为.sj文件,更改打开方式为scrj.exe解释器,即可成功运行,同时会在同目录下生成 文件名.sjast 文件,是 文件名.sj 文件的抽象语法树(AST)描述,下次可双击打开此文件,同时可安全删除;同时可双击scrj.exe解释器进入命令行模式。
IDE
这里有我为scrj语言开发的IDE的截图,实现了代码运行、代码调试运行、中英文切换、语法高亮、命令行仿真等功能。
这是代码运行的截图:
这是命令行仿真:
END
如果你也想尝试这个项目的话,不妨点个赞,关注本专栏,thanks~