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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
use std::str::FromStr;
use thiserror::Error;
use super::LogicalExpression;
/// Represents the possible errors that can occur during parsing of a logical expression.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Error)]
pub enum ParseError<E> {
/// Represents an error that occurred while parsing a condition.
#[error("Error parsing condition: {0}")]
ConditionParsing(E),
/// Represents an error when there is no matching opening bracket for a closing bracket.
#[error("No matching opening bracket")]
NoMatchingOpeningBracket,
/// Represents an error when there is no matching closing bracket for an opening bracket.
#[error("No matching closing bracket")]
NoMatchingClosingBracket,
/// Represents an error when there are multiple operators without a condition between them.
#[error("Multiple operators without a condition between them")]
MultipleOperators,
/// Represents an error when there is an empty condition.
#[error("Empty condition")]
EmptyCondition,
/// Represents an error when there is a leading operator without a preceding condition.
#[error("Leading operator without a preceding condition")]
LeadingOperator,
/// Represents an error when there is a trailing operator without a following condition.
#[error("Trailing operator without a following condition")]
TrailingOperator,
/// Represents an error when there is a condition before an opening bracket.
#[error("Condition before an opening bracket")]
ConditionBeforeOpeningBracket,
/// Represents an error when there is a condition after a closing bracket.
#[error("Condition after a closing bracket")]
ConditionAfterClosingBracket,
}
impl<E> From<E> for ParseError<E> {
fn from(err: E) -> Self {
Self::ConditionParsing(err)
}
}
struct Lists<T> {
or: Vec<T>,
and: Vec<T>,
}
impl<T> Lists<T> {
const fn new() -> Self {
Self {
or: Vec::new(),
and: Vec::new(),
}
}
}
impl<C: FromStr> LogicalExpression<C> {
/// Parses a logical expression from a string.
///
/// # Errors
/// Returns a `ParseError` if the string is not a valid logical expression, or if parsing a condition fails.
#[inline]
pub fn parse(s: &str) -> Result<Self, ParseError<<C as FromStr>::Err>> {
Self::parse_with(s, FromStr::from_str)
}
}
impl<C> LogicalExpression<C> {
/// Parses a logical expression from a string using a custom parsing function.
///
/// The `parse_condition` function is used to parse individual conditions from string slices.
///
/// # Errors
/// Returns a `ParseError` if the string is not a valid logical expression, or if `parse_condition` fails.
pub fn parse_with<F, E>(s: &str, mut parse_condition: F) -> Result<Self, ParseError<E>>
where
F: FnMut(&str) -> Result<C, E>,
{
Self::parse_with_expression(s, |s| Ok(Self::Condition(parse_condition(s)?)))
}
/// Parses a logical expression from a string using a custom parsing function.
///
/// The `parse_expression` function is used to parse individual conditions from string slices into expressions.
///
/// # Errors
/// Returns a `ParseError` if the string is not a valid logical expression, or if `parse_expression` fails.
pub fn parse_with_expression<F, E>(
s: &str,
mut parse_expression: F,
) -> Result<Self, ParseError<E>>
where
F: FnMut(&str) -> Result<Self, E>,
{
enum After {
Start,
Operator,
}
let mut bracket_stack = Vec::new();
let mut lists = Lists::new();
let mut start = 0;
let mut end = 0;
let mut state = Some(After::Start);
for c in s.chars() {
let clen = c.len_utf8();
match c {
'|' | '&' => {
let condition = s[start..end].trim();
if let Some(after) = state {
if condition.is_empty() {
return Err(match after {
After::Start => ParseError::LeadingOperator,
After::Operator => ParseError::MultipleOperators,
});
}
lists.and.push(parse_expression(condition)?);
} else if !condition.is_empty() {
return Err(ParseError::ConditionAfterClosingBracket);
}
start = end + clen;
if c == '|' {
lists.or.push(Self::and(lists.and));
lists.and = Vec::new();
}
state = Some(After::Operator);
}
'(' => {
let condition = s[start..end].trim();
if !condition.is_empty() {
return Err(ParseError::ConditionBeforeOpeningBracket);
}
bracket_stack.push(lists);
lists = Lists::new();
start = end + clen;
state = Some(After::Start);
}
')' => {
let Some(mut stack_lists) = bracket_stack.pop() else {
return Err(ParseError::NoMatchingOpeningBracket);
};
let condition = s[start..end].trim();
if let Some(after) = state {
if condition.is_empty() {
return Err(match after {
After::Start => ParseError::EmptyCondition,
After::Operator => ParseError::TrailingOperator,
});
}
lists.and.push(parse_expression(condition)?);
} else if !condition.is_empty() {
return Err(ParseError::ConditionAfterClosingBracket);
}
start = end + clen;
lists.or.push(Self::and(lists.and));
stack_lists.and.push(Self::or(lists.or));
lists = stack_lists;
state = None;
}
_ => (),
}
end += clen;
}
if !bracket_stack.is_empty() {
return Err(ParseError::NoMatchingClosingBracket);
}
let condition = s[start..end].trim();
if let Some(after) = state {
if condition.is_empty() {
return Err(match after {
After::Start => ParseError::EmptyCondition,
After::Operator => ParseError::TrailingOperator,
});
}
lists.and.push(parse_expression(condition)?);
} else if !condition.is_empty() {
return Err(ParseError::ConditionAfterClosingBracket);
}
lists.or.push(Self::and(lists.and));
Ok(Self::or(lists.or))
}
}