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>
impl<K> Node<K>
Sourcepub fn new(kind: K, children: Vec<Element<K>>) -> Self
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));Sourcepub fn kind(&self) -> &K
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");Sourcepub fn span(&self) -> Span
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));Sourcepub fn is_empty(&self) -> bool
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());Sourcepub fn len(&self) -> usize
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);Sourcepub fn children(&self) -> impl Iterator<Item = &Element<K>>
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"]);Sourcepub fn child_nodes(&self) -> impl Iterator<Item = &Node<K>>
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);Sourcepub fn child_tokens(&self) -> impl Iterator<Item = &Token<K>>
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"]);Sourcepub fn descendants(&self) -> impl Iterator<Item = &Node<K>>
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"]);Sourcepub fn tokens(&self) -> impl Iterator<Item = &Token<K>>
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"]);Sourcepub fn text<'s>(&self, source: &'s str) -> Option<&'s str>
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 stringTrait Implementations§
Source§impl<K> Drop for Node<K>
impl<K> Drop for Node<K>
Source§fn drop(&mut self)
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.