1use nom::branch::alt;
16use nom::combinator::consumed;
17use nom::combinator::map;
18use nom::multi::many1;
19use nom::sequence::terminated;
20use nom::Offset;
21use nom::Slice;
22use nom_rule::rule;
23use pratt::PrattError;
24use pratt::PrattParser;
25use pratt::Precedence;
26
27use crate::ast::quote::QuotedIdent;
28use crate::ast::ColumnID;
29use crate::ast::DatabaseRef;
30use crate::ast::Identifier;
31use crate::ast::IdentifierType;
32use crate::ast::SetType;
33use crate::ast::TableRef;
34use crate::ast::TableReference;
35use crate::parser::input::Input;
36use crate::parser::input::WithSpan;
37use crate::parser::query::with_options;
38use crate::parser::token::*;
39use crate::parser::Error;
40use crate::parser::ErrorKind;
41use crate::Range;
42use crate::Span;
43
44pub type IResult<'a, Output> = nom::IResult<Input<'a>, Output, Error<'a>>;
45
46pub fn match_text(text: &'static str) -> impl FnMut(Input) -> IResult<&Token> {
47 move |i| match i.tokens.first().filter(|token| token.text() == text) {
48 Some(token) => Ok((i.slice(1..), token)),
49 _ => Err(nom::Err::Error(Error::from_error_kind(
50 i,
51 ErrorKind::ExpectText(text),
52 ))),
53 }
54}
55
56pub fn match_token(kind: TokenKind) -> impl FnMut(Input) -> IResult<&Token> {
57 move |i| match i.tokens.first().filter(|token| token.kind == kind) {
58 Some(token) => Ok((i.slice(1..), token)),
59 _ => Err(nom::Err::Error(Error::from_error_kind(
60 i,
61 ErrorKind::ExpectToken(kind),
62 ))),
63 }
64}
65
66pub fn any_token(i: Input) -> IResult<&Token> {
67 match i.tokens.first().filter(|token| token.kind != EOI) {
68 Some(token) => Ok((i.slice(1..), token)),
69 _ => Err(nom::Err::Error(Error::from_error_kind(
70 i,
71 ErrorKind::Other("expected any token but reached the end"),
72 ))),
73 }
74}
75
76pub fn lambda_params(i: Input) -> IResult<Vec<Identifier>> {
77 let single_param = map(rule! {#ident}, |param| vec![param]);
78 let multi_params = map(
79 rule! { "(" ~ #comma_separated_list1(ident) ~ ")" },
80 |(_, params, _)| params,
81 );
82 rule!(
83 #single_param
84 | #multi_params
85 )(i)
86}
87
88pub fn ident(i: Input) -> IResult<Identifier> {
89 non_reserved_identifier(|token| token.is_reserved_ident(false))(i)
90}
91
92pub fn grant_ident(i: Input) -> IResult<Identifier> {
93 non_reserved_identifier(|token| token.is_grant_reserved_ident(false, true))(i)
94}
95
96pub fn plain_ident(i: Input) -> IResult<Identifier> {
97 plain_identifier(|token| token.is_reserved_ident(false))(i)
98}
99
100pub fn ident_after_as(i: Input) -> IResult<Identifier> {
101 non_reserved_identifier(|token| token.is_reserved_ident(true))(i)
102}
103
104pub fn function_name(i: Input) -> IResult<Identifier> {
105 non_reserved_identifier(|token| token.is_reserved_function_name())(i)
106}
107
108pub fn stage_name(i: Input) -> IResult<Identifier> {
109 let anonymous_stage = map(consumed(rule! { "~" }), |(span, _)| {
110 Identifier::from_name(transform_span(span.tokens), "~")
111 });
112
113 rule!(
114 #plain_ident
115 | #anonymous_stage
116 )(i)
117}
118
119fn plain_identifier(
120 is_reserved_keyword: fn(&TokenKind) -> bool,
121) -> impl FnMut(Input) -> IResult<Identifier> {
122 move |i| {
123 map(
124 rule! {
125 Ident
126 | #non_reserved_keyword(is_reserved_keyword)
127 },
128 |token| Identifier {
129 span: transform_span(&[token.clone()]),
130 name: token.text().to_string(),
131 quote: None,
132 ident_type: IdentifierType::None,
133 },
134 )(i)
135 }
136}
137
138fn quoted_identifier(i: Input) -> IResult<Identifier> {
139 match_token(LiteralString)(i).and_then(|(i2, token)| {
140 if token
141 .text()
142 .chars()
143 .next()
144 .filter(|c| i.dialect.is_ident_quote(*c))
145 .is_some()
146 {
147 let QuotedIdent(ident, quote) = token.text().parse().map_err(|_| {
148 nom::Err::Error(Error::from_error_kind(
149 i,
150 ErrorKind::Other("invalid identifier"),
151 ))
152 })?;
153 Ok((i2, Identifier {
154 span: transform_span(&[token.clone()]),
155 name: ident,
156 quote: Some(quote),
157 ident_type: IdentifierType::None,
158 }))
159 } else {
160 Err(nom::Err::Error(Error::from_error_kind(
161 i,
162 ErrorKind::ExpectToken(Ident),
163 )))
164 }
165 })
166}
167
168fn identifier_hole(i: Input) -> IResult<Identifier> {
169 check_template_mode(map(
170 consumed(rule! {
171 IDENTIFIER ~ ^"(" ~ #template_hole ~ ^")"
172 }),
173 |(span, (_, _, name, _))| Identifier {
174 span: transform_span(span.tokens),
175 name,
176 quote: None,
177 ident_type: IdentifierType::Hole,
178 },
179 ))(i)
180}
181
182fn identifier_variable(i: Input) -> IResult<Identifier> {
183 map(
184 consumed(rule! {
185 IDENTIFIER ~ ^"(" ~ ^#variable_ident ~ ^")"
186 }),
187 |(span, (_, _, name, _))| Identifier {
188 span: transform_span(span.tokens),
189 name,
190 quote: None,
191 ident_type: IdentifierType::Variable,
192 },
193 )(i)
194}
195
196fn non_reserved_identifier(
197 is_reserved_keyword: fn(&TokenKind) -> bool,
198) -> impl FnMut(Input) -> IResult<Identifier> {
199 move |i| {
200 rule!(
201 #plain_identifier(is_reserved_keyword)
202 | #quoted_identifier
203 | #identifier_hole
204 | #identifier_variable
205 )(i)
206 }
207}
208
209fn non_reserved_keyword(
210 is_reserved_keyword: fn(&TokenKind) -> bool,
211) -> impl FnMut(Input) -> IResult<&Token> {
212 move |i: Input| match i
213 .tokens
214 .first()
215 .filter(|token| token.kind.is_keyword() && !is_reserved_keyword(&token.kind))
216 {
217 Some(token) => Ok((i.slice(1..), token)),
218 _ => Err(nom::Err::Error(Error::from_error_kind(
219 i,
220 ErrorKind::ExpectToken(Ident),
221 ))),
222 }
223}
224
225pub fn database_ref(i: Input) -> IResult<DatabaseRef> {
226 map(dot_separated_idents_1_to_2, |(catalog, database)| {
227 DatabaseRef { catalog, database }
228 })(i)
229}
230
231pub fn table_ref(i: Input) -> IResult<TableRef> {
232 map(
233 rule! {
234 #dot_separated_idents_1_to_3 ~ #with_options?
235 },
236 |((catalog, database, table), with_options)| TableRef {
237 catalog,
238 database,
239 table,
240 with_options,
241 },
242 )(i)
243}
244
245pub fn set_type(i: Input) -> IResult<SetType> {
246 map(
247 rule! {
248 (GLOBAL | SESSION | VARIABLE)?
249 },
250 |res| match res {
251 Some(token) => match token.kind {
252 GLOBAL => SetType::SettingsGlobal,
253 SESSION => SetType::SettingsSession,
254 VARIABLE => SetType::Variable,
255 _ => unreachable!(),
256 },
257 None => SetType::SettingsSession,
258 },
259 )(i)
260}
261
262pub fn table_reference_only(i: Input) -> IResult<TableReference> {
263 map(
264 consumed(rule! {
265 #dot_separated_idents_1_to_3
266 }),
267 |(span, (catalog, database, table))| TableReference::Table {
268 span: transform_span(span.tokens),
269 catalog,
270 database,
271 table,
272 alias: None,
273 temporal: None,
274 with_options: None,
275 pivot: None,
276 unpivot: None,
277 sample: None,
278 },
279 )(i)
280}
281
282pub fn column_reference_only(i: Input) -> IResult<(TableReference, Identifier)> {
283 map(
284 consumed(rule! {
285 #dot_separated_idents_2_to_4
286 }),
287 |(span, (catalog, database, table, column))| {
288 (
289 TableReference::Table {
290 span: transform_span(span.tokens),
291 catalog,
292 database,
293 table,
294 alias: None,
295 temporal: None,
296 with_options: None,
297 pivot: None,
298 unpivot: None,
299 sample: None,
300 },
301 column,
302 )
303 },
304 )(i)
305}
306
307pub fn column_id(i: Input) -> IResult<ColumnID> {
308 alt((
309 map_res(rule! { ColumnPosition }, |token| {
310 let name = token.text().to_string();
311 let pos = name[1..]
312 .parse::<usize>()
313 .map_err(|e| nom::Err::Failure(e.into()))?;
314 if pos == 0 {
315 return Err(nom::Err::Failure(ErrorKind::Other(
316 "column position must be greater than 0",
317 )));
318 }
319 Ok(ColumnID::Position(crate::ast::ColumnPosition {
320 pos,
321 name,
322 span: Some(token.span),
323 }))
324 }),
325 map_res(rule! { #ident }, |ident| Ok(ColumnID::Name(ident))),
326 ))(i)
327}
328
329pub fn variable_ident(i: Input) -> IResult<String> {
330 map(rule! { IdentVariable }, |t| t.text()[1..].to_string())(i)
331}
332
333pub fn dot_separated_idents_1_to_2(i: Input) -> IResult<(Option<Identifier>, Identifier)> {
337 map(
338 rule! {
339 #ident ~ ( "." ~ #ident )?
340 },
341 |res| match res {
342 (ident1, None) => (None, ident1),
343 (ident0, Some((_, ident1))) => (Some(ident0), ident1),
344 },
345 )(i)
346}
347
348pub fn dot_separated_idents_1_to_3(
353 i: Input,
354) -> IResult<(Option<Identifier>, Option<Identifier>, Identifier)> {
355 map(
356 rule! {
357 #ident ~ ( "." ~ #ident ~ ( "." ~ #ident )? )?
358 },
359 |res| match res {
360 (ident2, None) => (None, None, ident2),
361 (ident1, Some((_, ident2, None))) => (None, Some(ident1), ident2),
362 (ident0, Some((_, ident1, Some((_, ident2))))) => (Some(ident0), Some(ident1), ident2),
363 },
364 )(i)
365}
366
367pub fn dot_separated_idents_2_to_4(
371 i: Input,
372) -> IResult<(
373 Option<Identifier>,
374 Option<Identifier>,
375 Identifier,
376 Identifier,
377)> {
378 map(
379 rule! {
380 #ident ~ "." ~ #ident ~ ( "." ~ #ident ~ ( "." ~ #ident )? )?
381 },
382 |res| match res {
383 (ident2, _, ident3, None) => (None, None, ident2, ident3),
384 (ident1, _, ident2, Some((_, ident3, None))) => (None, Some(ident1), ident2, ident3),
385 (ident0, _, ident1, Some((_, ident2, Some((_, ident3))))) => {
386 (Some(ident0), Some(ident1), ident2, ident3)
387 }
388 },
389 )(i)
390}
391
392pub fn comma_separated_list0<'a, T>(
393 item: impl FnMut(Input<'a>) -> IResult<'a, T>,
394) -> impl FnMut(Input<'a>) -> IResult<'a, Vec<T>> {
395 separated_list0(match_text(","), item)
396}
397
398pub fn comma_separated_list0_ignore_trailing<'a, T>(
399 item: impl FnMut(Input<'a>) -> IResult<'a, T>,
400) -> impl FnMut(Input<'a>) -> IResult<'a, Vec<T>> {
401 nom::multi::separated_list0(match_text(","), item)
402}
403
404pub fn comma_separated_list1_ignore_trailing<'a, T>(
405 item: impl FnMut(Input<'a>) -> IResult<'a, T>,
406) -> impl FnMut(Input<'a>) -> IResult<'a, Vec<T>> {
407 nom::multi::separated_list1(match_text(","), item)
408}
409
410pub fn semicolon_terminated_list1<'a, T>(
411 item: impl FnMut(Input<'a>) -> IResult<'a, T>,
412) -> impl FnMut(Input<'a>) -> IResult<'a, Vec<T>> {
413 many1(terminated(item, match_text(";")))
414}
415
416pub fn comma_separated_list1<'a, T>(
417 item: impl FnMut(Input<'a>) -> IResult<'a, T>,
418) -> impl FnMut(Input<'a>) -> IResult<'a, Vec<T>> {
419 separated_list1(match_text(","), item)
420}
421
422pub fn separated_list0<I, O, O2, E, F, G>(
426 mut sep: G,
427 mut f: F,
428) -> impl FnMut(I) -> nom::IResult<I, Vec<O>, E>
429where
430 I: Clone + nom::InputLength,
431 F: nom::Parser<I, O, E>,
432 G: nom::Parser<I, O2, E>,
433 E: nom::error::ParseError<I>,
434{
435 move |mut i: I| {
436 let mut res = Vec::new();
437
438 match f.parse(i.clone()) {
439 Err(_) => return Ok((i, res)),
440 Ok((i1, o)) => {
441 res.push(o);
442 i = i1;
443 }
444 }
445
446 loop {
447 let len = i.input_len();
448 match sep.parse(i.clone()) {
449 Err(nom::Err::Error(_)) => return Ok((i, res)),
450 Err(e) => return Err(e),
451 Ok((i1, _)) => {
452 if i1.input_len() == len {
454 return Err(nom::Err::Error(E::from_error_kind(
455 i1,
456 nom::error::ErrorKind::SeparatedList,
457 )));
458 }
459
460 match f.parse(i1.clone()) {
461 Err(e) => return Err(e),
462 Ok((i2, o)) => {
463 res.push(o);
464 i = i2;
465 }
466 }
467 }
468 }
469 }
470 }
471}
472
473pub fn separated_list1<I, O, O2, E, F, G>(
476 mut sep: G,
477 mut f: F,
478) -> impl FnMut(I) -> nom::IResult<I, Vec<O>, E>
479where
480 I: Clone + nom::InputLength,
481 F: nom::Parser<I, O, E>,
482 G: nom::Parser<I, O2, E>,
483 E: nom::error::ParseError<I>,
484{
485 move |mut i: I| {
486 let mut res = Vec::new();
487
488 match f.parse(i.clone()) {
490 Err(e) => return Err(e),
491 Ok((i1, o)) => {
492 res.push(o);
493 i = i1;
494 }
495 }
496
497 loop {
498 let len = i.input_len();
499 match sep.parse(i.clone()) {
500 Err(nom::Err::Error(_)) => return Ok((i, res)),
501 Err(e) => return Err(e),
502 Ok((i1, _)) => {
503 if i1.input_len() == len {
505 return Err(nom::Err::Error(E::from_error_kind(
506 i1,
507 nom::error::ErrorKind::SeparatedList,
508 )));
509 }
510
511 match f.parse(i1.clone()) {
512 Err(e) => return Err(e),
513 Ok((i2, o)) => {
514 res.push(o);
515 i = i2;
516 }
517 }
518 }
519 }
520 }
521 }
522}
523
524pub fn map_res<'a, O1, O2, F, G>(
526 mut parser: F,
527 mut f: G,
528) -> impl FnMut(Input<'a>) -> IResult<'a, O2>
529where
530 F: nom::Parser<Input<'a>, O1, Error<'a>>,
531 G: FnMut(O1) -> Result<O2, nom::Err<ErrorKind>>,
532{
533 move |input: Input| {
534 let i = input;
535 let bt = i.backtrace.clone();
536 let (rest, o1) = parser.parse(input)?;
537 match f(o1) {
538 Ok(o2) => Ok((rest, o2)),
539 Err(nom::Err::Error(e)) => {
540 i.backtrace.restore(bt);
541 Err(nom::Err::Error(Error::from_error_kind(i, e)))
542 }
543 Err(nom::Err::Failure(e)) => {
544 i.backtrace.restore(bt);
545 Err(nom::Err::Failure(Error::from_error_kind(i, e)))
546 }
547 Err(nom::Err::Incomplete(_)) => unreachable!(),
548 }
549 }
550}
551
552pub fn error_hint<'a, O, F>(
554 mut match_error: F,
555 message: &'static str,
556) -> impl FnMut(Input<'a>) -> IResult<'a, ()>
557where
558 F: nom::Parser<Input<'a>, O, Error<'a>>,
559{
560 move |input: Input| match match_error.parse(input) {
561 Ok(_) => Err(nom::Err::Error(Error::from_error_kind(
562 input,
563 ErrorKind::Other(message),
564 ))),
565 Err(_) => Ok((input, ())),
566 }
567}
568
569pub fn transform_span(tokens: &[Token]) -> Span {
570 Some(Range {
571 start: tokens.first().unwrap().span.start,
572 end: tokens.last().unwrap().span.end,
573 })
574}
575
576pub fn run_pratt_parser<'a, I, P, E>(
577 mut parser: P,
578 iter: &I,
579 rest: Input<'a>,
580 input: Input<'a>,
581) -> IResult<'a, P::Output>
582where
583 E: std::fmt::Debug,
584 P: PrattParser<I, Input = WithSpan<'a, E>, Error = &'static str>,
585 I: Iterator<Item = P::Input> + ExactSizeIterator + Clone,
586{
587 let mut iter_cloned = iter.clone();
588 let mut iter = iter.clone().peekable();
589 let len = iter.len();
590 let expr = parser
591 .parse_input(&mut iter, Precedence(0))
592 .map_err(|err| {
593 input.backtrace.clear();
595
596 let err_kind = match err {
597 PrattError::EmptyInput => ErrorKind::Other("expecting an operand"),
598 PrattError::UnexpectedNilfix(_) => ErrorKind::Other("unable to parse the element"),
599 PrattError::UnexpectedPrefix(_) => {
600 ErrorKind::Other("unable to parse the prefix operator")
601 }
602 PrattError::UnexpectedInfix(_) => {
603 ErrorKind::Other("missing lhs or rhs for the binary operator")
604 }
605 PrattError::UnexpectedPostfix(_) => {
606 ErrorKind::Other("unable to parse the postfix operator")
607 }
608 PrattError::UserError(err) => ErrorKind::Other(err),
609 };
610
611 let span = iter_cloned
612 .nth(len - iter.len() - 1)
613 .map(|elem| elem.span)
614 .unwrap_or_else(|| rest.slice(..1));
616
617 nom::Err::Error(Error::from_error_kind(span, err_kind))
618 })?;
619 if let Some(elem) = iter.peek() {
620 input.backtrace.clear();
622 Ok((input.slice(input.offset(&elem.span)..), expr))
623 } else {
624 Ok((rest, expr))
625 }
626}
627
628pub fn check_template_mode<'a, O, F>(mut parser: F) -> impl FnMut(Input<'a>) -> IResult<'a, O>
629where F: nom::Parser<Input<'a>, O, Error<'a>> {
630 move |input: Input| {
631 parser.parse(input).and_then(|(i, res)| {
632 if input.mode.is_template() {
633 Ok((i, res))
634 } else {
635 i.backtrace.clear();
636 let error = Error::from_error_kind(
637 input,
638 ErrorKind::Other("variable is only available in SQL template"),
639 );
640 Err(nom::Err::Failure(error))
641 }
642 })
643 }
644}
645
646pub fn template_hole(i: Input) -> IResult<String> {
647 check_template_mode(map(
648 rule! {
649 ":" ~ ^#plain_ident
650 },
651 |(_, name)| name.name,
652 ))(i)
653}
654
655macro_rules! declare_experimental_feature {
656 ($check_fn_name: ident, $feature_name: literal) => {
657 pub fn $check_fn_name<'a, O, F>(
658 is_exclusive: bool,
659 mut parser: F,
660 ) -> impl FnMut(Input<'a>) -> IResult<'a, O>
661 where
662 F: nom::Parser<Input<'a>, O, Error<'a>>,
663 {
664 move |input: Input| {
665 parser.parse(input).and_then(|(i, res)| {
666 if input.dialect.is_experimental() {
667 Ok((i, res))
668 } else {
669 i.backtrace.clear();
670 let error = Error::from_error_kind(
671 input,
672 ErrorKind::Other(
673 concat!(
674 $feature_name,
675 " only works in experimental dialect, try `set sql_dialect = 'experimental'`"
676 )
677 ),
678 );
679 if is_exclusive {
680 Err(nom::Err::Failure(error))
681 } else {
682 Err(nom::Err::Error(error))
683 }
684 }
685 })
686 }
687 }
688 };
689}
690
691declare_experimental_feature!(check_experimental_chain_function, "chain function");
692declare_experimental_feature!(check_experimental_list_comprehension, "list comprehension");