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 let mut bracket_stack = Vec::new();
90 let mut lists = Lists::new();
91 let mut start = 0;
92 let mut end = 0;
93
94 enum After {
95 Start,
96 Operator,
97 }
98
99 let mut state = Some(After::Start);
100
101 for c in s.chars() {
102 let clen = c.len_utf8();
103 match c {
104 '|' | '&' => {
105 let condition = s[start..end].trim();
106 if let Some(after) = state {
107 if condition.is_empty() {
108 return Err(match after {
109 After::Start => ParseError::LeadingOperator,
110 After::Operator => ParseError::MultipleOperators,
111 });
112 }
113 lists.and.push(Self::Condition(parse_condition(condition)?));
114 } else if !condition.is_empty() {
115 return Err(ParseError::ConditionAfterClosingBracket);
116 }
117
118 start = end + clen;
119
120 if c == '|' {
121 lists.or.push(Self::and(lists.and));
122 lists.and = Vec::new();
123 }
124
125 state = Some(After::Operator);
126 }
127 '(' => {
128 let condition = s[start..end].trim();
129 if !condition.is_empty() {
130 return Err(ParseError::ConditionBeforeOpeningBracket);
131 }
132
133 bracket_stack.push(lists);
134 lists = Lists::new();
135
136 start = end + clen;
137
138 state = Some(After::Start);
139 }
140 ')' => {
141 let Some(mut stack_lists) = bracket_stack.pop() else {
142 return Err(ParseError::NoMatchingOpeningBracket);
143 };
144
145 let condition = s[start..end].trim();
146 if let Some(after) = state {
147 if condition.is_empty() {
148 return Err(match after {
149 After::Start => ParseError::EmptyCondition,
150 After::Operator => ParseError::TrailingOperator,
151 });
152 }
153 lists.and.push(Self::Condition(parse_condition(condition)?));
154 } else if !condition.is_empty() {
155 return Err(ParseError::ConditionAfterClosingBracket);
156 }
157
158 start = end + clen;
159
160 lists.or.push(Self::and(lists.and));
161
162 stack_lists.and.push(Self::or(lists.or));
163
164 lists = stack_lists;
165
166 state = None;
167 }
168 _ => (),
169 }
170 end += clen;
171 }
172
173 if !bracket_stack.is_empty() {
174 return Err(ParseError::NoMatchingClosingBracket);
175 }
176
177 let condition = s[start..end].trim();
178 if let Some(after) = state {
179 if condition.is_empty() {
180 return Err(match after {
181 After::Start => ParseError::EmptyCondition,
182 After::Operator => ParseError::TrailingOperator,
183 });
184 }
185 lists.and.push(Self::Condition(parse_condition(condition)?));
186 } else if !condition.is_empty() {
187 return Err(ParseError::ConditionAfterClosingBracket);
188 }
189
190 lists.or.push(Self::and(lists.and));
191
192 Ok(Self::or(lists.or))
193 }
194}