☰
仓颉 std.ast 绑定模式节点 VarPattern:语法树中的变量绑定模式解析与实战
2026/10/15 18:05:50 网站建设 项目流程
  • 人工智能
  • AI 技能
  • 文档
  • 开发工具

【免费下载链接】DocAgent

项目地址:https://gitcode.com/Cangjie-SIG/DocAgent
点击查看免费下载

VarPattern 是仓颉(Cangjie)标准库std.ast中表示"绑定模式"的语法树节点,对应模式匹配中把匹配结果绑定到标识符的语法结构,例如for (i in 1..10)中的i。本文基于 std.ast 包 的官方类文档与源码级声明,完整讲解 VarPattern 的类定义、两个构造函数、identifier成员属性的读写规则,并结合 VarDecl、ForInExpr、MatchCase 等节点说明它的实际挂载位置,最后给出基于parsePattern解析与Visitor遍历的实战示例。读完本文,你将能识别并操作仓颉 AST 中任意一处"变量绑定模式"节点。

VarPattern 是什么:绑定模式节点

在仓颉的模式匹配体系中,模式(Pattern)用于描述"待匹配的数据应满足的结构",而绑定模式(binding pattern)是最基础的一类:它用一个合法的标识符将匹配到的值绑定到该名字上,后续代码可以直接引用这个名字。

按照 ast_package_classes.md 中的类说明,VarPattern 表示绑定模式节点,使用一个合法的标识符表示,官方给出的典型例子是:

for (i in 1..10)

其中i就是循环迭代表达式中被绑定到当前元素的标识符,对应 AST 中一个VarPattern节点。

绑定模式出现的位置非常广泛:for-in循环的迭代表达式、match分支、let解构、变量声明等凡是"按模式取名字"的场景都可能出现它的身影,因此理解 VarPattern 是使用std.ast做源码解析、宏处理和代码分析的基础。

类声明与继承关系

在 ast_package_classes.md 中,VarPattern 的完整类声明为:

public class VarPattern <: Pattern { public init() public init(identifier: Token) }

关键信息如下:

  • 父类型:Pattern。Pattern是public open class Pattern <: Node,即所有模式匹配节点的父类,它又继承自 Node(所有仓颉语法树节点的父类)。因此 VarPattern 天然具备 Node 的通用能力(如dump()、traverse(visitor)等)。
  • 可构造性:与某些只能由解析器生成的节点不同,VarPattern 是public类且提供了公开构造函数,开发者既可以"读"(从解析结果中取出),也可以"写"(手工构造后插入 AST)。

在std.ast的模式节点家族中,与 VarPattern 同属 Pattern 子类的还包括:ConstPattern(常量模式)、VarOrEnumPattern(标识符为Enum构造器的模式)、WildcardPattern(通配符_)、TuplePattern(元组模式)、TypePattern(类型模式)、EnumPattern(enum 模式)与 ExceptTypePattern(异常模式)等。后面会专门辨析它们之间的区分。

构造函数:两种创建方式

VarPattern 提供两个重载的构造函数,参见 ast_package_classes.md 的构造函数说明:

原型说明
init()构造一个默认的 VarPattern 对象。
init(identifier: Token)根据标识符构造一个 VarPattern 对象。

init():默认构造

public init()

创建一个"空壳"的绑定模式节点:此时节点内没有绑定任何标识符,需要后续通过identifier属性(见下一节)赋值后才能成为一个语义完整的模式节点。这种"先构造、后填充"的方式通常用于程序化构建 AST(例如宏展开时动态生成绑定)。

init(identifier: Token):根据标识符构造

public init(identifier: Token)

直接传入一个表示绑定名的词法单元来构造节点。参数说明(摘自类文档):

  • identifier: Token—— 将要构造为 VarPattern 的词法单元,即绑定标识符对应的 Token。

需要特别注意的是该构造函数可能抛出异常(见 ASTException 类说明):

  • ASTException—— 当输入的词法单元无法构造为 VarPattern 节点时抛出。

也就是说,并非任意Token都能成为合法的绑定模式:如果传入的 Token 不是合法的标识符词法单元(例如传入操作符或关键字),解析构造逻辑会判定无法构成 VarPattern 并抛出ASTException。因此在实际编码中,应当优先使用TokenKind.IDENTIFIER类型的词法单元来构造。

成员属性 identifier:读写绑定标识符

VarPattern 对外暴露的唯一成员属性是identifier,声明如下(见 ast_package_classes.md 的属性说明):

public mut prop identifier: Token

语义:获取或设置 VarPattern 节点中标识符的词法单元。

由于是mut prop(可变属性),它同时支持读取和写入:

// 读取绑定名 let name = varPattern.identifier // 改写绑定名 varPattern.identifier = Token(IDENTIFIER, "newName")

属性类型为 Token,即词法单元结构体。Token 是构成仓颉源码的最小单元,包含以下关键成员(详见 Token_struct.md):

成员类型含义
kindTokenKind词法单元的类型(关键字、标识符、运算符、常量值等)。
posPosition词法单元在源码中的位置信息(文件 ID、行号、列号)。
valueString词法单元的字面量值。
delimiterNumUInt16多行字符串的#符号个数(默认 1)。

因此对于一个解析自真实源码的 VarPattern,identifier.kind通常为IDENTIFIER、identifier.value就是绑定名本身(如i)、identifier.pos记录了该名字在源文件中的行列位置——这对做源码级诊断和定位非常有用。

VarPattern 在 AST 中的典型挂载场景

VarPattern 作为 Pattern 的子类,会被"持有模式"的各种上层节点引用。从std.ast的类定义可以确认以下几个典型的挂载位置:

变量定义节点 VarDecl

VarDecl 表示变量定义节点,其成员属性中包含:

public mut prop pattern: Pattern

即变量声明的模式部分。例如解析var a : Int64时,pattern就是绑定标识符a的 VarPattern 节点。在 parse.md 示例的 dump 输出 中可以看到,var a: Int32被解析为 VarDecl 后,其identifier(值为a、kind: IDENTIFIER)即对应这个绑定。

for-in 循环节点 ForInExpr

ForInExpr 表示for-in表达式,其成员属性:

public mut prop pattern: Pattern

对应官方文档中 VarPattern 的典型例子for (i in 1..10)里的i。循环体每轮迭代都会把当前元素绑定到该模式命名的变量上。

let 解构节点 LetPatternExpr

LetPatternExpr 表示let声明的解构匹配节点:

public mut prop pattern: Pattern

对应let关键字之后的 pattern,当解构的是单个标识符(如let x <- foo())时,该 pattern 即为 VarPattern。

match 分支节点 MatchCase

MatchCase 表示match表达式中的一个case节点:

public mut prop patterns: ArrayList<Pattern>

case后的 pattern 集合中,绑定模式就是 VarPattern。例如case i => ...会把匹配值绑定到i。此外 MatchExpr 通过matchCases持有多个 MatchCase,形成完整的模式匹配表达式。

与相近模式节点的辨析

std.ast中几个"单标识符形态"的模式节点容易混淆,从各自的类说明可以清晰区分:

节点语义典型形态
VarPattern绑定模式:把匹配值绑定到一个合法标识符for (i in 1..10)中的i
VarOrEnumPattern标识符解析为Enum构造器时的模式case RED中的RED(RED 是枚举构造器)
ConstPattern常量模式:匹配字面量常量case 1 => 0中的1
WildcardPattern通配符模式:匹配任意值但不绑定_

判断要点:模式的名字若会被"绑定复用",则是 VarPattern;若指向枚举构造器(按值比较是否命中),则是 VarOrEnumPattern;若是字面量常量,则是 ConstPattern;若用_忽略匹配值,则是 WildcardPattern。

实战:解析、遍历与构造 VarPattern

用 parsePattern 解析出 VarPattern

std.ast提供了解析函数parsePattern(Tokens)(见 ast_package_funcs.md),可将一组词法单元解析为 Pattern 节点。结合quote与类型转换(模式参考 parse.md 示例 的as ClassDecl写法),可以这样拿到 VarPattern:

import std.ast.* main() { let input: Tokens = quote(i) // 将源码片段转为词法单元 let pattern = parsePattern(input) // 解析出一个 Pattern 节点 var varPattern = match (pattern as VarPattern) { // 类型收敛到 VarPattern case Some(v) => v case None => throw Exception() } println("binding name is ${varPattern.identifier.value}") 0 }

其中varPattern.identifier.value将输出绑定名(此处为i),identifier.pos则记录了它的源码位置。

通过 Visitor 遍历包含 VarPattern 的节点

在 traverse.md 示例 中,展示了继承 Visitor 并重写visit(varDecl: VarDecl)来扫描变量声明节点的做法。同理,若要收集某个作用域内所有绑定模式的名字,可以重写对模式相关节点的访问逻辑,通过varDecl.pattern(或forInExpr.pattern、matchCase.patterns)逐层下钻,判断其动态类型是否为 VarPattern,再读取identifier.value:

class BindingCollector <: Visitor { public var bindings = ArrayList<String>() override public func visit(varDecl: VarDecl) { // 从声明节点的 pattern 中取绑定名 if (varDecl.pattern is VarPattern) { let vp = varDecl.pattern as VarPattern bindings.add(vp.identifier.value) } return } }

说明:以上基于 Visitor 与 VarDecl.pattern 的公开接口推导,具体遍历粒度以所用std.ast版本的 Visitor 默认实现为准。

手工构造并修改绑定模式

宏展开或代码生成场景下,往往需要程序化创建绑定模式。两种构造方式结合identifier属性即可完成:

import std.ast.* main() { // 方式一:默认构造后写入标识符 let p1 = VarPattern() p1.identifier = Token(IDENTIFIER, "item") // 方式二:直接以标识符词法单元构造 let p2 = VarPattern(Token(IDENTIFIER, "item")) println("${p1.identifier.value} ${p2.identifier.value}") 0 }

Token(IDENTIFIER, "item")使用了 Token 的构造函数init(kind: TokenKind, value: String),其中IDENTIFIER是 TokenKind 中表示标识符的枚举值(在 parse.md 的 dump 输出 中可见kind: IDENTIFIER的实例)。构造完成后,即可把该 VarPattern 挂到 VarDecl 的pattern或 ForInExpr 的pattern上,参与更大 AST 的组装。

异常与使用注意事项

围绕 VarPattern 的使用,需要留意以下几点(依据来自类文档与异常类定义):

  1. 构造失败会抛 ASTException:init(identifier: Token)在输入的词法单元无法构成绑定模式时会抛出 ASTException,建议构造前确认 Token 的类型为IDENTIFIER。
  2. identifier 属性语义要求合法标识符:identifier属性用于读写"标识符的词法单元",写入的值应当与绑定模式的语义一致(合法标识符),否则可能影响后续解析或宏展开的正确性。
  3. 解析失败场景:使用parsePattern等解析函数时,若输入词法单元无法解析为合法模式,会抛出 ParseASTException(std.ast的解析异常类),该异常与 ASTException 同属std.ast的异常体系,捕获时可按需分别处理。
  4. 绑定模式不是"表达式":VarPattern 继承自 Pattern 而非 Expr,它只描述"名字绑定"这一结构,本身不参与求值,切勿在需要表达式的字段(如VarDecl.expr)中直接挂入。

综上,VarPattern 是仓颉 AST 中连接"模式匹配语法"与"标识符绑定"的关键节点:读懂它,就能在for、match、let、变量声明等几乎所有涉及绑定的语法场景中,精确地解析、遍历和生成绑定名字,这是编写宏、静态分析器与代码生成工具的基础能力之一。建议进一步阅读 std.ast 包概览 了解完整节点体系,并结合 parse.md、operate.md、traverse.md 三个样例加深对 AST 解析与操作的整体理解。

  • 人工智能
  • AI 技能
  • 文档
  • 开发工具

【免费下载链接】DocAgent

项目地址:https://gitcode.com/Cangjie-SIG/DocAgent
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询