databend_common_ast/parser/
common.rs

1// Copyright 2021 Datafuse Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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
333/// Parse one to two idents separated by a dot, fulfilling from the right.
334///
335/// Example: `table.column`
336pub 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
348/// Parse one to three idents separated by a dot, fulfilling from the right.
349///
350/// Example: `db.table.column`
351///          `catalog.db.table`
352pub 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
367/// Parse two to four idents separated by a dot, fulfilling from the right.
368///
369/// Example: `catalog.db.table.column`
370pub 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
422/// A fork of `separated_list0` from nom, but never forgive parser error
423/// after a separator is encountered, and always forgive the first element
424/// failure.
425pub 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                    // infinite loop check: the parser must always consume
453                    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
473/// A fork of `separated_list1` from nom, but never forgive parser error
474/// after a separator is encountered.
475pub 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        // Parse the first element
489        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                    // infinite loop check: the parser must always consume
504                    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
524/// A fork of `map_res` from nom, but doesn't require `FromExternalError`.
525pub 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
552/// Try to find an error pattern that user may have made, and hint them with suggestion.
553pub 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            // Rollback parsing footprint on unused expr elements.
594            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                // It's safe to slice one more token because input must contain EOI.
615                .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        // Rollback parsing footprint on unused expr elements.
621        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");