Skip to content

Navigating Nodes โ€‹

What you'll learn โ€‹

  • Child, parent, and sibling navigation without allocation.
  • Field access and byte-range descendant lookup.

Complete example โ€‹

zig
var tree = try parser.parseString("1 + x");
defer tree.deinit();

const expr = tree.rootNode().child(0).?; // "expression"
const left = expr.namedChild(0).?; // "1"
const op = expr.child(1).?; // "+"
const right = expr.childByFieldName("right").?; // "x"

try std.testing.expect(left.parent().?.eql(expr));
try std.testing.expect(left.nextSibling().?.eql(op));
try std.testing.expect(left.nextNamedSibling().?.eql(right));

const found = tree.rootNode().descendantForByteRange(4, 5).?;

How it works โ€‹

  • child(i) counts every child including punctuation; namedChild(i) skips anonymous tokens.
  • parent() returns null at the root; siblings walk the parent's child list.
  • childByFieldName("left") consults the language's field map for the node's production id โ€” see Fields.
  • descendantForByteRange descends to the smallest node covering a range; namedDescendantForByteRange then walks up to the nearest named node.

Performance considerations โ€‹

All navigation is index arithmetic over the tree's pools โ€” no heap allocation, no tree copying.

API used โ€‹

  • Node โ€” full method table.

Released under the MIT License.