substrait_explain/parser/
common.rs1use std::collections::HashMap;
2use std::{fmt, thread};
3
4use pest::error::{Error as PestError, ErrorVariant};
5use pest::iterators::{Pair, Pairs};
6use pest::{Parser as PestParser, Span};
7use pest_derive::Parser as PestDeriveParser;
8use substrait::proto::sort_field::SortDirection;
9use thiserror::Error;
10
11use crate::extensions::SimpleExtensions;
12use crate::extensions::simple::MissingReference;
13
14#[derive(PestDeriveParser)]
15#[grammar = "parser/expression_grammar.pest"] pub(crate) struct ExpressionParser;
17
18#[derive(Error, Debug, Clone)]
21#[error("{kind} Error parsing {message}:\n{error}")]
22pub struct MessageParseError {
23 message: &'static str,
24 kind: ErrorKind,
25 #[source]
26 error: Box<PestError<Rule>>,
27}
28
29#[derive(Debug, Clone)]
30pub(crate) enum ErrorKind {
31 Syntax,
32 InvalidValue,
33 Lookup(MissingReference),
34}
35
36impl MessageParseError {
37 pub(crate) fn invalid(message: &'static str, span: Span, description: impl ToString) -> Self {
38 let error = PestError::new_from_span(
39 ErrorVariant::CustomError {
40 message: description.to_string(),
41 },
42 span,
43 );
44 Self::new(message, ErrorKind::InvalidValue, Box::new(error))
45 }
46
47 pub(crate) fn lookup(
48 message: &'static str,
49 missing: MissingReference,
50 span: Span,
51 description: impl ToString,
52 ) -> Self {
53 let error = PestError::new_from_span(
54 ErrorVariant::CustomError {
55 message: description.to_string(),
56 },
57 span,
58 );
59 Self::new(message, ErrorKind::Lookup(missing), Box::new(error))
60 }
61}
62
63impl MessageParseError {
64 pub(crate) fn new(message: &'static str, kind: ErrorKind, error: Box<PestError<Rule>>) -> Self {
65 Self {
66 message,
67 kind,
68 error,
69 }
70 }
71}
72
73impl fmt::Display for ErrorKind {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 match self {
76 ErrorKind::Syntax => write!(f, "Syntax"),
77 ErrorKind::InvalidValue => write!(f, "Invalid value"),
78 ErrorKind::Lookup(e) => write!(f, "Invalid reference ({e})"),
79 }
80 }
81}
82
83pub(crate) fn unwrap_single_pair(pair: Pair<Rule>) -> Pair<Rule> {
84 let mut pairs = pair.into_inner();
85 let pair = pairs.next().unwrap();
86 assert_eq!(pairs.next(), None);
87 pair
88}
89
90pub(crate) fn unescape_string(pair: Pair<Rule>) -> String {
103 let s = pair.as_str();
104
105 let (opener, closer) = match pair.as_rule() {
107 Rule::string_literal => ('\'', '\''),
108 Rule::quoted_name => ('"', '"'),
109 _ => panic!(
110 "unescape_string called with unexpected rule: {:?}",
111 pair.as_rule()
112 ),
113 };
114
115 let mut result = String::new();
116 let mut chars = s.chars();
117 let first = chars.next().expect("Empty string literal");
118
119 assert_eq!(
120 first, opener,
121 "Expected opening quote '{opener}', got '{first}'"
122 );
123
124 while let Some(c) = chars.next() {
126 match c {
127 c if c == closer => {
128 assert_eq!(
130 chars.next(),
131 None,
132 "Unexpected characters after closing quote"
133 );
134 break;
135 }
136 '\\' => {
137 let next = chars
138 .next()
139 .expect("Incomplete escape sequence at end of string");
140 match next {
141 'n' => result.push('\n'),
142 't' => result.push('\t'),
143 'r' => result.push('\r'),
144 _ => result.push(next),
147 }
148 }
149 _ => result.push(c),
150 }
151 }
152 result
153}
154
155pub(crate) trait ParsePair: Sized {
159 fn rule() -> Rule;
161
162 fn message() -> &'static str;
164
165 fn parse_pair(pair: Pair<Rule>) -> Self;
169
170 fn parse_str(s: &str) -> Result<Self, MessageParseError> {
171 let mut pairs = <ExpressionParser as PestParser<Rule>>::parse(Self::rule(), s)
172 .map_err(|e| MessageParseError::new(Self::message(), ErrorKind::Syntax, Box::new(e)))?;
173 assert_eq!(pairs.as_str(), s);
174 let pair = pairs.next().unwrap();
175 assert_eq!(pairs.next(), None);
176 Ok(Self::parse_pair(pair))
177 }
178}
179
180pub(crate) trait ScopedParsePair: Sized {
185 fn rule() -> Rule;
187
188 fn message() -> &'static str;
190
191 fn parse_pair(
195 extensions: &SimpleExtensions,
196 pair: Pair<Rule>,
197 ) -> Result<Self, MessageParseError>;
198}
199
200pub(crate) fn iter_pairs(pair: Pairs<'_, Rule>) -> RuleIter<'_> {
201 RuleIter {
202 iter: pair,
203 done: false,
204 }
205}
206
207pub(crate) struct RuleIter<'a> {
208 iter: Pairs<'a, Rule>,
209 done: bool,
211}
212
213impl<'a> From<Pairs<'a, Rule>> for RuleIter<'a> {
214 fn from(iter: Pairs<'a, Rule>) -> Self {
215 RuleIter { iter, done: false }
216 }
217}
218
219impl<'a> RuleIter<'a> {
220 pub(crate) fn peek(&self) -> Option<Pair<'a, Rule>> {
221 self.iter.peek()
222 }
223
224 pub(crate) fn try_pop(&mut self, rule: Rule) -> Option<Pair<'a, Rule>> {
226 match self.peek() {
227 Some(pair) if pair.as_rule() == rule => {
228 self.iter.next();
229 Some(pair)
230 }
231 _ => None,
232 }
233 }
234
235 pub(crate) fn pop(&mut self, rule: Rule) -> Pair<'a, Rule> {
237 let pair = self.iter.next().expect("expected another pair");
238 assert_eq!(
239 pair.as_rule(),
240 rule,
241 "expected rule {:?}, got {:?}",
242 rule,
243 pair.as_rule()
244 );
245 pair
246 }
247
248 pub(crate) fn parse_if_next<T: ParsePair>(&mut self) -> Option<T> {
250 match self.peek() {
251 Some(pair) if pair.as_rule() == T::rule() => {
252 self.iter.next();
253 Some(T::parse_pair(pair))
254 }
255 _ => None,
256 }
257 }
258
259 pub(crate) fn parse_if_next_scoped<T: ScopedParsePair>(
261 &mut self,
262 extensions: &SimpleExtensions,
263 ) -> Option<Result<T, MessageParseError>> {
264 match self.peek() {
265 Some(pair) if pair.as_rule() == T::rule() => {
266 self.iter.next();
267 Some(T::parse_pair(extensions, pair))
268 }
269 _ => None,
270 }
271 }
272
273 pub(crate) fn parse_next<T: ParsePair>(&mut self) -> T {
275 let pair = self.iter.next().unwrap();
276 T::parse_pair(pair)
277 }
278
279 pub(crate) fn parse_next_scoped<T: ScopedParsePair>(
281 &mut self,
282 extensions: &SimpleExtensions,
283 ) -> Result<T, MessageParseError> {
284 let pair = self.iter.next().unwrap();
285 T::parse_pair(extensions, pair)
286 }
287
288 pub(crate) fn done(mut self) {
289 self.done = true;
290 let next = match self.iter.next() {
294 Some(pair) if pair.as_rule() == Rule::EOI => self.iter.next(),
295 other => other,
296 };
297 assert_eq!(next, None);
298 }
299}
300
301impl Drop for RuleIter<'_> {
306 fn drop(&mut self) {
307 if self.done || thread::panicking() {
308 return;
309 }
310 assert_eq!(self.iter.next(), None);
312 }
313}
314
315pub(crate) struct ParsedNamedArgs<'a> {
318 map: HashMap<&'a str, Pair<'a, Rule>>,
319}
320
321impl<'a> ParsedNamedArgs<'a> {
322 pub(crate) fn new(pairs: Pairs<'a, Rule>, rule: Rule) -> Result<Self, MessageParseError> {
323 let mut map = HashMap::new();
324 for pair in pairs {
325 assert_eq!(pair.as_rule(), rule);
326 let mut inner = pair.clone().into_inner();
327 let name_pair = inner.next().unwrap();
328 let value_pair = inner.next().unwrap();
329 assert_eq!(inner.next(), None);
330 let name = name_pair.as_str();
331 if map.contains_key(name) {
332 return Err(MessageParseError::invalid(
333 "NamedArg",
334 name_pair.as_span(),
335 format!("Duplicate argument: {name}"),
336 ));
337 }
338 map.insert(name, value_pair);
339 }
340 Ok(Self { map })
341 }
342
343 pub(crate) fn pop(mut self, name: &str, rule: Rule) -> (Self, Option<Pair<'a, Rule>>) {
345 let pair = self.map.remove(name).inspect(|pair| {
346 assert_eq!(pair.as_rule(), rule, "Rule mismatch for argument {name}");
347 });
348 (self, pair)
349 }
350
351 pub(crate) fn done(self) -> Result<(), MessageParseError> {
353 if let Some((name, pair)) = self.map.iter().next() {
354 return Err(MessageParseError::invalid(
355 "NamedArgExtractor",
356 pair.as_span(),
358 format!("Unknown argument: {name}"),
359 ));
360 }
361 Ok(())
362 }
363}
364
365pub(crate) fn sort_direction_from_str(
372 name: &str,
373 span: pest::Span,
374) -> Result<SortDirection, MessageParseError> {
375 match name {
376 "AscNullsFirst" => Ok(SortDirection::AscNullsFirst),
377 "AscNullsLast" => Ok(SortDirection::AscNullsLast),
378 "DescNullsFirst" => Ok(SortDirection::DescNullsFirst),
379 "DescNullsLast" => Ok(SortDirection::DescNullsLast),
380 other => Err(MessageParseError::invalid(
381 "SortDirection",
382 span,
383 format!("Unknown sort direction: {other}"),
384 )),
385 }
386}
387
388#[cfg(test)]
389pub(crate) mod test_support {
390 use pest::Parser as PestParser;
391
392 use super::{ErrorKind, ExpressionParser, MessageParseError, ParsePair, ScopedParsePair};
393 use crate::extensions::SimpleExtensions;
394
395 pub(crate) trait Parse {
399 fn parse(input: &str) -> Result<Self, MessageParseError>
400 where
401 Self: Sized;
402 }
403
404 impl<T: ParsePair> Parse for T {
405 fn parse(input: &str) -> Result<Self, MessageParseError> {
406 T::parse_str(input)
407 }
408 }
409
410 pub(crate) trait ScopedParse: Sized {
415 fn parse(extensions: &SimpleExtensions, input: &str) -> Result<Self, MessageParseError>
416 where
417 Self: Sized;
418 }
419
420 impl<T: ScopedParsePair> ScopedParse for T {
421 fn parse(extensions: &SimpleExtensions, input: &str) -> Result<Self, MessageParseError> {
422 let mut pairs = ExpressionParser::parse(Self::rule(), input).map_err(|e| {
423 MessageParseError::new(Self::message(), ErrorKind::Syntax, Box::new(e))
424 })?;
425 assert_eq!(pairs.as_str(), input);
426 let pair = pairs.next().unwrap();
427 assert_eq!(pairs.next(), None);
428 Self::parse_pair(extensions, pair)
429 }
430 }
431}