Skip to main content

Introduction

You can access every node in a syntax tree using the TSNode APIs described in Basic Parsing, but if you need to access a large number of nodes, the fastest way to do so is with a tree cursor. A cursor is a stateful object that allows you to walk a syntax tree with maximum efficiency by maintaining state about the current position in the tree.

Creating a Tree Cursor

You can initialize a cursor from any node:
The node you pass to the cursor is considered the root of the cursor. The cursor cannot walk outside this node. Going to the parent or any sibling of the root node will always return false.This has no unexpected effects if the given input node is the actual root node of the tree, but is something to keep in mind when using cursors constructed with a non-root node.

Moving the Cursor

Once you have a cursor, you can move it around the tree imperatively:
These methods return true if the cursor successfully moved and false if there was no node to move to.
bool
Move the cursor to the first child of its current node. Returns true if the cursor successfully moved, false if there were no children.
bool
Move the cursor to the next sibling of its current node. Returns true if the cursor successfully moved, false if there was no next sibling.
bool
Move the cursor to the previous sibling of its current node. Returns true if the cursor successfully moved, false if there was no previous sibling.
This function may be slower than goto_next_sibling due to how node positions are stored. In the worst case, this will need to iterate through all the children up to the previous sibling node to recalculate its position.
bool
Move the cursor to the parent of its current node. Returns true if the cursor successfully moved, false if there was no parent node (cursor was already on the root).

Retrieving the Current Node

You can always retrieve the cursor’s current node, as well as the field name associated with the current node:

Complete Example: Tree Traversal

Here’s a complete example that demonstrates how to traverse an entire tree using a cursor:

Advanced Cursor Operations

Jumping to a Specific Descendant

You can jump directly to the nth descendant of the cursor’s root:

Getting Depth Information

Position-based Navigation

You can jump to the first child that contains or starts after a given position:
These functions return the index of the child node if one was found, and -1 if no such child was found.

Copying and Resetting Cursors

Use ts_tree_cursor_reset_to to reset a cursor to the same position as another cursor. Unlike ts_tree_cursor_reset, this will not lose parent information and allows reusing already created cursors.

Performance Considerations

Tree cursors are significantly more efficient than TSNode operations when traversing large portions of the tree because:
  • Cursors maintain state about the current position, avoiding repeated lookups
  • Memory allocation is minimized
  • Navigation operations are optimized for sequential access
For accessing a small number of nodes, the TSNode API is more convenient and sufficient.
The goto_previous_sibling operation may be slower than goto_next_sibling because node positions are stored in a way that’s optimized for forward traversal. In the worst case, it needs to iterate through all children up to the previous sibling to recalculate its position.If you need to traverse siblings in reverse order, consider collecting them in forward order first, then iterating the collection in reverse.
Remember that cursors are scoped to the node they were created from. If you create a cursor from a non-root node, the cursor cannot navigate outside that subtree. This is useful for limiting traversal to a specific portion of the tree.

Next Steps

Pattern Matching

Learn how to query syntax trees with patterns

Static Node Types

Generate type information for your language