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
79
80
81
82
83
84
85
// This file is generated automatically by infrastructure scripts. Please don't edit by hand.

use std::rc::Rc;

use super::{cst::*, cursor::Cursor};

#[allow(unused_variables)]
pub trait Visitor<E> {
    fn rule_enter(
        &mut self,
        node: &Rc<RuleNode>,
        cursor: &Cursor,
    ) -> Result<VisitorEntryResponse, E> {
        Ok(VisitorEntryResponse::StepIn)
    }

    fn rule_exit(
        &mut self,
        node: &Rc<RuleNode>,
        cursor: &Cursor,
    ) -> Result<VisitorExitResponse, E> {
        Ok(VisitorExitResponse::Continue)
    }

    fn token(&mut self, node: &Rc<TokenNode>, cursor: &Cursor) -> Result<VisitorExitResponse, E> {
        Ok(VisitorExitResponse::Continue)
    }
}

#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum VisitorEntryResponse {
    Quit,
    StepIn,
    StepOver,
}

#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum VisitorExitResponse {
    Quit,
    Continue,
}

#[allow(dead_code)]
impl Cursor {
    pub fn drive_visitor<E, V: Visitor<E>>(
        &mut self,
        visitor: &mut V,
    ) -> Result<VisitorExitResponse, E> {
        if self.is_completed() {
            return Ok(VisitorExitResponse::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)? {
                        VisitorEntryResponse::Quit => return Ok(VisitorExitResponse::Quit),
                        VisitorEntryResponse::StepIn => {
                            if self.go_to_first_child() {
                                self.drive_visitor(visitor)?;
                                self.go_to_parent();
                            }
                        }
                        VisitorEntryResponse::StepOver => {}
                    }
                    if visitor.rule_exit(&rule_node, self)? == VisitorExitResponse::Quit {
                        return Ok(VisitorExitResponse::Quit);
                    }
                }

                Node::Token(token_node) => {
                    if visitor.token(&token_node, self)? == VisitorExitResponse::Quit {
                        return Ok(VisitorExitResponse::Quit);
                    }
                }
            }
            if !self.go_to_next_sibling() {
                break;
            }
        }
        Ok(VisitorExitResponse::Continue)
    }
}