Skip to main content

NodeArena

Struct NodeArena 

Source
pub struct NodeArena { /* private fields */ }
Expand description

Owns a parsed tree and the handles issued against it.

Implementations§

Source§

impl NodeArena

Source

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.

Source

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.

Source

pub fn source(&self) -> &str

The source this tree was parsed from.

Source

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.

Source

pub fn is_empty(&self) -> bool

Whether only the root has been interned.

Source

pub fn kind(&self, handle: u32) -> Option<&'static str>

The node’s kind, as the grammar names it.

Source

pub fn is_named(&self, handle: u32) -> Option<bool>

Whether the node is named, as opposed to an anonymous token such as a bracket.

Source

pub fn text(&self, handle: u32) -> Option<&str>

The source text the node spans.

Source

pub fn position(&self, handle: u32) -> Option<(u32, u32)>

One-based line and column of the node’s start.

Source

pub fn byte_range(&self, handle: u32) -> Option<(usize, usize)>

The node’s byte range in the source.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn intern_path(&mut self, path: Vec<u32>) -> Option<u32>

Issue a handle for a path produced by NodeArena::path_of.

Source

pub fn parent(&mut self, handle: u32) -> Option<u32>

The node’s parent, if it is not the root.

Source

pub fn children(&mut self, handle: u32) -> Vec<u32>

Every child, including anonymous tokens.

Source

pub fn named_children(&mut self, handle: u32) -> Vec<u32>

Named children only, which is what a rule almost always wants.

Source

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 + b and a - b stay distinct. A node is excluded if and only if the grammar marked it extra (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/MISSING nodes 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.

Source

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.

Source

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.

Source

pub fn ancestors(&mut self, handle: u32) -> Vec<u32>

Ancestors, innermost first, ending at the root.

Trait Implementations§

Source§

impl Debug for NodeArena

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ParallelSend for T

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.