Skip to content

Memory Model โ€‹

Client owns an allocator (e.g. std.heap.DebugAllocator)
Parser.init(allocator) borrows it for the parser lifetime
parseString copies source bytes into the new Tree
Tree owns its node pool, child index buffer, and source copy
tree.cursor() / parser.queryCursor() inherit the stored allocator
Every deinit releases exactly what its object owns

The handoff rule โ€‹

The client allocator enters the library at exactly one place โ€” Parser.init โ€” and is then inherited: trees inherit the parser's allocator, cursors inherit their tree's or parser's, queries inherit the parser's via the convenience constructors. Standalone constructors take an explicit allocator for code that has no parent object to inherit from.

Ownership summary โ€‹

ObjectOwnsBorrows
Parserstacks, scratch, candidates, rangesthe allocator itself, the Language tables
Treesource copy, node pool, child indicesthe allocator, the Language
Nodenothingits tree
TreeCursorpath stackits tree
Querypatterns, captures, predicate argsthe allocator, the Language
QueryCursormatch liststhe allocator
Range slicenothing (caller-owned)โ€”

Language table data is always borrowed โ€” grammars are typically comptime-known statics, and the runtime never frees them.

Released under the MIT License.