pub struct NodeArena { /* private fields */ }Expand description
Owns a parsed tree and the handles issued against it.
Implementations§
Source§impl NodeArena
impl NodeArena
Sourcepub const ROOT: u32 = 0
pub const ROOT: u32 = 0
The root node’s handle.
A constant rather than a method: the root is interned first, so it is always zero.
Sourcepub fn new(tree: Tree, source: String) -> NodeArena
pub fn new(tree: Tree, source: String) -> NodeArena
Take ownership of a tree and its source.
The root is interned as handle 0, so rule code always has somewhere to start.
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
How many handles have been issued. Interning is lazy, so this reflects how much of the tree a rule actually touched.
Sourcepub fn kind(&self, handle: u32) -> Option<&'static str>
pub fn kind(&self, handle: u32) -> Option<&'static str>
The node’s kind, as the grammar names it.
Sourcepub fn is_named(&self, handle: u32) -> Option<bool>
pub fn is_named(&self, handle: u32) -> Option<bool>
Whether the node is named, as opposed to an anonymous token such as a bracket.
Sourcepub fn position(&self, handle: u32) -> Option<(u32, u32)>
pub fn position(&self, handle: u32) -> Option<(u32, u32)>
One-based line and column of the node’s start.
Sourcepub fn byte_range(&self, handle: u32) -> Option<(usize, usize)>
pub fn byte_range(&self, handle: u32) -> Option<(usize, usize)>
The node’s byte range in the source.
Sourcepub fn resolve_binding(
&self,
handle: u32,
resolver: &dyn BindingResolver,
) -> Option<Binding>
pub fn resolve_binding( &self, handle: u32, resolver: &dyn BindingResolver, ) -> Option<Binding>
What the identifier at a handle refers to.
Takes the resolver rather than holding one so the arena stays language-agnostic,
and does the work internally so the borrowed Node never escapes.
Sourcepub fn is_shadowed(&self, handle: u32, resolver: &dyn BindingResolver) -> bool
pub fn is_shadowed(&self, handle: u32, resolver: &dyn BindingResolver) -> bool
Whether the identifier at a handle shadows an outer binding of the same name.
Sourcepub const fn tree(&self) -> &Tree
pub const fn tree(&self) -> &Tree
The tree, for running queries against.
Nodes obtained this way borrow the arena immutably, so they cannot be interned
while still held. Use NodeArena::path_of to reduce them to paths first, drop
them, then call NodeArena::intern_path. The two-phase shape is not incidental:
it is what lets the arena own the tree, which is what makes the handles 'static
enough for the engine to hold.
Sourcepub fn path_of(&self, node: Node<'_>) -> Option<Vec<u32>>
pub fn path_of(&self, node: Node<'_>) -> Option<Vec<u32>>
Reduce a node to a path, so it can be interned after its borrow ends.
Returns None for a node belonging to a different tree. Interning one under a path
that happened to resolve locally would hand a rule a handle pointing at an
unrelated node — wrong results, no error.
Sourcepub fn intern_path(&mut self, path: Vec<u32>) -> Option<u32>
pub fn intern_path(&mut self, path: Vec<u32>) -> Option<u32>
Issue a handle for a path produced by NodeArena::path_of.
Sourcepub fn named_children(&mut self, handle: u32) -> Vec<u32>
pub fn named_children(&mut self, handle: u32) -> Vec<u32>
Named children only, which is what a rule almost always wants.
Sourcepub fn structure_fingerprint(&self, handle: u32) -> Option<StructureFingerprint>
pub fn structure_fingerprint(&self, handle: u32) -> Option<StructureFingerprint>
A structural summary of the subtree rooted at handle, computed in one host-side
walk.
The fold that produces it is the whole normalization contract, stated up front:
- Every non-extra node’s kind name contributes, named and anonymous — anonymous
token kinds are the operators, so
a + banda - bstay distinct. A node is excluded if and only if the grammar marked itextra(comments): a doc-comment difference is not an implementation difference, so comments change neither the bytes nor the count. - Token text is erased. An identifier or literal contributes its kind
(
identifier,number,string) and nothing else. The normalization is language-agnostic by construction — there is no per-language table of what counts as an identifier to maintain. - The fold is framed to be unambiguous. Every kind name is length-prefixed and every node writes its fold-child count, so two different shapes cannot concatenate into one preimage, and two trees whose preorder kind sequences agree but whose nesting differs stay distinct.
ERROR/MISSINGnodes fold like any other kind: a broken parse hashes as its broken shape rather than failing.
The leading byte of the fold is a format version. The fold encoding is host
behavior a rule’s verdict can depend on, and it is not itself in the cache key —
so a future change to this contract must bump it and lanekeep_js’s
HOST_API_VERSION together, or cached verdicts computed under the old encoding
stay valid under the old key.
The hash is blake3 of the fold bytes, lowercase hex. None when the handle does
not resolve — nothing rather than a fabricated shape, the same posture kind,
text and position take.
Sourcepub fn query_subtree(
&self,
handle: u32,
query: &CompiledQuery,
) -> Vec<Vec<(String, Vec<u32>)>>
pub fn query_subtree( &self, handle: u32, query: &CompiledQuery, ) -> Vec<Vec<(String, Vec<u32>)>>
Matches of a query, scoped to one node’s subtree.
Two-phase like everything else here: capture paths are collected while the tree is
borrowed, then interned once that borrow has ended. The arena owns the tree, so a
handle cannot be minted while a Node derived from it is alive.
Sourcepub fn closest_ancestor_paths(
&self,
handle: u32,
query: &CompiledQuery,
) -> Option<Vec<(String, Vec<u32>)>>
pub fn closest_ancestor_paths( &self, handle: u32, query: &CompiledQuery, ) -> Option<Vec<(String, Vec<u32>)>>
The nearest ancestor a query matches at, with that match’s captures.
“Matches at” rather than “matches within”: the query runs rooted at each ancestor in turn, and a match counts only if it captured that ancestor. Without that, a query matching anything anywhere inside would make the outermost ancestor the answer every time, which is never what a rule walking upward wants.