1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
// This file is generated automatically by infrastructure scripts. Please don't edit by hand.
use std::ops::ControlFlow;
use std::rc::Rc;
use super::{cst::*, cursor::Cursor};
/// A Visitor pattern for traversing the CST.
///
/// The trait supports fallible iteration, i.e. the visitor can early return an error from the visit.
pub trait Visitor<E> {
/// Called when the [`Visitor`] enters a [`RuleNode`].
fn rule_enter(
&mut self,
_node: &Rc<RuleNode>,
_cursor: &Cursor,
) -> Result<ControlFlow<(), Step>, E> {
Ok(ControlFlow::Continue(Step::In))
}
/// Called when the [`Visitor`] exits a [`RuleNode`].
fn rule_exit(&mut self, _node: &Rc<RuleNode>, _cursor: &Cursor) -> Result<ControlFlow<()>, E> {
Ok(ControlFlow::Continue(()))
}
/// Called when the [`Visitor`] enters a [`TokenNode`].
fn token(&mut self, _node: &Rc<TokenNode>, _cursor: &Cursor) -> Result<ControlFlow<()>, E> {
Ok(ControlFlow::Continue(()))
}
}
/// Whether the [`Visitor`] should should enter the children of a [`RuleNode`] or not.
pub enum Step {
In,
Over,
}
impl Cursor {
pub fn drive_visitor<E, V: Visitor<E>>(
&mut self,
visitor: &mut V,
) -> Result<ControlFlow<()>, E> {
if self.is_completed() {
return Ok(ControlFlow::Continue(()));
}
loop {
// Node clone is cheap because it's just an enum around an Rc
match self.node() {
Node::Rule(rule_node) => {
match visitor.rule_enter(&rule_node, self)? {
ControlFlow::Break(()) => return Ok(ControlFlow::Break(())),
ControlFlow::Continue(Step::In) => {
if self.go_to_first_child() {
self.drive_visitor(visitor)?;
self.go_to_parent();
}
}
ControlFlow::Continue(Step::Over) => {}
}
if visitor.rule_exit(&rule_node, self)? == ControlFlow::Break(()) {
return Ok(ControlFlow::Break(()));
}
}
Node::Token(token_node) => {
if visitor.token(&token_node, self)? == ControlFlow::Break(()) {
return Ok(ControlFlow::Break(()));
}
}
}
if !self.go_to_next_sibling() {
return Ok(ControlFlow::Continue(()));
}
}
}
}