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/5 10:55:37

计算机Java毕设实战-基于springboot的扶贫助农系统及其小程序的实现基于springboot的助农农产品销售平台小程序【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/6/6 10:50:48

【TSP问题】基于改进的秃鹰算法IBES求解旅行商问题附Matlab代码

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

作者头像 李华
网站建设 2026/5/29 6:43:50

企业专线与光纤宽带对比及年费用说明

二者核心差异在于接入类型、服务等级和适用场景&#xff0c;并非绝对的优劣之分&#xff0c;需结合企业需求选择&#xff0c;以下是详细对比及 2026 年市场参考年费&#xff08;不含局域网设备及布线费用&#xff0c;仅线路费用&#xff09;&#xff1a;一、核心对比表格维度企…

作者头像 李华
网站建设 2026/6/8 19:18:32

基于java + vue房屋租赁管理系统(源码+数据库+文档)

房屋租赁管理 目录 基于springboot vue房屋租赁管理系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue房屋租赁管理系统 一、前言 博主介绍&…

作者头像 李华