1use std::any::Any;
4use crate::arena::{Arena, NodeId, AstNode};
5
6pub enum VisitControl {
8 Continue,
10 SkipChildren,
12 Stop,
14}
15
16impl Arena {
17 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}