10 个版本

0.6.6 2024年6月19日
0.6.5 2023年12月19日
0.6.4 2023年7月20日
0.6.1 2023年3月5日
0.3.0 2021年7月7日

#20编程语言

Download history 3/week @ 2024-04-24 1/week @ 2024-05-22 15/week @ 2024-05-29 1/week @ 2024-06-05 10/week @ 2024-06-12 184/week @ 2024-06-19 4/week @ 2024-06-26 28/week @ 2024-07-03 43/week @ 2024-07-24 12/week @ 2024-07-31

55 每月下载量
2 个 crate 中使用 (通过 tokay-macros)

MIT 许可证

1.5MB
18K SLoC

Tokay

Tokay 是一种为即席解析而设计的编程语言。

Tokay 正在开发中,目前尚未考虑用于生产;成为 Tokay 持续开发的一部分,并 贡献

关于

Tokay 旨在成为一种可以用于快速实现文本处理问题的编程语言。这可以涉及简单的数据提取,也可以是解析句法结构或其部分,并将信息转换为结构化解析树或抽象语法树以进行进一步处理。

因此,Tokay 不仅是一个适用于简单单行代码(如匹配器或识别器)的实用工具,而且还可以用于实现代码分析器、重构工具、解释器、编译器或转换器。实际上,Tokay 的自身语言解析器也是用 Tokay 实现的。

Tokay 受 awk 启发,具有 Python 和 Rust 的句法和语义风味,但同时也遵循其自身的哲学、思想和设计原则。因此,它不能与其他语言或项目直接比较,而是一个独特的存在。

Tokay 仍然是一个非常年轻的项目,具有巨大的潜力。 志愿者欢迎加入!

亮点

  • 解释型、过程型和命令型脚本语言
  • 简洁易学的语法和对象系统
  • 基于流的输入处理
  • 自动解析树构建和合成
  • 支持左递归解析结构("解析器")
  • 内部实现记忆化 packrat 解析算法
  • 由于完全用安全的 Rust 编写,因此稳健且快速
  • 结合其他工具启用awk风格的单行脚本
  • 通用解析器和函数
  • 导入系统以创建模块化程序(即将推出)
  • 与其他程序的嵌入式互操作性(即将推出)

安装

通过使用Rust的依赖管理器和构建工具cargo,简单安装Tokay:

$ cargo install tokay

对于基于Arch Linux的发行版,Arch Linux AUR(Arch Linux用户仓库)中也有一个tokay和一个tokay-git软件包。

示例

Tokay的“Hello World”版本相当明显。

print("Hello World")
$ tokay 'print("Hello World")'
Hello World

Tokay还可以问候任何输入给它的wor(l)ds。下一个程序打印“Hello Venus”,“Hello Earth”或“Hello”后跟之前由内置的Word令牌解析的任何其他名称。任何非单词输入都会自动省略。

print("Hello", Word)
$ tokay 'print("Hello", Word)' -- "World 1337 Venus Mars 42 Max"
Hello World
Hello Venus
Hello Mars
Hello Max

一个简单的程序,用于计算单词和数字,并在之后打印总数,可以像这样实现:

Word words += 1
Number numbers += 1
end print(words || 0, "words,", numbers || 0, "numbers")
$ tokay 'Word words += 1; Number numbers += 1; end print(words || 0, "words,", numbers || 0, "numbers")' -- "this is just the 1st stage of 42.5 or .1 others"
9 words, 3 numbers

设计上,Tokay会自动从消耗的信息中构建语法树。

下一个程序实现了一个简单数学表达式的解析器和解释器,例如1 + 2 + 37 * (8 + 2) / 5。每个表达式的结果随后打印出来。

处理直接和间接左递归而不会导致无限循环是Tokay的核心特性之一。

_ : Char< \t>+            # redefine whitespace to just tab and space

Factor : @{
    Int _                 # built-in 64-bit signed integer token
    '(' _ Expr ')' _
}

Term : @{
    Term '*' _ Factor     $1 * $4
    Term '/' _ Factor     $1 / $4
    Factor
}

Expr : @{
    Expr '+' _ Term       $1 + $4
    Expr '-' _ Term       $1 - $4
    Term
}

Expr _ print("= " + $1)   # gives some neat result output
$ tokay examples/expr_from_readme.tok
1 + 2 + 3
= 6
7 * (8 + 2) / 5
= 14
7*(3-9)
= -42
...

从解析的整数计算斐波那契数列

fibonacci : @n {
    if n <= 1 n else fibonacci(n - 1) + fibonacci(n - 2)
}

Int print($1, "=>", fibonacci($1))
$ tokay examples/fibonacci2.tok
0
0 => 0
1
1 => 1
2
2 => 1
3
3 => 2
4
4 => 3
5
5 => 5
6
6 => 8
7
7 => 13
8
8 => 21
9
9 => 34
10
10 => 55

文档

Tokay的主页tokay.dev提供了快速入门和文档的链接。文档源代码维护在一个单独的仓库中。

调试

调试有两种方法可以使用。

使用log-crate进行跟踪

对于Rust标准跟踪,使用env_logger功能。完整的跟踪只编译到调试可执行文件中,发布版本只提供警告级别及以上。

$ RUST_LOG=tokay=debug tokay

或者,可以通过设置TOKAY_LOG来为__main__程序激活跟踪。这用于在内部解析器已编译和执行,并解析了实际程序之后开始跟踪。TOKAY_LOG可以设置为任何RUST_LOG兼容的格式,因为它立即变成了RUST_LOG

$ TOKAY_LOG=tokay=debug tokay

使用TOKAY_DEBUGTOKAY_PARSER_DEBUG的内置AST和VM调试器

TOKAY_DEBUG设置在1到6的调试级别之间。这也可以通过使用tokay -dddd来实现,其中每个d都会增加调试级别。此外,还可以将TOKAY_INSPECT设置为要逐步跟踪的解析器名称(-前缀)的列表(TOKAY_DEBUG=6)。

级别 模式
0 无调试
1 打印构建的AST
2 打印最终的中间程序
3 打印编译的VM程序
4 打印VM执行跟踪
5 打印VM堆栈内容
6 VM指令调试器

在调试级别1中查看程序的解析AST

$ cargo run -q -- -d 'x = 42 print("Hello World " + x)'
main [start 1:1, end 1:33]
 sequence [start 1:1, end 1:33]
  assign_drop [start 1:1, end 1:8]
   lvalue [start 1:1, end 1:3]
    identifier [start 1:1, end 1:2] => "x"
   value_integer [start 1:5, end 1:7] => 42
  call [start 1:8, end 1:33]
   identifier [start 1:8, end 1:13] => "print"
   callarg [start 1:14, end 1:32]
    op_binary_add [start 1:14, end 1:32]
     value_string [start 1:14, end 1:28] => "Hello World "
     identifier [start 1:31, end 1:32] => "x"

TOKAY_PARSER_DEBUG 设置解析器的特定调试级别,该解析器在Tokay本身中实现,并作为编译器的一部分。这里只能识别 > 2 的级别,因为解析器的AST已内置于代码中。

以下是运行简单“Hello World”程序的VM调试器操作过程。

`$ TOKAY_INSPECT="__main__" cargo run -q -- 'print("Hello World")'`
__main__      --- Code ---
__main__       000 Offset(Offset { offset: 6, row: 1, col: 7 })
__main__      >001 LoadStatic(1)
__main__       002 Offset(Offset { offset: 0, row: 1, col: 1 })
__main__       003 CallStaticArg((2, 1))
__main__      --- Reader ---
__main__       offset=Offset { offset: 0, row: 1, col: 1 }
__main__       eof=false
__main__      --- Globals ---
__main__      --- Stack ---
__main__      --- Frames ---
__main__       000 capture: 0, reader: 0, fuse: None

__main__      ip = 1 state = Ok(Push([59d29e639f88] "Hello World" (10)))
__main__      --- Code ---
__main__       000 Offset(Offset { offset: 6, row: 1, col: 7 })
__main__       001 LoadStatic(1)
__main__       002 Offset(Offset { offset: 0, row: 1, col: 1 })
__main__      >003 CallStaticArg((2, 1))
__main__      --- Reader ---
__main__       offset=Offset { offset: 0, row: 1, col: 1 }
__main__       eof=false
__main__      --- Globals ---
__main__      --- Stack ---
__main__       000 [59d29e639f88] "Hello World" (10)
__main__      --- Frames ---
__main__       000 capture: 0, reader: 0, fuse: None

Hello World
__main__      ip = 3 state = Ok(Push([59d29e498fd8] void (10)))
__main__      exit state = Ok(Push([59d29e498fd8] void (10)))

托凯编程语言以亚洲的托凯壁虎(Gekko gecko)命名,它在夜晚高喊“token”。

托凯标志和图标由Timmytiefkuehl设计。
还可以查看tokay-artwork存储库中的不同版本的标志。

许可证

版权所有 © 2024 由Jan Max Meyer,Phorward软件技术公司。

托凯是MIT许可证下的免费软件。
请参阅LICENSE文件以获取详细信息。

依赖项

~8–16MB
~198K SLoC