news 2026/6/10 11:34:57

请举例 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/6/10 10:04:41

数据中台在大数据领域的实时数据集成策略

数据中台在大数据领域的实时数据集成策略 关键词:数据中台、实时数据集成、大数据、流式计算、数据仓库、ETL、CDC 摘要:本文深入探讨了数据中台在大数据环境下的实时数据集成策略。我们将从数据中台的基本概念出发,分析实时数据集成的技术挑战,详细介绍主流实现方案,并通…

作者头像 李华
网站建设 2026/6/10 12:33:28

【无人机检测】无人机智能停车位检测系统附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和…

作者头像 李华
网站建设 2026/6/10 12:35:43

网络安全学习网站

很多想自学黑客技术的朋友&#xff0c;很容易走错方向。作为一名11年的资深白帽&#xff0c;给大家推荐7个我自己常用的学习网站&#xff0c;并且都是合法的学习网站&#xff0c;能带你了解到黑客有关的技术&#xff0c;视频&#xff0c;电子书&#xff0c;实践&#xff0c;工具…

作者头像 李华
网站建设 2026/6/10 12:34:18

116道网络安全面试真题(附答案),建议收藏!

116道网络安全面试真题&#xff08;附答案&#xff09;&#xff0c;建议收藏&#xff01; 随着国家对网络安全的重视度&#xff0c;促使这个职业也变得炙手可热&#xff0c;越来越多的年轻人为进入安全领域在做准备。 数以百计的面试&#xff0c;为何迟迟无法顺利入职&#x…

作者头像 李华
网站建设 2026/6/10 3:34:27

GBASE南大通用技术分享:GBase 8a数据库控制流函数简介(四)

南大通用GBase 8a数据库控制流函数IFNULL(expr1,expr2)&#xff1a;语法 IFNULL(expr1,expr2)函数说明 如果 expr1 不为 NULL&#xff0c;则 IFNULL()的返回值为 expr1&#xff0c;否则其返回值为 expr2。 IFNULL()的返回值是数字或是字符串&#xff0c; 具体情况取决于使用它的…

作者头像 李华