Skip to main content

Node

Struct Node 

Source
pub struct Node<K> { /* private fields */ }
Expand description

An interior node of a concrete syntax tree: a kind, the span of source it covers, and its ordered children.

A node owns its children directly, so a whole tree is a single owned value with no arena or handle bookkeeping. The children are in source order; a node’s covering span is the union of its children’s spans, computed once when the node is built. Because trivia rides as ordinary leaf tokens, the tree is lossless: slicing the original source by a node’s span — or concatenating its tokens — reproduces exactly the source that node came from.

The kind type K is shared by nodes and tokens alike (an enum a language defines with both composite and lexical variants), following the model token_lang establishes. The node type itself is generic over any K and needs no trait bound.

§Stack safety

Traversal (tokens, descendants) and teardown (Drop) are iterative: a tree tens of thousands of levels deep is walked and freed without recursing on the call stack. Clone, PartialEq, and Debug recurse with tree depth and so suit trees of realistic source depth.

§Examples

use syntax_lang::{Element, Node, Span, Token};

// `1 + 2` as a tiny expression node with three leaf tokens.
let node = Node::new(
    "add",
    vec![
        Element::Token(Token::new("num", Span::new(0, 1))),
        Element::Token(Token::new("plus", Span::new(2, 3))),
        Element::Token(Token::new("num", Span::new(4, 5))),
    ],
);

assert_eq!(node.kind(), &"add");
assert_eq!(node.span(), Span::new(0, 5));
assert_eq!(node.text("1 + 2"), Some("1 + 2"));
assert_eq!(node.children().count(), 3);

Implementations§

Source§

impl<K> Node<K>

Source

pub fn new(kind: K, children: Vec<Element<K>>) -> Self

Builds a node from a kind and its ordered children, computing the covering span as the union of the children’s spans.

Children are taken in source order. A node with no children reports an empty span at offset 0; build such nodes through a Builder instead, which places an empty node at the current stream position.

§Examples
use syntax_lang::{Element, Node, Span, Token};

let n = Node::new(
    "paren",
    vec![
        Element::Token(Token::new("(", Span::new(0, 1))),
        Element::Token(Token::new(")", Span::new(1, 2))),
    ],
);
assert_eq!(n.span(), Span::new(0, 2));
Source

pub fn kind(&self) -> &K

Borrows this node’s kind.

§Examples
use syntax_lang::Node;

let n: Node<&str> = Node::new("root", vec![]);
assert_eq!(n.kind(), &"root");
Source

pub fn span(&self) -> Span

Returns the span of source this node covers: the union of its children’s spans, or an empty span if it has none.

§Examples
use syntax_lang::{Element, Node, Span, Token};

let n = Node::new("n", vec![Element::Token(Token::new("t", Span::new(3, 8)))]);
assert_eq!(n.span(), Span::new(3, 8));
Source

pub fn is_empty(&self) -> bool

Whether this node has no children.

§Examples
use syntax_lang::Node;

let n: Node<&str> = Node::new("empty", vec![]);
assert!(n.is_empty());
Source

pub fn len(&self) -> usize

The number of direct children (nodes and tokens) this node has.

§Examples
use syntax_lang::{Element, Node, Span, Token};

let n = Node::new("n", vec![Element::Token(Token::new("t", Span::new(0, 1)))]);
assert_eq!(n.len(), 1);
Source

pub fn children(&self) -> impl Iterator<Item = &Element<K>>

Iterates this node’s direct children — nodes and tokens interleaved in source order.

§Examples
use syntax_lang::{Element, Node, Span, Token};

let n = Node::new(
    "n",
    vec![
        Element::Token(Token::new("a", Span::new(0, 1))),
        Element::Node(Node::new("inner", vec![Element::Token(Token::new("b", Span::new(1, 2)))])),
    ],
);
let kinds: Vec<_> = n.children().map(Element::kind).copied().collect();
assert_eq!(kinds, ["a", "inner"]);
Source

pub fn child_nodes(&self) -> impl Iterator<Item = &Node<K>>

Iterates only the direct children that are nested nodes, skipping leaf tokens.

§Examples
use syntax_lang::{Element, Node, Span, Token};

let n = Node::new(
    "n",
    vec![
        Element::Token(Token::new("a", Span::new(0, 1))),
        Element::Node(Node::new("inner", vec![Element::Token(Token::new("b", Span::new(1, 2)))])),
    ],
);
assert_eq!(n.child_nodes().count(), 1);
Source

pub fn child_tokens(&self) -> impl Iterator<Item = &Token<K>>

Iterates only the direct children that are leaf tokens, skipping nested nodes.

§Examples
use syntax_lang::{Element, Node, Span, Token};

let n = Node::new(
    "n",
    vec![
        Element::Token(Token::new("a", Span::new(0, 1))),
        Element::Node(Node::new("inner", vec![Element::Token(Token::new("b", Span::new(1, 2)))])),
    ],
);
let direct: Vec<_> = n.child_tokens().map(|t| *t.kind()).collect();
assert_eq!(direct, ["a"]);
Source

pub fn descendants(&self) -> impl Iterator<Item = &Node<K>>

Iterates this node and every node beneath it in pre-order (a parent before its descendants, children in source order).

The walk is iterative — its work stack lives on the heap — so a tree of any depth is traversed without overflowing the call stack.

§Examples
use syntax_lang::{Element, Node, Span, Token};

let tree = Node::new(
    "root",
    vec![Element::Node(Node::new(
        "inner",
        vec![Element::Token(Token::new("t", Span::new(0, 1)))],
    ))],
);
let kinds: Vec<_> = tree.descendants().map(Node::kind).copied().collect();
assert_eq!(kinds, ["root", "inner"]);
Source

pub fn tokens(&self) -> impl Iterator<Item = &Token<K>>

Iterates every leaf token in the tree in source order — the lossless token stream, trivia included.

Concatenating these tokens’ source slices reproduces the node’s source exactly; the walk is iterative and safe on any depth.

§Examples
use syntax_lang::{Element, Node, Span, Token};

let tree = Node::new(
    "root",
    vec![Element::Node(Node::new(
        "inner",
        vec![
            Element::Token(Token::new("a", Span::new(0, 1))),
            Element::Token(Token::new("b", Span::new(1, 2))),
        ],
    ))],
);
let leaves: Vec<_> = tree.tokens().map(|t| *t.kind()).collect();
assert_eq!(leaves, ["a", "b"]);
Source

pub fn text<'s>(&self, source: &'s str) -> Option<&'s str>

Slices source by this node’s covering span, returning the exact text the node came from, or None if the span lies outside source.

This is zero-copy: it borrows a sub-slice of source rather than allocating. Pass the same source the tree was built from; the None case guards against a mismatched or truncated string rather than panicking.

§Examples
use syntax_lang::{Element, Node, Span, Token};

let n = Node::new(
    "call",
    vec![
        Element::Token(Token::new("id", Span::new(0, 1))),
        Element::Token(Token::new("(", Span::new(1, 2))),
        Element::Token(Token::new(")", Span::new(2, 3))),
    ],
);
assert_eq!(n.text("f()"), Some("f()"));
assert_eq!(n.text("f"), None); // span runs past the string

Trait Implementations§

Source§

impl<K: Clone> Clone for Node<K>

Source§

fn clone(&self) -> Node<K>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<K: Debug> Debug for Node<K>

Source§

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

Formats the value using the given formatter. Read more
Source§

impl<K> Drop for Node<K>

Source§

fn drop(&mut self)

Frees the tree without recursion.

The default drop glue would recurse once per level of nesting, overflowing the stack on a pathologically deep tree (a long chain of single-child nodes). This moves every descendant node onto an explicit heap worklist and drops them there, so teardown depth is bounded by heap, not stack.

Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl<K: Eq> Eq for Node<K>

Source§

impl<K: PartialEq> PartialEq for Node<K>

Source§

fn eq(&self, other: &Node<K>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<K: PartialEq> StructuralPartialEq for Node<K>

Auto Trait Implementations§

§

impl<K> Freeze for Node<K>
where K: Freeze,

§

impl<K> RefUnwindSafe for Node<K>
where K: RefUnwindSafe,

§

impl<K> Send for Node<K>
where K: Send,

§

impl<K> Sync for Node<K>
where K: Sync,

§

impl<K> Unpin for Node<K>
where K: Unpin,

§

impl<K> UnsafeUnpin for Node<K>
where K: UnsafeUnpin,

§

impl<K> UnwindSafe for Node<K>
where K: UnwindSafe,

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = Infallible

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.