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
94
95
96
97
98
99
100
101
102
103
104
105
|
use crate::tokenizer::{self, If, Keyword::*, Loop};
pub type SplitWithMetadata<'a> = Vec<(&'a str, Option<Metadata>)>;
pub const EXPRESSION_DELIMITERS: &[char] = &[
';', '{', '}',
];
#[derive(Clone, Copy, Debug)]
pub enum Scope {
If(If),
Loop(Loop),
}
#[derive(Debug)]
pub enum Metadata {
StartScope,
EndScope,
}
#[derive(Debug)]
pub enum ExprT<'a> {
StartOrStop(bool),
Decision((&'a str, Scope)),
IO(&'a str),
Process(&'a str),
}
#[derive(Debug)]
pub struct Expr<'a> {
pub expr: ExprT<'a>,
pub meta: Option<Metadata>,
}
pub fn delimit(s: &str) -> SplitWithMetadata<'_> {
s.split_inclusive([
';', '{', '}',
])
.fold(Vec::new(), |mut acc, part| {
if let Some((i, ch)) = part
.char_indices()
.next_back()
{
acc.push((
if ch == ';' || ch == '{' || ch == '}' {
part[..i].trim()
} else {
part.trim()
},
None,
));
match ch {
'{' => {
if let Some((_, meta)) = acc.last_mut() {
*meta = Some(Metadata::StartScope);
}
}
'}' => {
if let Some((_, meta)) = acc.last_mut() {
*meta = Some(Metadata::EndScope);
}
}
_ => {}
}
}
acc
})
}
pub fn process(strs: SplitWithMetadata<'_>) -> Vec<Expr<'_>> {
let mut exprs = Vec::new();
for (str, meta) in strs {
let mut exp: Option<ExprT> = None;
// TODO: fix one line if else as not delimited by {}
for s in str.split_whitespace() {
if let Some(token) = tokenizer::parse(s) {
exp = match token {
If(t) => Some(ExprT::Decision((str, Scope::If(t.to_owned())))),
Loop(t) => Some(ExprT::Decision((str, Scope::Loop(t.to_owned())))),
Throw => Some(ExprT::IO(str)),
IO => Some(ExprT::IO(str)),
}
}
}
match exp {
Some(expr) => exprs.push(Expr {
expr,
meta,
}),
None => exprs.push(Expr {
expr: ExprT::Process(str),
meta,
}),
}
}
exprs
}
pub fn parse(str: &str) -> Vec<Expr<'_>> {
process(delimit(str))
}
|