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
mod pattern;
pub use pattern::{Item as PatternItem, Pattern, PatternError};
use crate::traverse::visitor::{Item as VisitorItem, Observer, Visitor};
use crate::Node;
#[derive(Debug)]
pub struct Finder {
looking_for: Pattern,
current_path: Pattern,
result: Option<Node>,
}
impl Finder {
pub fn run(looking_for: &str, root: &Node) -> Result<Option<Node>, PatternError> {
let looking_for = Pattern::new(looking_for)?;
let mut visitor = Visitor {
observer: Self {
looking_for,
current_path: Pattern::empty(),
result: None,
},
};
visitor.visit_root(&root);
Ok(visitor.observer.result)
}
}
impl Observer for Finder {
fn on_node(&mut self, node: &Node) {
if self.current_path == self.looking_for {
self.result = Some(node.clone());
}
}
fn on_subitem(&mut self, subitem: VisitorItem) {
self.current_path.push(PatternItem::VisitorItem(subitem))
}
fn on_subitem_moving_up(&mut self, _: VisitorItem) {
self.current_path.pop().unwrap();
}
}