#解释器 #抽象语法树 #编程语言 #类型 #语法树 #动态 #lox

bin+lib rocks-lang

Rust 实现的 Crafting Interpreters 的 Lox 语言

5 个版本

0.2.2 2023年6月30日
0.2.1 2023年6月29日
0.2.0 2023年6月22日
0.1.1 2023年4月26日
0.1.0 2023年4月25日

#735编程语言

每月 33 次下载

MIT 许可证

140KB
3K SLoC

crates.io docs.rs dependencies codecov

rocks-lang

Rocks 是一种用 Rust 编写的编程语言。它是一种动态类型语言,具有词法作用域和一等函数。Rocks 是一种树遍历解释器,具有手写的递归下降解析器。Rocks 是一个爱好项目,并不打算用于生产环境。

Rocks 是一种动态类型语言。这意味着变量的类型是在运行时确定的。这与静态类型语言相反,在静态类型语言中,变量的类型是在编译时确定的。动态类型语言通常更容易使用,但通常比静态类型语言慢。

Rocks 是一种树遍历解释器。这意味着解释器会遍历抽象语法树(AST),并评估每个节点。这与编译器不同,编译器会将 AST 转换为字节码或机器码。树遍历解释器通常比编译器更容易实现,但通常比编译器慢。

Rocks 是一个爱好项目,并不打算用于生产环境。这个项目的目标是学习更多关于编程语言和解释器的知识。本项目受到 Bob Nystrom 的 Crafting Interpreters 一书的启发。

您可以使用以下命令安装解释器。

cargo install rocks-lang

扫描

解释器的第一步是扫描。扫描是将字符字符串转换为令牌列表的过程。令牌是编程语言的单个单元。例如,字符串 1 + 2 将被转换为以下令牌

[Number(1), Plus, Number(2)]

扫描器在 scanner 模块中实现,作为源代码中字符的迭代器。它是一个简单的状态机,在调用时返回源代码中的下一个令牌。

扫描器报告源代码中的语法错误为ScanError。这些错误是些简单问题,例如未结束的字符串字面量或意外的字符。扫描器一旦遇到语法错误就会报告。这意味着即使扫描器已经遇到语法错误,它仍然会继续扫描源代码。这对于用户来说很有用,因为它允许用户一次修复多个语法错误。

解析

解释器的第二步是解析。解析是将令牌列表转换为抽象语法树(AST)的过程。解析器在parser模块中实现,作为一个递归下降解析器。解析器将令牌列表转换为表达式和语句。Expressions是产生值的代码片段,特别是产生一个Object。在Rocks中,对象是一个总称,包括所有类型的值,如字面量、函数、类和实例。Statements是不产生值但执行某些操作的代码片段。这些操作修改程序的状态,因此被称为副作用。例如,变量声明或if子句会被分类为语句。

例如,字符串print 1 + 2;会被转换为以下AST

PrintStatement {
    BinaryExpression {
        left: Number(1),
        operator: Plus,
        right: Number(2),
    }
}

解析器报告源代码中的语法错误为ParseError。与扫描器不同,解析器会捕获跨越多个令牌的错误。例如,以下表达式是无效的,因为它缺少右操作数

1 !=

然而,与扫描器类似,解析器会继续解析源代码,即使它已经遇到语法错误,也会使用一种称为同步的技术。这很有用,因为它允许用户一次修复多个语法错误。

解析

解释器的第三步是解析。解析是静态分析AST以确定每个变量的作用域的过程。虽然这需要先遍历AST,但这是构建稳健的词法作用域所必需的。解析器在resolver模块中实现,作为一个树遍历解释器。解析器在解析器之后运行,因为它需要AST完全构建。解析器报告错误为ResolveError。这些错误在语法上是有效的,但在语义上无效,因此无法被扫描器或解析器捕获。例如,以下表达式是有效的Rocks语法,但它因为变量a在同一个作用域内被定义了两次而语义上无效

{
   var a = 1;
   var a = 2;
}

解释

解释器的最后一步是解释。解释是将抽象语法树(AST)评估的过程。解释器在interpreter模块中以树遍历解释器的方式实现,地址为https://github.com/boranseckin/rocks/blob/c6b62d328f8b1f33f0c2420dd67b70b25db25669/src/interpreter.rs。由于之前的步骤,解释器能够评估AST并生成结果。解释器将错误报告为RuntimeError。尽管扫描器、解析器和解析器试图在运行代码之前捕获尽可能多的错误,但大多数错误只能在运行时捕获。例如,以下表达式是有效的Rocks语法,但它在语义上是不正确的,因为它试图将字符串和数字相加。

var a = "123";
var b = a + 123;

解释器还负责管理环境。环境是变量名到其值的映射。环境在environment模块中以哈希表的堆栈形式实现,地址为https://github.com/boranseckin/rocks/blob/c6b62d328f8b1f33f0c2420dd67b70b25db25669/src/environment.rs。每个哈希表代表程序中的一个作用域。这允许解释器实现词法作用域。解释器还管理调用堆栈。

许可:MIT

依赖项

~3–10MB
~97K SLoC