Concrete Syntax Tree 具体语法树
在阅读一个用 LLM 给 Python 加 docstring 的工具llm-docsmith
的创作笔记1时,首次了解到了 Concrete Syntax Tree 具体语法树这个概念(之前只知道 AST 抽象语法树)。
搜索了一些相关资料,看起来可以按照抽象层级从低到高这样排序:
- 源代码:抽象层级最低,信息最丰富
- CST:抽象层级略高(有语言 grammer 能有的全部信息),信息较为丰富,但是视解析器可能丢失一些语言 grammer 没有的信息(例如缩进)
- AST:抽象层级最高,只含有相对必要的信息(例如
(a+b)
的左右括号在 CST 里存在,但是 AST 里没有,因为可以通过 AST 树上节点的父子关系推断出来。)
大部分时候我们所需要的是 AST (例如实际 eval 某个程序),解析器实现则基本可以分为(1)源代码->AST,(2)源代码->CST->AST两种。(注意 CST->AST 可能不是 trivial 的,需要一些复杂的转换操作。)但是如果你想重构/格式化代码而不影响其他现存代码,CST 里包含的丰富信息就很重要了,这意味着可以在修改树结构之后,再重新用 CST 生成源代码,且对于未修改的 CST 部分,生成的代码和原始输入的代码(基本)一致。
对于 Python,libcst2 实现了最精确的解析,可以无损从 CST 转换为原始代码(含缩进/空格/注释);对于其他语言,则可以考虑用通用的 tree-sitter3,其实现了多个语言的 CST 解析器(但我似乎还没太弄清楚是否能像 libcst 那样精确)。
相关链接:
- https://eli.thegreenplace.net/2009/02/16/abstract-vs-concrete-syntax-trees/ (一篇 AST vs CST 的深入对比)
- https://zed.dev/blog/syntax-aware-editing (tree-sitter 的作者也是 zed 的作者?)
- https://marketplace.visualstudio.com/items?itemName=ms-vscode.anycode (在语言服务不可用的时候,VS Code 会用 tree-sitter 来实现基本的语言理解,支持 outline,jump to symbol 等功能)
-
llm-docsmith blog: https://mathpn.com/posts/llm-docsmith/ ↩︎
-
libcst: https://libcst.readthedocs.io/en/latest/why_libcst.html ↩︎
-
tree-sitter: https://tree-sitter.github.io/tree-sitter/7-playground.html ↩︎