#incremental #parser #d

tree-sitter-d

tree-sitter 解析库的 D 语法

4 个版本 (2 个破坏性更新)

0.6.1 2024年7月29日
0.6.0 2024年7月29日
0.5.1 2024年7月29日
0.3.8 2023年12月2日

#104文本编辑器

Download history 417/week @ 2024-07-27 17/week @ 2024-08-03

每月下载量:434

MIT 许可证

21MB
596K SLoC

C 593K SLoC // 0.0% comments JavaScript 2K SLoC // 0.1% comments Scheme 743 SLoC // 0.1% comments Rust 36 SLoC // 0.4% comments

tree-sitter-d

Tree Sitter 的 D 语法

Stand With Ukraine Build/test MIT License D Language

这是什么?

这是一个 D 语法,用于 Tree Sitter

截至本文撰写时,我相信它完全支持 D 2.108。

我相信这是截至本文撰写时最准确、最完整的 D 机器可读语法。事实上,它可能是唯一可以声称完全或几乎完全符合 D 2.108 的语法。

我们在 Weka 有大量的代码,这个语料库被用来测试和验证这个解析器。截至本文撰写时,它通过得很好,我没有听说过这个语法失败的任何突出异常。

此外,这个语法还与 DMD 源代码以及 DMD 测试用例进行了测试。

我希望这项工作不仅能在 Tree Sitter 的环境中使用,还能作为一个更正式、更准确的语法的起点,该语法反映了 DMD 引用编译器的实际行为。

语法偏差

这已被用于解析来自 DMD 自身的测试语料库。在这种情况下,有一些失败以几种形式出现

  • 语法或错误没有在 DMD 捕获的代码中(因为它们位于未编译的代码中,例如未实例化的模板)。这个语法不知道实例化或隐藏在条件编译后面的结构,并验证整个源代码文档。我认为这是一个特性,而不是错误。

  • 旧版 body 关键字的废弃使用(它不再是关键字)。如果你的源文件有这个问题,将 body 改为 do。你也可以直接删除这个词,因为在它出现的语法中它是完全可选的。

  • 带有中间多行注释的 #line 指令的病理情况。实际上没有任何东西会发出这样的破坏性语法,修复它需要显著更改词法分析器,而这对现实世界的利益几乎为零。(这个问题在 D 的新版本中已修复。)

  • 内联汇编基本上被视为一个没有实际验证的标记流。由于这是编译器和 CPU 特定的,因此在这里尝试添加它没有太多意义。(DMD 的内联汇编在 D 社区中并不广泛使用,甚至在该社区内部,因为它仅限于 x86。)

  • 现在已移除将 enum 作为返回类型的使用,遵循 D 2.105。如果这会在旧代码中产生错误,请使用 auto。(对于使用最新版 D 的用户来说,这实际上不是一种偏差。)

在某些方面,这种语法比 D 网站上正式指定的语法更严格。它有一些规则,会拒绝在 D 语法中看似合法但实际在语义分析过程中被编译器拒绝的构造。

我认为这种紧度的增加不会导致任何正确程序被拒绝,并且它减少了语言中的一些歧义。这主要涉及在仅允许单个值的情况下拒绝使用表达式列表(即 "expression1, expression2, ...")。(例如,你不能在 return 语句中使用逗号表达式。)

致谢

虽然在线资源(DGrammar项目的一部分和网站上指定的语法)存在许多问题,但它们仍为这项工作提供了一个极好的起点。没有这些资源,这将是无法完成的,或者至少是一个非常困难的项目。

此外,Discord 上的 D 社区在理解语法方面非常有帮助,并且对我的许多关于潜在语言构造的查询表示耐心,其中许多都是完全不合理的。

挑战和致谢

D 是一种极其复杂的(有些人可能会说过于复杂)语言,它缺乏一个准确的正式语法,现有的可机器读取的语法(DGrammar)存在错误或已过时。此外,规范也不是最新的,存在冲突和不准确性,这些都不反映实际的语言。

使用递归下降语法(具有 Tree Sitters GLR(1) 风格)的语法进行这项工作是一项了不起的成就。在语法本身中存在许多冲突和歧义。

因此,这主要是通过手工完成的,阅读语法规范,并进行大量实验。

在进行这项工作时,很容易识别出一些语言构造,有些人可能会认为语言可以轻易去掉,而不会失去其任何实际能力。

此外,这项工作还有一些我希望能避免的丑陋的 hacks — 其中很大一部分几乎肯定是我对 Tree Sitter 或 D 或两者都理解不足的结果。我欢迎那些更有知识的人的贡献或建议来改进这个。

未来方向

  • 最好是将这个项目移交给 D 或 Tree-Sitter 社区之一。这可能会促进最有可能从中受益的人们的偶然发现。

  • 额外的查询。本地查询等。再次,欢迎贡献!

  • 改进缩进或突出显示查询。

  • DDOC 支持。可以说 DDOC 是一种语言。

  • 扩展测试覆盖范围。这里有大量的测试用例,但我们真的需要一个更丰富的语料库。这是相当乏味的,但使用 -u 标志与 tree-sitter test 一起可以使用。

  • 还要突出显示测试覆盖范围!

性能

使用此语法解析 DMD 编译器的整个文件语料库(不包括负面测试)的 Tree Sitter 的试验运行仅用了 1.94 秒(1.86 用户,0.07 系统)。

这涉及到解析 3094 个文件,包含 834,637 行源代码。

这是每个文件平均 627 us,或每行代码 2.3 us。

换句话说,这个解析器每秒可以解析大约430K行的代码。

这次测试是在2020款MacBook Air上进行的,该设备配备了M1处理器和16GB RAM。

依赖项

~2.8–4MB
~72K SLoC