Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

遍历节点示例

ASTVisitor 使用示例

ASTVisitor 是 SyntaxTreeNode 访问器的基类。

使用方式:

  1. 继承 ASTVisitor 并重写 preAction / postAction 或特定 visit* 方法;
  2. 调用 walk(root) 从任意节点开始遍历;
  3. 通过返回 PreActionModePostActionMode 控制遍历流程。

假设我们有一段需要分析的代码:

package a

main(){
  var expr = 1 + 2
  println(expr)
  var nextExpr = expr + 1
  println(nextExpr)
}

下面演示如何继承 ASTVisitor,在遍历过程中统计所有 BinaryExpr 节点,并在遇到第一个 CallExpr 后立即停止遍历:

import stdx.syntax.*

// 1. 继承 ASTVisitor
public class BinaryCounter <: ASTVisitor {
    public var count = 0

    // 2. 重写 preAction,只在进入节点前做判断
    public override func preAction(node: SyntaxTreeNode): PreActionMode {
        match (node) {
            // 遇到 BinaryExpr 时计数 +1 并继续
            case _: BinaryExpr =>
                count += 1
                return PreActionMode.Continue

            // 遇到 CallExpr 立即停止整个遍历
            case _: CallExpr =>
                println("Found CallExpr, stop traversal")
                return PreActionMode.Stop

            // 其它节点保持默认行为
            case _ => PreActionMode.Continue
        }
    }
}

// 3. 使用示例
main() {
    let root = parseFile("example.cj")

    let counter = BinaryCounter()
    counter.walk(root.node.getOrThrow())          // 开始遍历

    println("Total BinaryExpr count: ${counter.count}")
}

运行流程:

  1. walk(root) 从根节点开始深度优先遍历;
  2. 每进入一个节点会调用 preAction
    • 如果是 BinaryExpr,计数器自增并返回 CONTINUE 继续;
    • 如果是 CallExpr,返回 STOP,遍历立即终止;
  3. 最终打印统计结果。

运行结果:

Found CallExpr, stop traversal
Total BinaryExpr count: 1