use super::model::Node;
pub enum Direction {
Entering,
Exiting,
}
pub enum NextAction {
GotoNext,
SkipChildren,
End,
}
pub trait Visitor<'input> {
fn visit(&self, node: &'input Node<'input>, direction: Direction) -> NextAction;
}
impl<'a> Node<'a> {
pub fn traverse(&'a self, visitor: &impl Visitor<'a>) -> NextAction {
let children = match self.children() {
Some(c) => c,
None => return visitor.visit(self, Direction::Entering),
};
match visitor.visit(self, Direction::Entering) {
NextAction::GotoNext => {
for child in children.iter() {
if let NextAction::End = child.traverse(visitor) {
return NextAction::End;
}
}
visitor.visit(self, Direction::Exiting)
}
NextAction::SkipChildren => {
visitor.visit(self, Direction::Exiting)
}
NextAction::End => {
let _ = visitor.visit(self, Direction::Exiting);
NextAction::End
}
}
}
}