Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -554,8 +554,8 @@ fast-float2 = "0.2.3"
gix = "0.71.0"
indent = "0.1.1"
logos = "0.12.1"
nom = "7.1.1"
nom-rule = "0.4"
nom = "8.0.0"
nom-rule = "0.5.1"
pratt = "0.4.0"
rspack-codespan-reporting = "0.11"
rustc-demangle = "0.1"
Expand Down
19 changes: 14 additions & 5 deletions src/query/ast/benches/bench.rs

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/query/ast/src/parser/comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use nom::Parser;
use nom_rule::rule;

use super::expr::literal_string;
Expand All @@ -33,7 +34,7 @@ pub fn comment(i: Input) -> IResult<Statement> {
| #comment_column: "`COMMENT [IF EXISTS] ON COLUMN <table_name>.<column_name> IS '<string_literal>'`"
| #comment_network_policy: "`COMMENT [IF EXISTS] ON NETWORK POLICY <policy_name> IS '<string_literal>'`"
| #comment_password_policy: "`COMMENT [IF EXISTS] ON PASSWORD POLICY <policy_name> IS '<string_literal>'`"
)(i)
).parse(i)
}

fn comment_table(i: Input) -> IResult<Statement> {
Expand Down
159 changes: 95 additions & 64 deletions src/query/ast/src/parser/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,26 @@
use std::cell::RefCell;
use std::rc::Rc;

use nom::branch::alt;
use nom::combinator::consumed;
use nom::combinator::map;
use nom::multi::many1;
pub use nom::branch::alt;
pub use nom::branch::permutation;
pub use nom::combinator::consumed;
pub use nom::combinator::map;
pub use nom::combinator::not;
pub use nom::combinator::value;
pub use nom::multi::many1;
use nom::sequence::terminated;
use nom::Offset;
use nom::Slice;
use nom::Parser;
use nom_rule::rule;
use pratt::PrattError;
use pratt::PrattParser;
use pratt::Precedence;

pub fn parser_fn<'a, O, P>(mut parser: P) -> impl FnMut(Input<'a>) -> IResult<'a, O>
where P: nom::Parser<Input<'a>, Output = O, Error = Error<'a>> {
move |input| parser.parse(input)
}

use crate::ast::quote::QuotedIdent;
use crate::ast::ColumnID;
use crate::ast::DatabaseRef;
Expand Down Expand Up @@ -85,7 +93,8 @@ pub fn lambda_params(i: Input) -> IResult<Vec<Identifier>> {
rule!(
#single_param
| #multi_params
)(i)
)
.parse(i)
}

pub fn ident(i: Input) -> IResult<Identifier> {
Expand Down Expand Up @@ -116,7 +125,8 @@ pub fn stage_name(i: Input) -> IResult<Identifier> {
rule!(
#plain_ident
| #anonymous_stage
)(i)
)
.parse(i)
}

fn plain_identifier(
Expand All @@ -134,7 +144,8 @@ fn plain_identifier(
quote: None,
ident_type: IdentifierType::None,
},
)(i)
)
.parse(i)
}
}

Expand Down Expand Up @@ -193,7 +204,8 @@ fn identifier_variable(i: Input) -> IResult<Identifier> {
quote: None,
ident_type: IdentifierType::Variable,
},
)(i)
)
.parse(i)
}

fn non_reserved_identifier(
Expand All @@ -205,7 +217,8 @@ fn non_reserved_identifier(
| #quoted_identifier
| #identifier_hole
| #identifier_variable
)(i)
)
.parse(i)
}
}

Expand All @@ -228,7 +241,8 @@ fn non_reserved_keyword(
pub fn database_ref(i: Input) -> IResult<DatabaseRef> {
map(dot_separated_idents_1_to_2, |(catalog, database)| {
DatabaseRef { catalog, database }
})(i)
})
.parse(i)
}

pub fn table_ref(i: Input) -> IResult<TableRef> {
Expand All @@ -242,7 +256,8 @@ pub fn table_ref(i: Input) -> IResult<TableRef> {
table,
with_options,
},
)(i)
)
.parse(i)
}

pub fn set_type(i: Input) -> IResult<SetType> {
Expand All @@ -259,7 +274,8 @@ pub fn set_type(i: Input) -> IResult<SetType> {
},
None => SetType::SettingsSession,
},
)(i)
)
.parse(i)
}

pub fn table_reference_only(i: Input) -> IResult<TableReference> {
Expand All @@ -279,7 +295,8 @@ pub fn table_reference_only(i: Input) -> IResult<TableReference> {
unpivot: None,
sample: None,
},
)(i)
)
.parse(i)
}

pub fn column_reference_only(i: Input) -> IResult<(TableReference, Identifier)> {
Expand All @@ -304,40 +321,51 @@ pub fn column_reference_only(i: Input) -> IResult<(TableReference, Identifier)>
column,
)
},
)(i)
)
.parse(i)
}

pub fn column_id(i: Input) -> IResult<ColumnID> {
alt((
map_res(rule! { ColumnPosition }, |token| {
let name = token.text().to_string();
let pos = name[1..]
.parse::<usize>()
.map_err(|e| nom::Err::Failure(e.into()))?;
if pos == 0 {
return Err(nom::Err::Failure(ErrorKind::Other(
"column position must be greater than 0",
)));
}
Ok(ColumnID::Position(crate::ast::ColumnPosition {
pos,
name,
span: Some(token.span),
}))
}),
// ROW could be a column name for compatibility
map_res(rule! {ROW}, |token| {
Ok(ColumnID::Name(Identifier::from_name(
transform_span(&[token.clone()]),
"row",
)))
}),
map_res(rule! { #ident }, |ident| Ok(ColumnID::Name(ident))),
))(i)
alt((column_position, column_row, column_ident)).parse(i)
}

pub fn column_position(i: Input) -> IResult<ColumnID> {
map_res(rule! { ColumnPosition }, |token| {
let name = token.text().to_string();
let pos = name[1..]
.parse::<usize>()
.map_err(|e| nom::Err::Failure(e.into()))?;
if pos == 0 {
return Err(nom::Err::Failure(ErrorKind::Other(
"column position must be greater than 0",
)));
}
Ok(ColumnID::Position(crate::ast::ColumnPosition {
pos,
name,
span: Some(token.span),
}))
})
.parse(i)
}

pub fn column_row(i: Input) -> IResult<ColumnID> {
// ROW could be a column name for compatibility
map_res(rule! {ROW}, |token| {
Ok(ColumnID::Name(Identifier::from_name(
transform_span(&[token.clone()]),
"row",
)))
})
.parse(i)
}

pub fn column_ident(i: Input) -> IResult<ColumnID> {
map_res(rule! { #ident }, |ident| Ok(ColumnID::Name(ident))).parse(i)
}

pub fn variable_ident(i: Input) -> IResult<String> {
map(rule! { IdentVariable }, |t| t.text()[1..].to_string())(i)
map(rule! { IdentVariable }, |t| t.text()[1..].to_string()).parse(i)
}

/// Parse one to two idents separated by a dot, fulfilling from the right.
Expand All @@ -352,7 +380,8 @@ pub fn dot_separated_idents_1_to_2(i: Input) -> IResult<(Option<Identifier>, Ide
(ident1, None) => (None, ident1),
(ident0, Some((_, ident1))) => (Some(ident0), ident1),
},
)(i)
)
.parse(i)
}

/// Parse one to three idents separated by a dot, fulfilling from the right.
Expand All @@ -371,7 +400,8 @@ pub fn dot_separated_idents_1_to_3(
(ident1, Some((_, ident2, None))) => (None, Some(ident1), ident2),
(ident0, Some((_, ident1, Some((_, ident2))))) => (Some(ident0), Some(ident1), ident2),
},
)(i)
)
.parse(i)
}

/// Parse two to four idents separated by a dot, fulfilling from the right.
Expand All @@ -396,36 +426,37 @@ pub fn dot_separated_idents_2_to_4(
(Some(ident0), Some(ident1), ident2, ident3)
}
},
)(i)
)
.parse(i)
}

pub fn comma_separated_list0<'a, T>(
item: impl FnMut(Input<'a>) -> IResult<'a, T>,
item: impl nom::Parser<Input<'a>, Output = T, Error = Error<'a>>,
) -> impl FnMut(Input<'a>) -> IResult<'a, Vec<T>> {
separated_list0(match_text(","), item)
}

pub fn comma_separated_list0_ignore_trailing<'a, T>(
item: impl FnMut(Input<'a>) -> IResult<'a, T>,
) -> impl FnMut(Input<'a>) -> IResult<'a, Vec<T>> {
item: impl nom::Parser<Input<'a>, Output = T, Error = Error<'a>>,
) -> impl nom::Parser<Input<'a>, Output = Vec<T>, Error = Error<'a>> {
nom::multi::separated_list0(match_text(","), item)
}

pub fn comma_separated_list1_ignore_trailing<'a, T>(
item: impl FnMut(Input<'a>) -> IResult<'a, T>,
) -> impl FnMut(Input<'a>) -> IResult<'a, Vec<T>> {
item: impl nom::Parser<Input<'a>, Output = T, Error = Error<'a>>,
) -> impl nom::Parser<Input<'a>, Output = Vec<T>, Error = Error<'a>> {
nom::multi::separated_list1(match_text(","), item)
}

pub fn semicolon_terminated_list1<'a, T>(
item: impl FnMut(Input<'a>) -> IResult<'a, T>,
) -> impl FnMut(Input<'a>) -> IResult<'a, Vec<T>> {
item: impl nom::Parser<Input<'a>, Output = T, Error = Error<'a>>,
) -> impl nom::Parser<Input<'a>, Output = Vec<T>, Error = Error<'a>> {
many1(terminated(item, match_text(";")))
}

pub fn comma_separated_list1<'a, T>(
item: impl FnMut(Input<'a>) -> IResult<'a, T>,
) -> impl FnMut(Input<'a>) -> IResult<'a, Vec<T>> {
item: impl nom::Parser<Input<'a>, Output = T, Error = Error<'a>>,
) -> impl nom::Parser<Input<'a>, Output = Vec<T>, Error = Error<'a>> {
separated_list1(match_text(","), item)
}

Expand All @@ -437,9 +468,9 @@ pub fn separated_list0<I, O, O2, E, F, G>(
mut f: F,
) -> impl FnMut(I) -> nom::IResult<I, Vec<O>, E>
where
I: Clone + nom::InputLength,
F: nom::Parser<I, O, E>,
G: nom::Parser<I, O2, E>,
I: Clone + nom::Input,
F: nom::Parser<I, Output = O, Error = E>,
G: nom::Parser<I, Output = O2, Error = E>,
E: nom::error::ParseError<I>,
{
move |mut i: I| {
Expand Down Expand Up @@ -487,9 +518,9 @@ pub fn separated_list1<I, O, O2, E, F, G>(
mut f: F,
) -> impl FnMut(I) -> nom::IResult<I, Vec<O>, E>
where
I: Clone + nom::InputLength,
F: nom::Parser<I, O, E>,
G: nom::Parser<I, O2, E>,
I: Clone + nom::Input,
F: nom::Parser<I, Output = O, Error = E>,
G: nom::Parser<I, Output = O2, Error = E>,
E: nom::error::ParseError<I>,
{
move |mut i: I| {
Expand Down Expand Up @@ -537,7 +568,7 @@ pub fn map_res<'a, O1, O2, F, G>(
mut f: G,
) -> impl FnMut(Input<'a>) -> IResult<'a, O2>
where
F: nom::Parser<Input<'a>, O1, Error<'a>>,
F: nom::Parser<Input<'a>, Output = O1, Error = Error<'a>>,
G: FnMut(O1) -> Result<O2, nom::Err<ErrorKind>>,
{
move |input: Input| {
Expand Down Expand Up @@ -565,7 +596,7 @@ pub fn error_hint<'a, O, F>(
message: &'static str,
) -> impl FnMut(Input<'a>) -> IResult<'a, ()>
where
F: nom::Parser<Input<'a>, O, Error<'a>>,
F: nom::Parser<Input<'a>, Output = O, Error = Error<'a>>,
{
move |input: Input| match match_error.parse(input) {
Ok(_) => Err(nom::Err::Error(Error::from_error_kind(
Expand Down Expand Up @@ -682,7 +713,7 @@ where
}

pub fn check_template_mode<'a, O, F>(mut parser: F) -> impl FnMut(Input<'a>) -> IResult<'a, O>
where F: nom::Parser<Input<'a>, O, Error<'a>> {
where F: nom::Parser<Input<'a>, Output = O, Error = Error<'a>> {
move |input: Input| {
parser.parse(input).and_then(|(i, res)| {
if input.mode.is_template() {
Expand Down Expand Up @@ -715,7 +746,7 @@ macro_rules! declare_experimental_feature {
mut parser: F,
) -> impl FnMut(Input<'a>) -> IResult<'a, O>
where
F: nom::Parser<Input<'a>, O, Error<'a>>,
F: nom::Parser<Input<'a>, Output = O, Error = Error<'a>>,
{
move |input: Input| {
parser.parse(input).and_then(|(i, res)| {
Expand Down
Loading
Loading