Skip to main content
The Node trait is used to represent nodes such as tokens or function definitions in the full-moon AST. This trait is sealed and cannot be implemented for types outside of full-moon.

Trait Definition

pub trait Node: private::Sealed {
    /// The start position of a node. None if can't be determined
    fn start_position(&self) -> Option<Position>;

    /// The end position of a node. None if it can't be determined
    fn end_position(&self) -> Option<Position>;

    /// Whether another node of the same type is the same as this one semantically, ignoring position
    fn similar(&self, other: &Self) -> bool
    where
        Self: Sized;

    /// The token references that comprise a node
    fn tokens(&self) -> Tokens;

    /// The full range of a node, if it has both start and end positions
    fn range(&self) -> Option<(Position, Position)> {
        Some((self.start_position()?, self.end_position()?))
    }

    /// The tokens surrounding a node that are ignored and not accessible through the node's own accessors.
    /// Use this if you want to get surrounding comments or whitespace.
    /// Returns a tuple of the leading and trailing trivia.
    fn surrounding_trivia(&self) -> (Vec<&Token>, Vec<&Token>) {
        let mut tokens = self.tokens();
        let leading = tokens.next();
        let trailing = tokens.next_back();

        (
            match leading {
                Some(token) => token.leading_trivia().collect(),
                None => Vec::new(),
            },
            match trailing {
                Some(token) => token.trailing_trivia().collect(),
                None => Vec::new(),
            },
        )
    }
}

Methods

start_position

fn start_position(&self) -> Option<Position>
Returns the start position of the node in the source code. Returns None if the position cannot be determined.

end_position

fn end_position(&self) -> Option<Position>
Returns the end position of the node in the source code. Returns None if the position cannot be determined.

similar

fn similar(&self, other: &Self) -> bool where Self: Sized
Compares whether another node of the same type is semantically the same as this one, ignoring position information. Useful for comparing AST structures without considering their location in the source.

tokens

fn tokens(&self) -> Tokens
Returns an iterator over all the token references that comprise this node.

range

fn range(&self) -> Option<(Position, Position)>
Returns the full range of the node as a tuple of (start_position, end_position). Returns None if either position cannot be determined.

surrounding_trivia

fn surrounding_trivia(&self) -> (Vec<&Token>, Vec<&Token>)
Returns the tokens surrounding a node that are ignored and not accessible through the node’s own accessors. Use this method to access surrounding comments or whitespace. Returns a tuple of (leading_trivia, trailing_trivia).

Tokens Iterator

The Tokens type is an iterator returned by Node::tokens():
pub struct Tokens<'a> {
    pub(crate) items: Vec<TokenItem<'a>>,
}

impl<'a> Iterator for Tokens<'a> {
    type Item = &'a TokenReference;
    fn next(&mut self) -> Option<Self::Item>;
}

impl DoubleEndedIterator for Tokens<'_> {
    fn next_back(&mut self) -> Option<Self::Item>;
}
The Tokens iterator is double-ended, allowing iteration from both the start and end of the token sequence.

Implementations

The Node trait is implemented for many types in full-moon:
  • Ast - The complete AST
  • TokenReference - Individual tokens
  • Box<T> where T: Node
  • &T where T: Node
  • &mut T where T: Node
  • Option<T> where T: Node
  • Vec<T> where T: Node
  • (A, B) where A: Node, B: Node
  • All AST node types (e.g., FunctionDeclaration, LocalAssignment, etc.)

Example: Getting Node Position

use full_moon::node::Node;

let ast = full_moon::parse("local x = 1").unwrap();

if let Some(start) = ast.start_position() {
    println!("AST starts at line {}, column {}", start.line(), start.character());
}

if let Some((start, end)) = ast.range() {
    println!("AST spans from {:?} to {:?}", start, end);
}

Example: Comparing Nodes

use full_moon::node::Node;

let ast1 = full_moon::parse("local x = 1").unwrap();
let ast2 = full_moon::parse("local x = 1").unwrap();
let ast3 = full_moon::parse("local y = 2").unwrap();

assert!(ast1.similar(&ast2)); // Same semantically
assert!(!ast1.similar(&ast3)); // Different semantically

Example: Accessing Surrounding Trivia

use full_moon::node::Node;

let ast = full_moon::parse("-- comment\nlocal x = 1 -- inline comment").unwrap();

// Get surrounding trivia (comments, whitespace) for the AST
let (leading, trailing) = ast.surrounding_trivia();

println!("Leading trivia: {} tokens", leading.len());
println!("Trailing trivia: {} tokens", trailing.len());

for token in leading {
    println!("Leading: {:?}", token);
}

for token in trailing {
    println!("Trailing: {:?}", token);
}

Example: Iterating Over Tokens

use full_moon::node::Node;

let ast = full_moon::parse("local x = 1").unwrap();

// Iterate over all tokens in the AST
for token in ast.tokens() {
    println!("Token: {}", token);
}

// Double-ended iteration
let mut tokens = ast.tokens();
if let Some(first) = tokens.next() {
    println!("First token: {}", first);
}
if let Some(last) = tokens.next_back() {
    println!("Last token: {}", last);
}

Use Cases

The Node trait is useful for:
  • Position tracking: Finding where code elements appear in source
  • Semantic comparison: Comparing AST structures without position data
  • Token access: Getting all tokens that make up a node
  • Trivia analysis: Accessing comments and whitespace around nodes
  • Range calculation: Determining the span of code elements
  • Generic AST traversal: Writing code that works with any node type

See Also

  • Visitor - Trait for visiting nodes immutably
  • VisitorMut - Trait for visiting nodes mutably
  • Position - Represents a position in source code
  • TokenReference - Represents a token with trivia

Build docs developers (and LLMs) love