Content
AST(Abstract Syntax Tree,抽象语法树)是把源代码按语法结构解析后得到的树状表示。它不是源代码的文本副本,而是对代码结构关系的抽象表达,因此特别适合做编译、转译、静态分析和代码修改。只要工具需要“理解代码在说什么”,而不是只对字符串做替换,AST 往往就是核心中间层。
Acceptance
AST (Abstract Syntax Tree) 是源代码的树形结构表示。编译器/解释器将代码文本解析(parse)为 AST 后,后续的分析、转换、生成都基于这棵树操作,而非直接操作字符串。[1]
示例: const x = 1 + 2 解析为:
VariableDeclaration
└── VariableDeclarator
├── id: Identifier (x)
└── init: BinaryExpression
├── left: NumericLiteral (1)
├── operator: +
└── right: NumericLiteral (2)
几乎所有代码分析工具都基于 AST:
- Babel: 读 AST → 转换节点 → 输出新代码(如 TSX → JS)
- ESLint: 读 AST → 遍历节点 → 逐规则检查
- Prettier: 读 AST → 丢弃原格式 → 从 AST 重新打印
- Biome: 同 ESLint + Prettier,但用 Rust 自研解析器,一次解析
Question
- AST 和 CST (Concrete Syntax Tree) 的区别是什么?为什么大多数工具选择 AST 而非 CST?
- Babel 的 plugin 开发本质上就是”写一个 AST visitor”——visitor 模式在这里解决了什么问题?
- 如果两段代码功能相同但写法不同(如
if/elsevsternary),它们的 AST 是否相同?这对代码分析意味着什么?
See Also
YoYo’s Note
AST 是代码工具链的”通用语言”——不管你想做什么(检查规范、格式化、类型转换、压缩),第一步都是把代码变成树。这就像你想分析一篇文章,先要把它拆成”段落→句子→词语”的结构,而不是逐字符扫描。
Babel、ESLint、Prettier 三个工具各自独立解析 AST,这意味着同一份代码被解析了三次——Biome 的核心优势之一就是只解析一次,用同一棵树同时做 lint 和 format。
Answer
AST 和 CST (Concrete Syntax Tree) 的区别是什么?为什么大多数工具选择 AST 而非 CST?
CST 更贴近源代码表面形式,会保留括号、分号、空白等具体语法细节,而 AST 会把这些冗余细节抽掉,只保留对语义和结构真正重要的节点关系。大多数分析和转换工具选择 AST,是因为它更稳定、更简洁,更适合表达“代码在做什么”而不是“代码长什么样”。
Babel 的 plugin 开发本质上就是”写一个 AST visitor”——visitor 模式在这里解决了什么问题?
visitor 模式把“遍历树”与“在某类节点上做什么”拆开了。插件作者不需要自己手写整棵树的遍历逻辑,只要声明当遇到 Identifier、CallExpression 这类节点时该做什么,框架就会负责把这些处理器挂到正确的位置上。这样代码转换会更模块化,也更容易组合。
如果两段代码功能相同但写法不同(如
if/elsevsternary),它们的 AST 是否相同?这对代码分析意味着什么?
通常不会相同,因为 AST 描述的是语法结构而不是“抽象功能等价性”。if/else 和 ternary 在人看来可能表达同一意图,但在语法树里是不同节点形态。这意味着基于 AST 的工具天然擅长做语法级分析和转换,但如果要判断更高层的语义等价,就需要额外的数据流、控制流或语义分析。
- MindGym M0 session (2026-04-12/13) — 讲解 ESLint/Prettier/Biome 时引入 AST 概念 ↩
- https://astexplorer.net — 在线 AST 可视化工具
- Babel Plugin Handbook — visitor 模式与 AST 转换说明
- 编译原理教材 / AST 与 CST 对比资料