logical_expressions/
parser.rs1use std::str::FromStr;
2
3use thiserror::Error;
4
5use super::LogicalExpression;
6
7#[derive(Copy, Clone, PartialEq, Eq, Debug, Error)]
9pub enum ParseError<E> {
10 #[error("Error parsing condition: {0}")]
12 ConditionParsing(E),
13
14 #[error("No matching opening bracket")]
16 NoMatchingOpeningBracket,
17
18 #[error("No matching closing bracket")]
20 NoMatchingClosingBracket,
21
22 #[error("Multiple operators without a condition between them")]
24 MultipleOperators,
25
26 #[error("Empty condition")]
28 EmptyCondition,
29
30 #[error("Leading operator without a preceding condition")]
32 LeadingOperator,
33
34 #[error("Trailing operator without a following condition")]
36 TrailingOperator,
37
38 #[error("Condition before an opening bracket")]
40 ConditionBeforeOpeningBracket,
41
42 #[error("Condition after a closing bracket")]
44 ConditionAfterClosingBracket,
45}
46
47impl<E> From<E> for ParseError<E> {
48 fn from(err: E) -> Self {
49 Self::ConditionParsing(err)
50 }
51}
52
53struct Lists<T> {
54 or: Vec<T>,
55 and: Vec<T>,
56}
57
58impl<T> Lists<T> {
59 fn new() -> Self {
60 Self {
61 or: Vec::new(),
62 and: Vec::new(),
63 }
64 }
65}
66
67impl<C: FromStr> LogicalExpression<C> {
68 #[inline]
73 pub fn parse(s: &str) -> Result<Self, ParseError<<C as FromStr>::Err>> {
74 Self::parse_with(s, FromStr::from_str)
75 }
76}
77
78impl<C> LogicalExpression<C> {
79 pub fn parse_with<F, E>(s: &str, mut parse_condition: F) -> Result<Self, ParseError<E>>
86 where
87 F: FnMut(&str) -> Result<C, E>,
88 {
89 Self::parse_with_expression(s, |s| Ok(Self::Condition(parse_condition(s)?)))
90 }
91
92 pub fn parse_with_expression<F, E>(
99 s: &str,
100 mut parse_expression: F,
101 ) -> Result<Self, ParseError<E>>
102 where
103 F: FnMut(&str) -> Result<Self, E>,
104 {
105 let mut bracket_stack = Vec::new();
106 let mut lists = Lists::new();
107 let mut start = 0;
108 let mut end = 0;
109
110 enum After {
111 Start,
112 Operator,
113 }
114
115 let mut state = Some(After::Start);
116
117 for c in s.chars() {
118 let clen = c.len_utf8();
119 match c {
120 '|' | '&' => {
121 let condition = s[start..end].trim();
122 if let Some(after) = state {
123 if condition.is_empty() {
124 return Err(match after {
125 After::Start => ParseError::LeadingOperator,
126 After::Operator => ParseError::MultipleOperators,
127 });
128 }
129 lists.and.push(parse_expression(condition)?);
130 } else if !condition.is_empty() {
131 return Err(ParseError::ConditionAfterClosingBracket);
132 }
133
134 start = end + clen;
135
136 if c == '|' {
137 lists.or.push(Self::and(lists.and));
138 lists.and = Vec::new();
139 }
140
141 state = Some(After::Operator);
142 }
143 '(' => {
144 let condition = s[start..end].trim();
145 if !condition.is_empty() {
146 return Err(ParseError::ConditionBeforeOpeningBracket);
147 }
148
149 bracket_stack.push(lists);
150 lists = Lists::new();
151
152 start = end + clen;
153
154 state = Some(After::Start);
155 }
156 ')' => {
157 let Some(mut stack_lists) = bracket_stack.pop() else {
158 return Err(ParseError::NoMatchingOpeningBracket);
159 };
160
161 let condition = s[start..end].trim();
162 if let Some(after) = state {
163 if condition.is_empty() {
164 return Err(match after {
165 After::Start => ParseError::EmptyCondition,
166 After::Operator => ParseError::TrailingOperator,
167 });
168 }
169 lists.and.push(parse_expression(condition)?);
170 } else if !condition.is_empty() {
171 return Err(ParseError::ConditionAfterClosingBracket);
172 }
173
174 start = end + clen;
175
176 lists.or.push(Self::and(lists.and));
177
178 stack_lists.and.push(Self::or(lists.or));
179
180 lists = stack_lists;
181
182 state = None;
183 }
184 _ => (),
185 }
186 end += clen;
187 }
188
189 if !bracket_stack.is_empty() {
190 return Err(ParseError::NoMatchingClosingBracket);
191 }
192
193 let condition = s[start..end].trim();
194 if let Some(after) = state {
195 if condition.is_empty() {
196 return Err(match after {
197 After::Start => ParseError::EmptyCondition,
198 After::Operator => ParseError::TrailingOperator,
199 });
200 }
201 lists.and.push(parse_expression(condition)?);
202 } else if !condition.is_empty() {
203 return Err(ParseError::ConditionAfterClosingBracket);
204 }
205
206 lists.or.push(Self::and(lists.and));
207
208 Ok(Self::or(lists.or))
209 }
210}