use std::any::Any;
use crate::arena::{Arena, NodeId, AstNode};
pub enum VisitControl {
Continue,
SkipChildren,
Stop,
}
impl Arena {
pub fn visit<F>(&self, root: NodeId, f: &mut F, options: Option<&dyn Any>) -> VisitControl
where
F: FnMut(NodeId, &AstNode, &Arena, usize, Option<&dyn Any>) -> VisitControl,
{
self.visit_impl(root, 0, f, options)
}
fn visit_impl<F>(
&self,
node_id: NodeId,
depth: usize,
f: &mut F,
options: Option<&dyn Any>,
) -> VisitControl
where
F: FnMut(NodeId, &AstNode, &Arena, usize, Option<&dyn Any>) -> VisitControl,
{
let node = self.get_node(node_id);
let children: Vec<NodeId> = match node {
AstNode::JmsSelector(n) => n.children.clone(),
AstNode::OrExpression(n) => n.children.clone(),
AstNode::AndExpression(n) => n.children.clone(),
AstNode::EqualityExpression(n) => n.children.clone(),
AstNode::ComparisonExpression(n) => n.children.clone(),
AstNode::AddExpression(n) => n.children.clone(),
AstNode::MultExpr(n) => n.children.clone(),
AstNode::UnaryExpr(n) => n.children.clone(),
AstNode::PrimaryExpr(n) => n.children.clone(),
AstNode::Literal(n) => n.children.clone(),
AstNode::StringLiteral(n) => n.children.clone(),
AstNode::Variable(n) => n.children.clone(),
};
match f(node_id, node, self, depth, options) {
VisitControl::Stop => return VisitControl::Stop,
VisitControl::SkipChildren => return VisitControl::Continue,
VisitControl::Continue => {}
}
for child in children {
if matches!(
self.visit_impl(child, depth + 1, f, options),
VisitControl::Stop
) {
return VisitControl::Stop;
}
}
VisitControl::Continue
}
}