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 在 文本编辑器
每月下载量:434
21MB
596K SLoC
tree-sitter-d
Tree Sitter 的 D 语法
这是什么?
这是一个 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