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
use crate::prog_gen::{GroupType, PGM};
use crate::Result;
use crate::ast::{Node, Processor, Return};
/// Implements continue on a fail branch for V93K by removing any bin nodes that are
/// siblings of continue nodes. The continue nodes are also removed in the process since
/// they have now served their function.
pub struct ContinueImplementer {
cont: bool,
}
pub fn run(node: &Node<PGM>) -> Result<Node<PGM>> {
let mut p = ContinueImplementer { cont: false };
let ast = node.process(&mut p)?.unwrap();
Ok(ast)
}
impl Processor<PGM> for ContinueImplementer {
fn on_node(&mut self, node: &Node<PGM>) -> crate::Result<Return<PGM>> {
Ok(match &node.attrs {
PGM::OnFailed(_) => {
let orig = self.cont;
if node
.children
.iter()
.any(|n| matches!(n.attrs, PGM::Continue))
{
self.cont = true;
}
let children = node.process_and_box_children(self)?;
self.cont = orig;
if children.is_empty() {
Return::None
} else {
Return::Replace(node.updated(None, Some(children), None))
}
}
PGM::Continue => Return::None,
PGM::Bin(_, _, _) => {
if self.cont {
Return::None
} else {
Return::Unmodified
}
}
PGM::Group(_, _, kind, _) => match kind {
GroupType::Flow => {
let on_fail = node
.children
.iter()
.find(|n| matches!(n.attrs, PGM::OnFailed(_)));
if let Some(on_fail) = on_fail {
let orig = self.cont;
if on_fail
.children
.iter()
.any(|n| matches!(n.attrs, PGM::Continue))
{
self.cont = true;
}
let children = node.process_and_box_children(self)?;
self.cont = orig;
Return::Replace(node.updated(None, Some(children), None))
} else {
Return::ProcessChildren
}
}
_ => Return::ProcessChildren,
},
_ => Return::ProcessChildren,
})
}
}