Skip to content

Trees โ€‹

What you'll learn โ€‹

  • Recursive tree printing and iterative cursor traversal.

Complete example โ€‹

examples/tree_walk.zig (recursive, over a * (b + 2)):

zig
fn printNode(node: treesitter.Node, depth: usize) void {
    for (0..depth) |_| std.debug.print("  ", .{});
    std.debug.print("{s} [{d}, {d}] named={}\n", .{ node.nodeType(), node.startByte(), node.endByte(), node.isNamed() });
    var i: u32 = 0;
    while (i < node.childCount()) : (i += 1) printNode(node.child(i).?, depth + 1);
}

examples/tree_cursor.zig (iterative, over a + b * c) drives gotoFirstChild / gotoNextSibling / gotoParent with tree.cursor().

Running the examples โ€‹

sh
zig build run-tree_walk
zig build run-tree_cursor

Expected output โ€‹

tree_walk (abridged):

text
program [0, 11] named=true
  expression [0, 11] named=true
    term [0, 11] named=true
      term [0, 1] named=true
        factor [0, 1] named=true
          identifier [0, 1] named=true
      * [2, 3] named=false
      factor [4, 11] named=true
        ( [4, 5] named=false
        expression [5, 10] named=true
        ...
        ) [10, 11] named=false

tree_cursor:

text
depth=0 program [0, 9]
depth=1 expression [0, 9]
depth=2 expression [0, 1]
depth=3 term [0, 1]
depth=4 factor [0, 1]
depth=5 identifier [0, 1]
depth=2 + [2, 3]
depth=2 term [4, 9]
depth=3 term [4, 5]
depth=4 factor [4, 5]
depth=5 identifier [4, 5]
depth=3 * [6, 7]
depth=3 factor [8, 9]
depth=4 identifier [8, 9]

How it works โ€‹

Both traversals visit the same nodes: recursion is simplest for printing, while the cursor version runs in constant extra memory and can pause or snapshot with copy(). Notice how precedence shapes the tree โ€” b * c groups under one term, and the parenthesized (b + 2) nests a full expression inside a factor.

API used โ€‹

Released under the MIT License.