news 2026/9/8 2:32:18

请举例 AST 的更多真实例子

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
请举例 AST 的更多真实例子

请举例 AST 的更多真实例子

下面给你几个更真实、更接近解析器输出的 AST 例子(我会用“代码片段 → AST(树形/括号式)→ 可能的序列化”来展示)。为了可读性,我会给精简但结构真实的 AST(类似 Tree-sitter / ESTree / Python ast 模块的风格),并标出你关心的点:raw AST 往往只有类型/位置,增强后才更像“可读语义图”


例子 1:Python 赋值 + 二元运算 + 调用

代码

total = add(x, 2) + y

raw AST(括号式,接近 Pythonast.dump/ Tree-sitter 结构)

(Module (Assign targets=[(Name id='total' ctx=Store())] value=(BinOp left=(Call func=(Name id='add' ctx=Load()) args=[(Name id='x' ctx=Load()), (Constant value=2)] ) op=Add() right=(Name id='y' ctx=Load()) ) ) )

关键观察

  • 这里其实已经含有id='total'/'add'/'x'/'y',但很多解析器/标准化 AST可能会把这些 leaf 值抽象成Identifier类型,或只在 token 表里存(AST 节点本身只有 span)。

  • 运算符常常是一个节点Add()或 token,而不是文本"+"


例子 2:Python if + 比较 + 返回(带 else)

代码

def clamp(x, lo, hi): if x < lo: return lo elif x > hi: return hi return x

AST(更完整一点)

(Module (Assign targets=[(Name id='total' ctx=Store())] value=(BinOp left=(Call func=(Name id='add' ctx=Load()) args=[(Name id='x' ctx=Load()), (Constant value=2)] ) op=Add() right=(Name id='y' ctx=Load()) ) ) )

(Module (FunctionDef name='clamp' args=(arguments args=[x,lo,hi]) body=[ (If test=(Compare left=(Name 'x') ops=[Lt()] comparators=[(Name 'lo')]) body=[(Return (Name 'lo'))] orelse=[ (If test=(Compare left=(Name 'x') ops=[Gt()] comparators=[(Name 'hi')]) body=[(Return (Name 'hi'))] orelse=[] ) ] ), (Return (Name 'x')) ] ) )

关键观察

  • “elif” 在 AST 里常常表现成If嵌套在orelse中(这就是结构信息:树上位置决定语义)。

  • 如果你把它“纯前序 token 化”成一串If Compare Name Lt Name Return ...,模型很容易把哪个 return 属于哪个分支搞混。


例子 3:JavaScript(ESTree 风格)箭头函数 + map + 对象字面量

代码

const res = arr.map(x => ({k: x, v: x * 2}));

raw AST(接近 ESTree / Babel AST)

{ "type": "VariableDeclaration", "kind": "const", "declarations": [{ "type": "VariableDeclarator", "id": {"type": "Identifier", "name": "res"}, "init": { "type": "CallExpression", "callee": { "type": "MemberExpression", "object": {"type": "Identifier", "name": "arr"}, "property": {"type": "Identifier", "name": "map"}, "computed": false }, "arguments": [{ "type": "ArrowFunctionExpression", "params": [{"type": "Identifier", "name": "x"}], "body": { "type": "ObjectExpression", "properties": [ {"type": "Property", "key": {"type": "Identifier", "name": "k"}, "value": {"type": "Identifier", "name": "x"}}, {"type": "Property", "key": {"type": "Identifier", "name": "v"}, "value": {"type": "BinaryExpression", "operator": "*", "left": {"type": "Identifier", "name": "x"}, "right": {"type": "NumericLiteral", "value": 2}}} ] } }] } }] }

关键观察

  • JS AST 通常非常“语义化”:BinaryExpression.operator="*"MemberExpressionObjectExpression

  • 但也会很“长”:大量结构包装节点,序列化会爆 token(尤其大函数)。


例子 4:C / C++ 风格:for 循环 + 数组索引 + 累加

代码

for (int i = 0; i < n; i++) { sum += a[i]; }

AST(接近 Clang AST / Tree-sitter C 的结构)

(ForStatement init=(Declaration (InitDeclarator declarator=(Identifier "i") value=(NumberLiteral "0") ) ) condition=(BinaryExpression left=(Identifier "i") operator="<" right=(Identifier "n") ) update=(UpdateExpression operator="++" argument=(Identifier "i") ) body=(CompoundStatement (ExpressionStatement (AssignmentExpression left=(Identifier "sum") operator="+=" right=(SubscriptExpression object=(Identifier "a") index=(Identifier "i") ) ) ) ) )

关键观察

  • a[i]不是Call,而是SubscriptExpression/ArraySubscriptExpr一类节点。

  • 很多解析器会把operator当 token,而不是节点;也有的会把operator变成子节点。


例子 5:Java:try-catch + throw + 方法调用链

代码

try { return service.get(id).toString(); } catch (Exception e) { throw new RuntimeException(e); }

AST(接近 JavaParser / Eclipse JDT)

(TryStatement tryBlock=(Block (ReturnStatement expression=(MethodInvocation name="toString" scope=(MethodInvocation name="get" scope=(NameExpr "service") args=[(NameExpr "id")] ) ) ) ) catchClauses=[ (CatchClause parameter=(Parameter type="Exception" name="e") body=(Block (ThrowStatement expression=(ObjectCreationExpr type="RuntimeException" args=[(NameExpr "e")] ) ) ) ) ] )

关键观察

  • 链式调用service.get(id).toString()在 AST 里是嵌套 MethodInvocation

  • catch (Exception e)是一个带 parameter 的节点,属于TryStatement的子列表。


例子 6:未经增强的 AST(更“原始/抽象”)会长什么样?

很多论文里说的 “raw AST” 指的是:AST 节点只有类型/结构,叶子节点的具体值(标识符名、数字)不在 AST node 内,而在 tokenizer/token-table 里。那它可能更像下面这样:

代码

balance = 0

raw AST(极抽象版本:只剩类型)

(assignment_statement (left (identifier)) (right (integer)) )

这种形式当然也能序列化给 LLM:

assignment_statement left identifier right integer

但它对“总结/注释/意图理解”很不友好:模型不知道 identifier 是balance,integer 是0

而增强后的版本会更像:

(assignment_statement (left (variable:balance)) (right (integer:0)) )

信息密度立刻高很多。


你如果要“更真实”:我可以按你指定语言/解析器输出格式给

你可以告诉我你想看哪种(不用你再解释用途,我直接按常见格式给):

  1. Pythonast.dump()风格

  2. Tree-sitter S-expression 风格(很多论文用这个)

  3. JavaScript ESTree JSON(Babel/Acorn)

  4. Clang AST(C/C++)

  5. 自定义序列化:SBT / Preorder / NIT(带 children id)

你回一句:

  • “给我 3 个 Python 例子,按 tree-sitter 风格 + NIT 序列化”

  • “给我 JS 的 ESTree JSON + 对应的 NIT 序列”

我就可以把每个例子都配上树 → 序列的完整对照。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/3 0:01:03

【YOLOv8多模态涨点改进】独家创新首发 | TGRS 2025 | 引入CDFIM跨模态差异特征交互模块,通过差异特征提取和融合增强机制,减少了冗余信息,显著提升了小目标的检测精度,高效涨点改进

一、本文介绍 🔥本文给大家介绍使用 CDFIM跨模态差异特征交互模块改进 YOLOv8 多模态目标检测,通过有效的差异特征提取和增强,显著提升了小目标的检测精度,特别是在复杂背景和低对比度环境下。该模块通过残差加法和通道与空间注意力机制,增强了可见光与红外模态之间的互…

作者头像 李华
网站建设 2026/9/5 4:55:03

Perl 运算符

Perl 运算符 概述 Perl 是一种强大的编程语言,广泛应用于文本处理、系统管理、网络编程等多个领域。在 Perl 中,运算符是执行计算和比较的基础元素。本文将详细介绍 Perl 中常用的运算符及其用法。 运算符分类 Perl 中的运算符主要分为以下几类: 算术运算符:用于执行数…

作者头像 李华
网站建设 2026/9/7 10:36:07

2026年最新《三角洲行动下载与安装全指南》:高速获取、安全配置与性能优化全流程

前言 在近两年FPS类游戏的热度中&#xff0c;《三角洲行动》凭借高质量的画面表现、战术协同设计和端游级射击手感成为众多玩家关注的焦点。相比以往需要复杂配置的硬核射击作品&#xff0c;本作在下载安装上的门槛已大幅降低。本文将为你系统讲解三角洲行动下载的完整流程&am…

作者头像 李华
网站建设 2026/9/7 20:38:51

Claude Code + Skill 的使用技巧

前两天&#xff0c;Boris再次公开了Claude Code团队的10个内部技巧。这次的分享比年初那次更硬核&#xff0c;干货浓度高到离谱。我花了整整一个下午消化这些内容&#xff0c;又在实战中验证了几天&#xff0c;决定把最有价值的部分提炼出来&#xff0c;分享给正在使用或准备入…

作者头像 李华