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
86
87
88
89
90
91
92
93
use super::{Glob, Matcher, Splitter};
#[derive(Clone, Debug)]
pub struct GlobStack<'a>(Vec<&'a [Matcher]>);
impl<'a> GlobStack<'a> {
pub fn new(starter: &Glob) -> GlobStack<'_> {
GlobStack(vec![starter.0.as_slice()])
}
pub fn add_glob(&mut self, glob: &'a Glob) {
self.0.push(glob.0.as_slice());
}
pub fn add_matcher(&mut self, matcher: &'a Matcher) {
self.0.push(std::slice::from_ref(matcher));
}
pub fn next(&mut self) -> Option<&'a Matcher> {
while let Some(front) = self.0.last_mut() {
if let Some((retval, rest)) = front.split_last() {
*front = rest;
return Some(retval);
} else {
self.0.pop();
}
}
None
}
}
enum SavePoint<'a, 'b> {
Rewind(Splitter<'a>, GlobStack<'b>, &'b Matcher),
Alts(Splitter<'a>, GlobStack<'b>, &'b [Glob]),
}
pub struct SaveStack<'a, 'b> {
globs: GlobStack<'b>,
stack: Vec<SavePoint<'a, 'b>>,
}
impl<'a, 'b> SaveStack<'a, 'b> {
pub fn new(_: &Splitter<'a>, glob: &'b Glob) -> SaveStack<'a, 'b> {
SaveStack {
globs: GlobStack::new(glob),
stack: Vec::<SavePoint<'a, 'b>>::new(),
}
}
pub fn globs(&mut self) -> &mut GlobStack<'b> {
&mut self.globs
}
pub fn add_rewind(&mut self, splitter: Splitter<'a>, matcher: &'b Matcher) {
self
.stack
.push(SavePoint::Rewind(splitter, self.globs.clone(), matcher))
}
pub fn add_alts(&mut self, splitter: Splitter<'a>, matcher: &'b [Glob]) {
if let Some((first, rest)) = matcher.split_first() {
self.stack.push(SavePoint::Alts(splitter, self.globs.clone(), rest));
self.globs().add_glob(first);
}
}
pub fn restore(&mut self) -> Option<Splitter<'a>> {
while let Some(point) = self.stack.pop() {
use SavePoint::*;
match point {
Rewind(splitter, globs, matcher) => {
self.stack.pop();
self.globs = globs;
self.globs.add_matcher(matcher);
return Some(splitter);
}
Alts(splitter, globs, alts) => {
self.globs = globs;
if let Some((glob, rest)) = alts.split_first() {
if !rest.is_empty() {
self
.stack
.push(SavePoint::Alts(splitter.clone(), self.globs.clone(), rest));
}
self.globs.add_glob(glob);
return Some(splitter);
}
}
}
}
None
}
}