1use crate::query::{
14 Matcher,
15 parse::{
16 parser::{format_unexpected_token, format_unknown_key},
17 tokenizer::{Token, TokenKind, TokenSpan},
18 },
19 queryable::{QueryKeyValue, Queryable},
20};
21
22#[derive(Debug, thiserror::Error)]
23#[allow(missing_docs)]
24pub enum Error<E: Queryable>
25where
26 <E::KeyValue as QueryKeyValue>::Err: std::fmt::Debug + std::fmt::Display,
27{
28 #[error(fmt = format_unexpected_token)]
29 UnexpectedToken { expected: TokenKind, found: Token },
30
31 #[error("The input stream contained {found} but expected one of: {expected:?}")]
34 UnexpectedTokens {
35 expected: Vec<TokenKind>,
37
38 found: Token,
40 },
41
42 #[error(fmt = format_unknown_key::<E>)]
44 UnknownKey {
45 err: <E::KeyValue as QueryKeyValue>::Err,
47
48 key: String,
50
51 at: TokenSpan,
53 },
54
55 #[error("The input stream countained a unknown value '{value}' for the default key: {err}")]
57 UnknownDefaultKey {
58 value: String,
60
61 err: <<E as Queryable>::KeyValue as QueryKeyValue>::Err,
63
64 at: TokenSpan,
66 },
67
68 #[error("Expected a LHS for {at}, but got nothing.")]
71 MissingLhs {
72 at: Token,
74 },
75}
76
77impl<E: Queryable> From<super::parsing::Error<E>> for Error<E>
78where
79 <E::KeyValue as QueryKeyValue>::Err: std::fmt::Debug + std::fmt::Display,
80{
81 fn from(value: super::parsing::Error<E>) -> Self {
82 match value {
83 super::parsing::Error::UnexpectedToken { expected, found } => {
84 Self::UnexpectedToken { expected, found }
85 }
86 super::parsing::Error::UnknownKey { err, key, at } => Self::UnknownKey { err, key, at },
87 }
88 }
89}
90
91pub(super) struct Parser<'a, E: Queryable> {
92 parent: &'a mut super::Parser<'a, E>,
93}
94
95impl<'a, E: Queryable> Parser<'a, E>
96where
97 <E::KeyValue as QueryKeyValue>::Err: std::fmt::Debug + std::fmt::Display,
98{
99 pub(super) fn parse(parent: &'a mut super::Parser<'a, E>) -> Result<Matcher<E>, Error<E>> {
100 let mut me = Parser { parent };
101 me.actual_parse(None)
102 }
103
104 fn actual_parse(&mut self, matcher: Option<Matcher<E>>) -> Result<Matcher<E>, Error<E>> {
105 fn unwrap_matcher<E: Queryable>(
106 matcher: Option<Matcher<E>>,
107 token: Token,
108 ) -> Result<Matcher<E>, Error<E>>
109 where
110 <E::KeyValue as QueryKeyValue>::Err: std::fmt::Debug + std::fmt::Display,
111 {
112 if let Some(matcher) = matcher {
113 Ok(matcher)
114 } else {
115 Err(Error::MissingLhs { at: token })
116 }
117 }
118
119 self.clean();
120
121 let peek_next = self.parent.tokenizer.peek();
122 match peek_next.kind {
123 TokenKind::And => {
124 let token = self.parent.expect(TokenKind::And)?;
125 self.parent.expect(TokenKind::Break)?;
126
127 let next = Matcher::And {
128 lhs: Box::new(unwrap_matcher(matcher, token)?),
129 rhs: Box::new(self.parse_matcher()?),
130 };
131 self.actual_parse(Some(next))
132 }
133 TokenKind::Or => {
134 let token = self.parent.expect(TokenKind::Or)?;
135 self.parent.expect(TokenKind::Break)?;
136
137 let next = Matcher::Or {
138 lhs: Box::new(unwrap_matcher(matcher, token)?),
139 rhs: Box::new(self.parse_matcher()?),
140 };
141 self.actual_parse(Some(next))
142 }
143
144 TokenKind::ParenOpen | TokenKind::Char(_) => {
145 let next = merge_matcher(matcher, self.parse_matcher()?);
146
147 self.actual_parse(Some(next))
148 }
149
150 TokenKind::Colon => Err(Error::UnexpectedTokens {
151 expected: vec![
152 TokenKind::And,
153 TokenKind::Or,
154 TokenKind::ParenOpen,
155 TokenKind::Char('*'),
156 ],
157 found: peek_next,
158 }),
159 TokenKind::Eof => Ok(matcher.expect("This should be some at this point")),
160 TokenKind::Break | TokenKind::ParenClose => unreachable!("Sorted out above."),
161 }
162 }
163
164 fn clean(&mut self) {
165 while let kind @ (TokenKind::ParenClose | TokenKind::Break) =
167 self.parent.tokenizer.peek().kind()
168 {
169 let next = self.parent.tokenizer.next_token();
170 assert_eq!(next.kind, kind);
171 }
172 }
173
174 fn parse_matcher(&mut self) -> Result<Matcher<E>, Error<E>> {
175 let peek_next = self.parent.tokenizer.peek();
176
177 match peek_next.kind {
178 TokenKind::ParenOpen => self.parse_and_or_or(),
179 TokenKind::Char(_) => self.parse_match_key(),
180 TokenKind::Colon
181 | TokenKind::Eof
182 | TokenKind::ParenClose
183 | TokenKind::And
184 | TokenKind::Or => Err(Error::UnexpectedTokens {
185 expected: vec![TokenKind::ParenOpen, TokenKind::Char('*')],
186 found: peek_next,
187 }),
188 TokenKind::Break => {
189 self.parent.expect(TokenKind::Break)?;
190 self.parse_matcher()
191 }
192 }
193 }
194
195 fn parse_match_key(&mut self) -> Result<Matcher<E>, Error<E>> {
196 let key_tokens = self
201 .parent
202 .take_while(|t| matches!(t, TokenKind::Char(_)))?;
203 let key = if TokenKind::Colon == self.parent.tokenizer.peek().kind {
204 self.parent.expect(TokenKind::Colon)?;
206 let (value, value_span_end) = {
207 let value_tokens = self
208 .parent
209 .take_while(|t| matches!(t, TokenKind::Char(_)))?;
210 (
211 super::Parser::<'a, E>::parse_value_from(&value_tokens),
212 value_tokens.last().map_or(0, |last| last.span.stop),
213 )
214 };
215
216 self.parent
217 .parse_key_from(&key_tokens, value, value_span_end)?
218 } else {
219 let value = super::Parser::<'a, E>::parse_value_from(&key_tokens);
223 E::KeyValue::from_value(self.parent.user_state, value.clone()).map_err(|err| {
224 Error::UnknownDefaultKey {
225 value,
226 err,
227 at: TokenSpan {
228 start: key_tokens.first().expect("Exists").span.start,
229 stop: key_tokens.last().expect("Exists").span.stop,
230 },
231 }
232 })?
233 };
234
235 Ok(Matcher::Match { key_value: key })
236 }
237
238 fn parse_and_or_or(&mut self) -> Result<Matcher<E>, Error<E>> {
239 self.parent.expect(TokenKind::ParenOpen)?;
240 let lhs = Box::new(self.parse_matcher()?);
241 self.parent.expect(TokenKind::Break)?;
242
243 self.clean();
246
247 let mode = {
248 let next = self.parent.tokenizer.next_token();
249 match next.kind {
250 TokenKind::And => TokenKind::And,
251 TokenKind::Or => TokenKind::Or,
252 _ => {
253 return Err(Error::UnexpectedTokens {
254 expected: vec![TokenKind::And, TokenKind::Or],
255 found: next,
256 });
257 }
258 }
259 };
260
261 self.parent.expect(TokenKind::Break)?;
262 let rhs = Box::new(self.parse_matcher()?);
263
264 if self.parent.tokenizer.peek().kind() == TokenKind::ParenClose {
268 self.parent.expect(TokenKind::ParenClose)?;
269 }
270
271 if mode == TokenKind::And {
272 Ok(Matcher::And { lhs, rhs })
273 } else if mode == TokenKind::Or {
274 Ok(Matcher::Or { lhs, rhs })
275 } else {
276 unreachable!("This should have been filtered out in the match above");
277 }
278 }
279}
280
281fn merge_matcher<E: Queryable>(old: Option<Matcher<E>>, new: Matcher<E>) -> Matcher<E> {
282 if let Some(old) = old {
283 Matcher::And {
284 lhs: Box::new(old),
285 rhs: Box::new(new),
286 }
287 } else {
288 new
289 }
290}
291
292#[cfg(test)]
293mod test {
294 use pretty_assertions::assert_eq;
295
296 use crate::query::{
297 Matcher::{And, Match, Or},
298 ParseMode, Query,
299 parse::parser::test::{
300 QueryTestKey1::{Value1, Value2},
301 QueryTestKeyValue::{Key1, Key2, Key3},
302 QueryTestObj, query,
303 },
304 };
305
306 #[test]
307 fn test_default_key() {
308 let input = "(value1 AND 'state p2 ')";
309 let query = Query::<QueryTestObj>::from_continuous_str(&(), input, ParseMode::Relaxed)
310 .map_err(|err| panic!("{err}"))
311 .unwrap();
312
313 assert_eq!(
314 query,
315 query! {
316 And {
317 lhs: {Match (Key2, "value1")},
318 rhs: {Match (Key2, "state p2 \u{f0d58}")}
319 }
320 }
321 );
322 }
323
324 #[test]
325 fn test_and_defaults() {
326 let input = "key1:value1 key2:other key3:20";
327 let query = Query::<QueryTestObj>::from_continuous_str(&(), input, ParseMode::Relaxed)
328 .map_err(|err| panic!("{err}"))
329 .unwrap();
330
331 assert_eq!(
332 query,
333 query! {
334 And {
335 lhs: {And {
336 lhs: {Match(Key1, Value1)},
337 rhs: {Match(Key2, "other")},
338 }},
339 rhs: {Match(Key3, 20)}
340 }
341 },
342 );
343 }
344
345 #[test]
346 fn test_full_defaults() {
347 let input = "value1 other 20";
348 let query = Query::<QueryTestObj>::from_continuous_str(&(), input, ParseMode::Relaxed)
349 .map_err(|err| panic!("{err}"))
350 .unwrap();
351
352 assert_eq!(
353 query,
354 query! {
355 And {
356 lhs: {
357 And {
358 lhs: {Match(Key2, "value1")},
359 rhs: {Match(Key2, "other")},
360 },
361 },
362 rhs: {Match(Key2,"20")}
363 }
364 },
365 );
366 }
367
368 #[test]
369 fn test_and_chain() {
370 let input = "key1:value1 AND key1:value2 AND key2:value3 OR key3:21";
371 let query = Query::<QueryTestObj>::from_continuous_str(&(), input, ParseMode::Relaxed)
372 .map_err(|err| panic!("{err}"))
373 .unwrap();
374
375 assert_eq!(
376 query,
377 query! {
378 Or {
379 lhs: {And {
380 lhs: {And {
381 lhs: {Match(Key1, Value1)},
382 rhs: {Match(Key1, Value2)}
383 }},
384 rhs: {Match(Key2, "value3")},
385 }},
386 rhs: {Match(Key3, 21)},
387 }
388 }
389 );
390 }
391
392 #[test]
393 #[ignore = "The order of the AND and OR conjunctions is wrong."]
394 fn test_full_query() {
395 let input = "(
396 (
397 key1:value1
398 AND 'key2:bitter sweet 🫠'
399 AND key3:20199
400 ) OR (
401 key2:abc
402 AND key1:value2
403 AND key1:value1
404 )
405 ) OR (
406 (
407 c
408 AND key3:20
409 ) OR (
410 orwell
411 AND key3:1902
412 )
413 )"
414 .replace('\n', "");
415 let query = Query::<QueryTestObj>::from_continuous_str(&(), &input, ParseMode::Relaxed)
416 .map_err(|err| panic!("{err}"))
417 .unwrap();
418
419 assert_eq!(
420 query,
421 query! {
422 Or {
423 lhs: {Or {
424 lhs: {And {
425 lhs: {And {
426 lhs: {Match(Key1, Value1)},
427 rhs: {Match(Key2, "bitter sweet 🫠")},
428 }
429 },
430 rhs: {Match(Key3, 20199)},
431 } },
432 rhs: {And {
433 lhs: {And {
434 lhs: {Match(Key2, "abc")},
435 rhs: {Match(Key1, Value2)},
436 }},
437 rhs: {Match(Key1, Value1)},
438 } }
439 } },
440 rhs: {Or {
441 lhs: {And {
442 lhs: {Match(Key2, "c")},
443 rhs: {Match(Key3, 20)},
444 }},
445 rhs: {And {
446 lhs: {Match(Key2, "orwell")},
447 rhs: {Match(Key3, 1902)},
448 }}
449 }
450 },
451 }
452 }
453 );
454 }
455}