Skip to main content

parser/
visitor.rs

1//! Visitor for depth-first AST traversal. Generated by CongoCC Parser Generator. Do not edit.
2
3use std::any::Any;
4use crate::arena::{Arena, NodeId, AstNode};
5
6/// Controls visitor traversal behavior
7pub enum VisitControl {
8    /// Visit children, then continue with siblings
9    Continue,
10    /// Skip this node's children, continue with siblings
11    SkipChildren,
12    /// Stop traversal entirely
13    Stop,
14}
15
16impl Arena {
17    /// Visit all nodes depth-first starting from `root`.
18    ///
19    /// The closure `f` receives `(node_id, node, arena, depth, options)` and returns
20    /// a `VisitControl` to guide traversal. `options` is an optional caller-supplied
21    /// context passed through to every invocation.
22    pub fn visit<F>(&self, root: NodeId, f: &mut F, options: Option<&dyn Any>) -> VisitControl
23    where
24        F: FnMut(NodeId, &AstNode, &Arena, usize, Option<&dyn Any>) -> VisitControl,
25    {
26        self.visit_impl(root, 0, f, options)
27    }
28
29    fn visit_impl<F>(
30        &self,
31        node_id: NodeId,
32        depth: usize,
33        f: &mut F,
34        options: Option<&dyn Any>,
35    ) -> VisitControl
36    where
37        F: FnMut(NodeId, &AstNode, &Arena, usize, Option<&dyn Any>) -> VisitControl,
38    {
39        let node = self.get_node(node_id);
40        let children: Vec<NodeId> = match node {
41            AstNode::JmsSelector(n) => n.children.clone(),
42            AstNode::OrExpression(n) => n.children.clone(),
43            AstNode::AndExpression(n) => n.children.clone(),
44            AstNode::EqualityExpression(n) => n.children.clone(),
45            AstNode::ComparisonExpression(n) => n.children.clone(),
46            AstNode::AddExpression(n) => n.children.clone(),
47            AstNode::MultExpr(n) => n.children.clone(),
48            AstNode::UnaryExpr(n) => n.children.clone(),
49            AstNode::PrimaryExpr(n) => n.children.clone(),
50            AstNode::Literal(n) => n.children.clone(),
51            AstNode::StringLiteral(n) => n.children.clone(),
52            AstNode::Variable(n) => n.children.clone(),
53        };
54        match f(node_id, node, self, depth, options) {
55            VisitControl::Stop => return VisitControl::Stop,
56            VisitControl::SkipChildren => return VisitControl::Continue,
57            VisitControl::Continue => {}
58        }
59        for child in children {
60            if matches!(
61                self.visit_impl(child, depth + 1, f, options),
62                VisitControl::Stop
63            ) {
64                return VisitControl::Stop;
65            }
66        }
67        VisitControl::Continue
68    }
69}