Skip to main content
The Visitor trait implements functions to listen for specific nodes and tokens in the AST. Unlike VisitorMut, nodes and tokens passed are immutable.

Trait Definition

pub trait Visitor {
    /// Visit the nodes of an Ast
    fn visit_ast(&mut self, ast: &Ast) where Self: Sized {
        ast.nodes().visit(self);
        ast.eof().visit(self);
    }

    // AST node visit methods
    fn visit_anonymous_call(&mut self, _node: &FunctionArgs) { }
    fn visit_anonymous_call_end(&mut self, _node: &FunctionArgs) { }
    fn visit_anonymous_function(&mut self, _node: &AnonymousFunction) { }
    fn visit_anonymous_function_end(&mut self, _node: &AnonymousFunction) { }
    fn visit_assignment(&mut self, _node: &Assignment) { }
    fn visit_assignment_end(&mut self, _node: &Assignment) { }
    fn visit_block(&mut self, _node: &Block) { }
    fn visit_block_end(&mut self, _node: &Block) { }
    fn visit_call(&mut self, _node: &Call) { }
    fn visit_call_end(&mut self, _node: &Call) { }
    fn visit_contained_span(&mut self, _node: &ContainedSpan) { }
    fn visit_contained_span_end(&mut self, _node: &ContainedSpan) { }
    fn visit_do(&mut self, _node: &Do) { }
    fn visit_do_end(&mut self, _node: &Do) { }
    fn visit_else_if(&mut self, _node: &ElseIf) { }
    fn visit_else_if_end(&mut self, _node: &ElseIf) { }
    fn visit_eof(&mut self, _node: &TokenReference) { }
    fn visit_eof_end(&mut self, _node: &TokenReference) { }
    fn visit_expression(&mut self, _node: &Expression) { }
    fn visit_expression_end(&mut self, _node: &Expression) { }
    fn visit_field(&mut self, _node: &Field) { }
    fn visit_field_end(&mut self, _node: &Field) { }
    fn visit_function_args(&mut self, _node: &FunctionArgs) { }
    fn visit_function_args_end(&mut self, _node: &FunctionArgs) { }
    fn visit_function_body(&mut self, _node: &FunctionBody) { }
    fn visit_function_body_end(&mut self, _node: &FunctionBody) { }
    fn visit_function_call(&mut self, _node: &FunctionCall) { }
    fn visit_function_call_end(&mut self, _node: &FunctionCall) { }
    fn visit_function_declaration(&mut self, _node: &FunctionDeclaration) { }
    fn visit_function_declaration_end(&mut self, _node: &FunctionDeclaration) { }
    fn visit_function_name(&mut self, _node: &FunctionName) { }
    fn visit_function_name_end(&mut self, _node: &FunctionName) { }
    fn visit_generic_for(&mut self, _node: &GenericFor) { }
    fn visit_generic_for_end(&mut self, _node: &GenericFor) { }
    fn visit_if(&mut self, _node: &If) { }
    fn visit_if_end(&mut self, _node: &If) { }
    fn visit_index(&mut self, _node: &Index) { }
    fn visit_index_end(&mut self, _node: &Index) { }
    fn visit_local_assignment(&mut self, _node: &LocalAssignment) { }
    fn visit_local_assignment_end(&mut self, _node: &LocalAssignment) { }
    fn visit_local_function(&mut self, _node: &LocalFunction) { }
    fn visit_local_function_end(&mut self, _node: &LocalFunction) { }
    fn visit_last_stmt(&mut self, _node: &LastStmt) { }
    fn visit_last_stmt_end(&mut self, _node: &LastStmt) { }
    fn visit_method_call(&mut self, _node: &MethodCall) { }
    fn visit_method_call_end(&mut self, _node: &MethodCall) { }
    fn visit_numeric_for(&mut self, _node: &NumericFor) { }
    fn visit_numeric_for_end(&mut self, _node: &NumericFor) { }
    fn visit_parameter(&mut self, _node: &Parameter) { }
    fn visit_parameter_end(&mut self, _node: &Parameter) { }
    fn visit_prefix(&mut self, _node: &Prefix) { }
    fn visit_prefix_end(&mut self, _node: &Prefix) { }
    fn visit_return(&mut self, _node: &Return) { }
    fn visit_return_end(&mut self, _node: &Return) { }
    fn visit_repeat(&mut self, _node: &Repeat) { }
    fn visit_repeat_end(&mut self, _node: &Repeat) { }
    fn visit_stmt(&mut self, _node: &Stmt) { }
    fn visit_stmt_end(&mut self, _node: &Stmt) { }
    fn visit_suffix(&mut self, _node: &Suffix) { }
    fn visit_suffix_end(&mut self, _node: &Suffix) { }
    fn visit_table_constructor(&mut self, _node: &TableConstructor) { }
    fn visit_table_constructor_end(&mut self, _node: &TableConstructor) { }
    fn visit_token_reference(&mut self, _node: &TokenReference) { }
    fn visit_token_reference_end(&mut self, _node: &TokenReference) { }
    fn visit_un_op(&mut self, _node: &UnOp) { }
    fn visit_un_op_end(&mut self, _node: &UnOp) { }
    fn visit_var(&mut self, _node: &Var) { }
    fn visit_var_end(&mut self, _node: &Var) { }
    fn visit_var_expression(&mut self, _node: &VarExpression) { }
    fn visit_var_expression_end(&mut self, _node: &VarExpression) { }
    fn visit_while(&mut self, _node: &While) { }
    fn visit_while_end(&mut self, _node: &While) { }

    // Token visit methods
    fn visit_identifier(&mut self, _token: &Token) { }
    fn visit_multi_line_comment(&mut self, _token: &Token) { }
    fn visit_number(&mut self, _token: &Token) { }
    fn visit_single_line_comment(&mut self, _token: &Token) { }
    fn visit_string_literal(&mut self, _token: &Token) { }
    fn visit_symbol(&mut self, _token: &Token) { }
    fn visit_token(&mut self, _token: &Token) { }
    fn visit_whitespace(&mut self, _token: &Token) { }
}

Available Methods

The Visitor trait provides methods for visiting:

AST Nodes

For each AST node type, two methods are provided:
  • visit_<node>(&mut self, node: &<NodeType>) - Called when entering the node
  • visit_<node>_end(&mut self, node: &<NodeType>) - Called when leaving the node
Key node types include:
  • visit_local_assignment / visit_local_assignment_end - Local variable assignments
  • visit_function_declaration / visit_function_declaration_end - Function declarations
  • visit_function_call / visit_function_call_end - Function calls
  • visit_if / visit_if_end - If statements
  • visit_while / visit_while_end - While loops
  • visit_expression / visit_expression_end - Expressions
  • And many more…

Tokens

Token visitor methods include:
  • visit_identifier - Identifiers
  • visit_number - Number literals
  • visit_string_literal - String literals
  • visit_symbol - Symbols (operators, punctuation)
  • visit_whitespace - Whitespace
  • visit_single_line_comment - Single-line comments
  • visit_multi_line_comment - Multi-line comments
  • visit_token - Any token

Example: Collecting Local Variables

use full_moon::ast;
use full_moon::visitors::*;

// A visitor that logs every local assignment made
#[derive(Default)]
struct LocalVariableVisitor {
    names: Vec<String>,
}

impl Visitor for LocalVariableVisitor {
    fn visit_local_assignment(&mut self, local_assignment: &ast::LocalAssignment) {
        self.names.extend(&mut local_assignment.names().iter().map(|name| name.token().to_string()));
    }
}

let mut visitor = LocalVariableVisitor::default();
visitor.visit_ast(&full_moon::parse("local x = 1; local y, z = 2, 3").unwrap());
assert_eq!(visitor.names, vec!["x", "y", "z"]);

Example: Counting Function Calls

use full_moon::ast;
use full_moon::visitors::*;

#[derive(Default)]
struct FunctionCallCounter {
    count: usize,
}

impl Visitor for FunctionCallCounter {
    fn visit_function_call(&mut self, _call: &ast::FunctionCall) {
        self.count += 1;
    }
}

let mut visitor = FunctionCallCounter::default();
visitor.visit_ast(&full_moon::parse("print('hello'); foo(); bar()").unwrap());
assert_eq!(visitor.count, 3);

Example: Analyzing Comments

use full_moon::tokenizer::Token;
use full_moon::visitors::*;

#[derive(Default)]
struct CommentCollector {
    comments: Vec<String>,
}

impl Visitor for CommentCollector {
    fn visit_single_line_comment(&mut self, token: &Token) {
        self.comments.push(token.to_string());
    }
    
    fn visit_multi_line_comment(&mut self, token: &Token) {
        self.comments.push(token.to_string());
    }
}

let mut visitor = CommentCollector::default();
visitor.visit_ast(&full_moon::parse("-- comment 1\nlocal x = 1 --[[ comment 2 ]]").unwrap());
assert_eq!(visitor.comments.len(), 2);

See Also

  • VisitorMut - Mutable visitor trait
  • Node - Node trait for AST elements

Build docs developers (and LLMs) love