-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcollapse.rs
70 lines (56 loc) · 1.85 KB
/
collapse.rs
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
use parse::Ast;
use std::collections::VecDeque;
pub fn collapse(v: Vec<Ast>) -> Vec<Ast> {
let mut c = Collapser { data: v, pos: 0 };
c.collapse();
let Collapser { data, .. } = c;
data
}
#[derive(Debug)]
struct Collapser {
data: Vec<Ast>,
pos: usize,
}
impl Collapser {
fn cur(&self) -> Ast { self.data[self.pos].clone() }
fn collapse(&mut self) {
let mut vec = vec![];
loop {
let cur = self.cur();
let ast = match cur {
Ast::Char(_) |
Ast::Literal(_) => Some(cur),
Ast::Class(mut deque) => Some(self.collapse_class(&mut deque)),
Ast::Empty => None,
_ => unimplemented!(),
};
if let Some(val) = ast { vec.push(val) }
if !self.next() { break }
}
self.data = vec;
}
// I think this entire thing might be replaceable with a fold but
// I was running into issues when testing it. `chunks` returns references
// and DequeVec doesn't implement Deref so I can't call chunks on it. Maybe
// in the future.
fn collapse_class(&mut self, deque: &mut VecDeque<Ast>) -> Ast {
let mut left = deque.pop_front()
.unwrap();
while let Some(op) = deque.pop_front() {
let right = deque.pop_front()
.unwrap();
left = match op {
Ast::Op(op) => op.apply(left, right),
// Only operators should ever appear here.
_ => unreachable!(),
};
}
// Empty intersections like `< & [a] >` are not allowed.
if let Ast::Empty = left { panic!("An empty class `<[]>` is not allowed!") }
left
}
fn next(&mut self) -> bool {
self.pos += 1;
self.pos != self.data.len()
}
}