diff --git a/Cargo.lock b/Cargo.lock index df8e1aa..180cbfa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,9 +175,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.8" +version = "4.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" dependencies = [ "clap_builder", "clap_derive", @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.8" +version = "4.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" dependencies = [ "anstream", "anstyle", @@ -405,8 +405,8 @@ dependencies = [ name = "jql-parser" version = "7.0.7" dependencies = [ - "nom", "thiserror", + "winnow", ] [[package]] @@ -462,12 +462,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -477,16 +471,6 @@ dependencies = [ "adler", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "num-traits" version = "0.2.17" @@ -986,6 +970,15 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "winnow" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +dependencies = [ + "memchr", +] + [[package]] name = "yansi" version = "0.5.1" diff --git a/crates/jql-parser/Cargo.toml b/crates/jql-parser/Cargo.toml index c8568cd..33a2359 100644 --- a/crates/jql-parser/Cargo.toml +++ b/crates/jql-parser/Cargo.toml @@ -11,8 +11,8 @@ repository = { workspace = true } version = { workspace = true } [dependencies] -nom = "7.1.3" thiserror = { workspace = true } +winnow = "0.5.19" [lib] path = "src/lib.rs" diff --git a/crates/jql-parser/src/combinators.rs b/crates/jql-parser/src/combinators.rs index c14b89d..956cd71 100644 --- a/crates/jql-parser/src/combinators.rs +++ b/crates/jql-parser/src/combinators.rs @@ -1,31 +1,21 @@ -use nom::{ - branch::alt, - bytes::complete::{ - tag, - take_until, - }, - character::complete::{ - char, +use winnow::{ + ascii::{ digit1, multispace0, }, combinator::{ - iterator, - map, - map_res, - opt, - recognize, - value, - }, - error::ParseError, - multi::separated_list1, - sequence::{ + alt, delimited, - pair, + opt, preceded, + repeat, + separated, separated_pair, }, - IResult, + error::ParserError, + token::take_until0, + PResult, + Parser, }; use crate::tokens::{ @@ -35,6 +25,31 @@ use crate::tokens::{ Token, }; +/// Colon. +static COLON: char = ':'; +/// Comma. +static COMMA: char = ','; +/// Curly brace open. +static CURLY_BRACE_OPEN: char = '{'; +/// Curly brace close. +static CURLY_BRACE_CLOSE: char = '}'; +/// Double-quote. +static DOUBLE_QUOTE: char = '"'; +/// Equal. +static EQUAL: char = '='; +/// Square brace open. +static SQUARE_BRACE_OPEN: char = '['; +/// Square brace close. +static SQUARE_BRACE_CLOSE: char = ']'; + +/// False. +static FALSE: &str = "false"; +/// True. +static TRUE: &str = "true"; + +/// Lenses start. +static LENSES_START: &str = "|={"; + /// Flatten operator. static FLATTEN: &str = ".."; /// Group separator. @@ -49,215 +64,169 @@ static TRUNCATE: &str = "!"; /// A combinator which takes an `inner` parser and produces a parser which also /// consumes both leading and trailing whitespaces, returning the output of /// `inner`. -pub(crate) fn trim<'a, F, O, E>(inner: F) -> impl FnMut(&'a str) -> IResult<&'a str, O, E> +pub(crate) fn trim<'a, F, O, E>(inner: F) -> impl Parser<&'a str, O, E> where - E: ParseError<&'a str>, - F: FnMut(&'a str) -> IResult<&'a str, O, E>, + E: ParserError<&'a str>, + F: Parser<&'a str, O, E>, { delimited(multispace0, inner, multispace0) } /// A combinator which parses a stringified number as an `Index`. -pub(crate) fn parse_number(input: &str) -> IResult<&str, Index> { - map_res(recognize(digit1), |index: &str| { - index.parse::().map(Index) - })(input) +pub(crate) fn parse_number(input: &mut &str) -> PResult { + digit1 + .try_map(|index: &str| index.parse::().map(Index)) + .parse_next(input) } /// A combinator which parses a key surrounded by double quotes. -pub(crate) fn parse_key<'a, E>() -> impl FnMut(&'a str) -> IResult<&'a str, &'a str, E> -where - E: ParseError<&'a str>, -{ - trim(delimited(char('"'), take_until(r#"""#), char('"'))) +pub(crate) fn parse_key<'a>(input: &mut &'a str) -> PResult<&'a str> { + trim(delimited(DOUBLE_QUOTE, take_until0(r#"""#), DOUBLE_QUOTE)).parse_next(input) } /// A combinator which parses a list of `Index`. -pub(crate) fn parse_indexes(input: &str) -> IResult<&str, Vec> { - separated_list1(trim(tag(",")), trim(parse_number))(input) +pub(crate) fn parse_indexes(input: &mut &str) -> PResult> { + separated(1.., parse_number, trim(COMMA)).parse_next(input) } /// A combinator which parses a list of keys. -fn parse_keys(input: &str) -> IResult<&str, Vec<&str>> { - separated_list1(trim(tag(",")), trim(parse_key()))(input) +fn parse_keys<'a>(input: &mut &'a str) -> PResult> { + separated(1.., trim(parse_key), trim(COMMA)).parse_next(input) } /// A combinator which parses a list of keys surrounded by curly braces. -pub(crate) fn parse_multi_key<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Vec<&'a str>> { - trim(delimited(char('{'), parse_keys, char('}'))) +pub(crate) fn parse_multi_key<'a>(input: &mut &'a str) -> PResult> { + trim(delimited( + trim(CURLY_BRACE_OPEN), + parse_keys, + trim(CURLY_BRACE_CLOSE), + )) + .parse_next(input) } /// A combinator which parses an array of `Index`. -pub(crate) fn parse_array_index<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Vec> { - trim(delimited(char('['), parse_indexes, char(']'))) +pub(crate) fn parse_array_index(input: &mut &str) -> PResult> { + trim(delimited( + trim(SQUARE_BRACE_OPEN), + parse_indexes, + trim(SQUARE_BRACE_CLOSE), + )) + .parse_next(input) } /// A combinator which parses an array range. -pub(crate) fn parse_array_range<'a>() --> impl FnMut(&'a str) -> IResult<&'a str, (Option, Option)> { +pub(crate) fn parse_array_range(input: &mut &str) -> PResult<(Option, Option)> { trim(delimited( - char('['), - separated_pair(opt(parse_number), tag(":"), opt(parse_number)), - char(']'), + SQUARE_BRACE_OPEN, + separated_pair(opt(parse_number), trim(COLON), opt(parse_number)), + SQUARE_BRACE_CLOSE, )) + .parse_next(input) } /// A combinator which parses a list of index surrounded by curly braces. -pub(crate) fn parse_object_index<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Vec> { - trim(delimited(char('{'), parse_indexes, char('}'))) -} - -/// A combinator which parses an object range. -pub(crate) fn parse_object_range<'a>() --> impl FnMut(&'a str) -> IResult<&'a str, (Option, Option)> { +pub(crate) fn parse_object_index(input: &mut &str) -> PResult> { trim(delimited( - char('{'), - separated_pair(opt(parse_number), tag(":"), opt(parse_number)), - char('}'), + trim(CURLY_BRACE_OPEN), + parse_indexes, + trim(CURLY_BRACE_CLOSE), )) + .parse_next(input) } -/// A combinator which parses a `LensValue::Null`. -pub(crate) fn parse_null_lens_value<'a, E>() -> impl FnMut(&'a str) -> IResult<&'a str, LensValue, E> -where - E: ParseError<&'a str>, -{ - value(LensValue::Null, tag("null")) -} - -/// A combinator which parses a `LensValue::String`. -pub(crate) fn parse_string_lens_value<'a, E>() --> impl FnMut(&'a str) -> IResult<&'a str, LensValue, E> -where - E: ParseError<&'a str>, -{ - map(parse_key(), LensValue::String) -} - -/// A combinator which parses a `LensValue::Number`. -pub(crate) fn parse_number_lens_value(input: &str) -> IResult<&str, LensValue> { - map_res(recognize(digit1), |index: &str| { - index.parse::().map(LensValue::Number) - })(input) -} - -/// A combinator which parses a `LensValue::Bool`. -pub(crate) fn parse_bool_lens_value<'a, E>() -> impl FnMut(&'a str) -> IResult<&'a str, LensValue, E> -where - E: ParseError<&'a str>, -{ - alt(( - map(tag("false"), |_| LensValue::Bool(false)), - map(tag("true"), |_| LensValue::Bool(true)), +/// A combinator which parses an object range. +pub(crate) fn parse_object_range(input: &mut &str) -> PResult<(Option, Option)> { + trim(delimited( + trim(CURLY_BRACE_OPEN), + separated_pair(opt(parse_number), trim(COLON), opt(parse_number)), + trim(CURLY_BRACE_CLOSE), )) + .parse_next(input) } /// A combinator which parses any lens value. -pub(crate) fn parse_lens_value<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, LensValue> { +pub(crate) fn parse_lens_value<'a>(input: &mut &'a str) -> PResult> { alt(( - parse_bool_lens_value(), - parse_null_lens_value(), - parse_number_lens_value, - parse_string_lens_value(), + FALSE.value(LensValue::Bool(false)), + TRUE.value(LensValue::Bool(true)), + "null".value(LensValue::Null), + digit1.try_map(|s: &str| s.parse::().map(LensValue::Number)), + parse_key.map(LensValue::String), )) + .parse_next(input) } - +// /// A combinator which parses a lens key. -fn parse_lens_key(key: &str) -> IResult<&str, Token> { +fn parse_lens_key<'a>(input: &mut &'a str) -> PResult> { alt(( - map(parse_array_index(), Token::ArrayIndexSelector), - map(parse_array_range(), |(start, end)| { - Token::ArrayRangeSelector(Range(start, end)) - }), - map(parse_key(), Token::KeySelector), - map(parse_multi_key(), Token::MultiKeySelector), - map(parse_object_index(), Token::ObjectIndexSelector), - map(parse_object_range(), |(start, end)| { - Token::ObjectRangeSelector(Range(start, end)) - }), - ))(key) + parse_array_index.map(Token::ArrayIndexSelector), + parse_array_range.map(|(start, end)| Token::ArrayRangeSelector(Range(start, end))), + parse_key.map(Token::KeySelector), + parse_multi_key.map(Token::MultiKeySelector), + parse_object_index.map(Token::ObjectIndexSelector), + parse_object_range.map(|(start, end)| Token::ObjectRangeSelector(Range(start, end))), + )) + .parse_next(input) } /// A combinator which parses multiple lens keys. -fn parse_lens_keys(key: &str) -> IResult<&str, Vec> { - let mut parser_iterator = iterator(key, parse_lens_key); - let tokens = parser_iterator.collect::>(); - - let (rest, ()) = parser_iterator.finish()?; - - Ok((rest, tokens)) +fn parse_lens_keys<'a>(input: &mut &'a str) -> PResult>> { + repeat(1.., parse_lens_key).parse_next(input) } /// A combinator which parses a lens. -pub(crate) fn parse_lens<'a>() --> impl FnMut(&'a str) -> IResult<&'a str, (Vec, Option)> { - trim(pair( +pub(crate) fn parse_lens<'a>( + input: &mut &'a str, +) -> PResult<(Vec>, Option>)> { + trim(( parse_lens_keys, - opt(preceded(trim(tag("=")), parse_lens_value())), + opt(preceded(trim(EQUAL), parse_lens_value)), )) + .parse_next(input) } /// A combinator which parses a list of lenses. -pub(crate) fn parse_lenses<'a>() --> impl FnMut(&'a str) -> IResult<&'a str, Vec<(Vec>, Option>)>> { +pub(crate) fn parse_lenses<'a>( + input: &mut &'a str, +) -> PResult>, Option>)>> { trim(delimited( - tag("|={"), - separated_list1(trim(tag(",")), trim(parse_lens())), - char('}'), + trim(LENSES_START), + separated(1.., trim(parse_lens), trim(COMMA)), + trim(CURLY_BRACE_CLOSE), )) + .parse_next(input) } /// A combinator which parses a flatten operator. -pub(crate) fn parse_flatten_operator<'a, E>() -> impl FnMut(&'a str) -> IResult<&'a str, &'a str, E> -where - E: ParseError<&'a str>, -{ - trim(tag(FLATTEN)) +pub(crate) fn parse_flatten_operator<'a>(input: &mut &'a str) -> PResult<&'a str> { + trim(FLATTEN).parse_next(input) } /// A combinator which parses a pipe in operator. -pub(crate) fn parse_pipe_in_operator<'a, E>() -> impl FnMut(&'a str) -> IResult<&'a str, &'a str, E> -where - E: ParseError<&'a str>, -{ - trim(tag(PIPE_IN)) +pub(crate) fn parse_pipe_in_operator<'a>(input: &mut &'a str) -> PResult<&'a str> { + trim(PIPE_IN).parse_next(input) } /// A combinator which parses a pipe out operator. -pub(crate) fn parse_pipe_out_operator<'a, E>() -> impl FnMut(&'a str) -> IResult<&'a str, &'a str, E> -where - E: ParseError<&'a str>, -{ - trim(tag(PIPE_OUT)) +pub(crate) fn parse_pipe_out_operator<'a>(input: &mut &'a str) -> PResult<&'a str> { + trim(PIPE_OUT).parse_next(input) } /// A combinator which parses a truncate operator. -pub(crate) fn parse_truncate_operator<'a, E>() -> impl FnMut(&'a str) -> IResult<&'a str, &'a str, E> -where - E: ParseError<&'a str>, -{ - trim(tag(TRUNCATE)) +pub(crate) fn parse_truncate_operator<'a>(input: &mut &'a str) -> PResult<&'a str> { + trim(TRUNCATE).parse_next(input) } /// A combinator which parses a group separator. -pub(crate) fn parse_group_separator<'a, E>() -> impl FnMut(&'a str) -> IResult<&'a str, &'a str, E> -where - E: ParseError<&'a str>, -{ - trim(tag(GROUP_SEP)) +pub(crate) fn parse_group_separator<'a>(input: &mut &'a str) -> PResult<&'a str> { + trim(GROUP_SEP).parse_next(input) } #[cfg(test)] mod tests { - use nom::{ - bytes::complete::tag, - error::Error, - }; - use super::{ parse_array_index, parse_array_range, - parse_bool_lens_value, parse_flatten_operator, parse_group_separator, parse_indexes, @@ -265,16 +234,12 @@ mod tests { parse_lens, parse_lenses, parse_multi_key, - parse_null_lens_value, parse_number, - parse_number_lens_value, parse_object_index, parse_object_range, parse_pipe_in_operator, parse_pipe_out_operator, - parse_string_lens_value, parse_truncate_operator, - trim, FLATTEN, GROUP_SEP, PIPE_IN, @@ -287,256 +252,174 @@ mod tests { Token, }; - #[test] - fn check_trim() { - assert_eq!( - trim(tag::<&str, &str, Error<_>>("abc"))(" abc ").unwrap(), - ("", "abc") - ); - } - #[test] fn check_parse_number() { - assert_eq!(parse_number("123").unwrap(), ("", Index(123))); - assert!(parse_number("abc").is_err()); - assert!(parse_number("abc123").is_err()); + assert_eq!(parse_number(&mut "123"), Ok(Index(123))); + assert!(parse_number(&mut "abc").is_err()); + assert!(parse_number(&mut "abc123").is_err()); } #[test] fn check_parse_key() { - assert_eq!(parse_key::>()(r#""abc""#).unwrap(), ("", "abc")); - assert!(parse_key::>()("abc").is_err()); + assert_eq!(parse_key(&mut r#""abc""#), Ok("abc")); + assert!(parse_key(&mut "abc").is_err()); } #[test] fn check_parse_indexes() { - assert_eq!(parse_indexes("123").unwrap(), ("", vec![Index(123)])); + assert_eq!(parse_indexes(&mut "123"), Ok(vec![Index(123)])); assert_eq!( - parse_indexes("123,456,789").unwrap(), - ("", vec![Index(123), Index(456), Index(789)]) + parse_indexes(&mut "123,456,789"), + Ok(vec![Index(123), Index(456), Index(789)]) ); - assert!(parse_indexes("abc").is_err()); + assert!(parse_indexes(&mut "abc").is_err()); } #[test] fn check_parse_multi_key() { - assert_eq!(parse_multi_key()(r#"{"abc"}"#).unwrap(), ("", vec!["abc"])); + assert_eq!(parse_multi_key(&mut r#"{"abc"}"#), Ok(vec!["abc"])); assert_eq!( - parse_multi_key()(r#"{"abc","def"}"#).unwrap(), - ("", vec!["abc", "def"]) + parse_multi_key(&mut r#"{"abc","def"}"#), + Ok(vec!["abc", "def"]) ); - assert!(parse_multi_key()("{}").is_err()); - assert!(parse_multi_key()("{123}").is_err()); + assert!(parse_multi_key(&mut "{}").is_err()); + assert!(parse_multi_key(&mut "{123}").is_err()); } #[test] fn check_parse_array_index() { - assert_eq!(parse_array_index()("[1]").unwrap(), ("", vec![Index(1)])); + assert_eq!(parse_array_index(&mut "[1]"), Ok(vec![Index(1)])); assert_eq!( - parse_array_index()("[1,2,3]").unwrap(), - ("", vec![Index(1), Index(2), Index(3)]) + parse_array_index(&mut "[1,2,3]"), + Ok(vec![Index(1), Index(2), Index(3)]) ); - assert!(parse_array_index()("[]").is_err()); - assert!(parse_array_index()(r#"["1"]"#).is_err()); + assert!(parse_array_index(&mut "[]").is_err()); + assert!(parse_array_index(&mut r#"["1"]"#).is_err()); } #[test] fn check_parse_array_range() { - assert_eq!(parse_array_range()("[:]").unwrap(), ("", (None, None))); - assert_eq!( - parse_array_range()("[1:]").unwrap(), - ("", (Some(Index(1)), None)) - ); + assert_eq!(parse_array_range(&mut "[:]"), Ok((None, None))); + assert_eq!(parse_array_range(&mut "[1:]"), Ok((Some(Index(1)), None))); + assert_eq!(parse_array_range(&mut "[:1]"), Ok((None, Some(Index(1))))); assert_eq!( - parse_array_range()("[:1]").unwrap(), - ("", (None, Some(Index(1)))) + parse_array_range(&mut "[1:3]"), + Ok((Some(Index(1)), Some(Index(3)))) ); - assert_eq!( - parse_array_range()("[1:3]").unwrap(), - ("", (Some(Index(1)), Some(Index(3)))) - ); - assert!(parse_array_range()("[]").is_err()); + assert!(parse_array_range(&mut "[]").is_err()); } #[test] fn check_parse_object_index() { - assert_eq!(parse_object_index()("{1}").unwrap(), ("", vec![Index(1)])); + assert_eq!(parse_object_index(&mut "{1}"), Ok(vec![Index(1)])); assert_eq!( - parse_object_index()("{1,2}").unwrap(), - ("", vec![Index(1), Index(2)]) + parse_object_index(&mut "{1,2}"), + Ok(vec![Index(1), Index(2)]) ); - assert!(parse_object_index()("{}").is_err()); + assert!(parse_object_index(&mut "{}").is_err()); } #[test] fn check_parse_object_range() { - assert_eq!(parse_object_range()("{:}").unwrap(), ("", (None, None))); + assert_eq!(parse_object_range(&mut "{:}"), Ok((None, None))); + assert_eq!(parse_object_range(&mut "{1:}"), Ok((Some(Index(1)), None))); + assert_eq!(parse_object_range(&mut "{:1}"), Ok((None, Some(Index(1))))); assert_eq!( - parse_object_range()("{1:}").unwrap(), - ("", (Some(Index(1)), None)) + parse_object_range(&mut "{1:3}"), + Ok((Some(Index(1)), Some(Index(3)))) ); - assert_eq!( - parse_object_range()("{:1}").unwrap(), - ("", (None, Some(Index(1)))) - ); - assert_eq!( - parse_object_range()("{1:3}").unwrap(), - ("", (Some(Index(1)), Some(Index(3)))) - ); - assert!(parse_object_range()("{}").is_err()); + assert!(parse_object_range(&mut "{}").is_err()); } #[test] fn check_parse_flatten_operator() { - assert_eq!( - parse_flatten_operator::>()("..").unwrap(), - ("", FLATTEN) - ); - assert!(parse_flatten_operator::>()("").is_err()); + assert_eq!(parse_flatten_operator(&mut ".."), Ok(FLATTEN)); + assert_eq!(parse_flatten_operator(&mut " .. "), Ok(FLATTEN)); + assert!(parse_flatten_operator(&mut "").is_err()); } #[test] fn check_parse_pipe_in_operator() { - assert_eq!( - parse_pipe_in_operator::>()("|>").unwrap(), - ("", PIPE_IN) - ); - assert!(parse_pipe_in_operator::>()("").is_err()); + assert_eq!(parse_pipe_in_operator(&mut "|>"), Ok(PIPE_IN)); + assert_eq!(parse_pipe_in_operator(&mut " |> "), Ok(PIPE_IN)); + assert!(parse_pipe_in_operator(&mut "").is_err()); } #[test] fn check_parse_pipe_out_operator() { - assert_eq!( - parse_pipe_out_operator::>()("<|").unwrap(), - ("", PIPE_OUT) - ); - assert!(parse_pipe_out_operator::>()("").is_err()); + assert_eq!(parse_pipe_out_operator(&mut "<|"), Ok(PIPE_OUT)); + assert_eq!(parse_pipe_out_operator(&mut " <| "), Ok(PIPE_OUT)); + assert!(parse_pipe_out_operator(&mut "").is_err()); } #[test] fn check_parse_truncate_operator() { - assert_eq!( - parse_truncate_operator::>()("!").unwrap(), - ("", TRUNCATE) - ); - assert!(parse_truncate_operator::>()("").is_err()); + assert_eq!(parse_truncate_operator(&mut "!"), Ok(TRUNCATE)); + assert_eq!(parse_truncate_operator(&mut " ! "), Ok(TRUNCATE)); + assert!(parse_truncate_operator(&mut "").is_err()); } #[test] fn check_parse_group_separator() { - assert_eq!( - parse_group_separator::>()(",").unwrap(), - ("", GROUP_SEP) - ); - assert!(parse_group_separator::>()("").is_err()); + assert_eq!(parse_group_separator(&mut ","), Ok(GROUP_SEP)); + assert_eq!(parse_group_separator(&mut " , "), Ok(GROUP_SEP)); + assert!(parse_group_separator(&mut "").is_err()); } #[test] - fn check_parse_bool_lens_value() { + fn check_parse_lens() { assert_eq!( - parse_bool_lens_value::>()("false").unwrap(), - ("", LensValue::Bool(false)) + parse_lens(&mut r#""abc""#), + Ok((vec![Token::KeySelector("abc")], None)) ); assert_eq!( - parse_bool_lens_value::>()("true").unwrap(), - ("", LensValue::Bool(true)) + parse_lens(&mut r#""abc"=null"#), + Ok((vec![Token::KeySelector("abc")], Some(LensValue::Null))) ); - assert!(parse_bool_lens_value::>()("").is_err()); - } - - #[test] - fn check_parse_null_lens_value() { assert_eq!( - parse_null_lens_value::>()("null").unwrap(), - ("", LensValue::Null) + parse_lens(&mut r#""abc"="def""#), + Ok(( + vec![Token::KeySelector("abc")], + Some(LensValue::String("def")) + )) ); - assert!(parse_null_lens_value::>()("").is_err()); - } - - #[test] - fn check_parse_string_lens_value() { assert_eq!( - parse_string_lens_value::>()(r#""abc""#).unwrap(), - ("", LensValue::String("abc")) + parse_lens(&mut r#""abc"=123"#), + Ok(( + vec![Token::KeySelector("abc")], + Some(LensValue::Number(123)) + )) ); - assert!(parse_string_lens_value::>()("").is_err()); - } - - #[test] - fn check_parse_number_lens_value() { assert_eq!( - parse_number_lens_value("123").unwrap(), - ("", LensValue::Number(123)) + parse_lens(&mut r#""abc""bcd"[0]=123"#), + Ok(( + vec![ + Token::KeySelector("abc"), + Token::KeySelector("bcd"), + Token::ArrayIndexSelector(vec![Index(0)]) + ], + Some(LensValue::Number(123)) + )) ); - assert!(parse_number_lens_value("").is_err()); + assert!(parse_lens(&mut "").is_err()); } #[test] - fn check_parse_lens() { - assert_eq!( - parse_lens()(r#""abc""#).unwrap(), - ("", (vec![Token::KeySelector("abc")], None)) - ); - assert_eq!( - parse_lens()(r#""abc"=null"#).unwrap(), - ("", (vec![Token::KeySelector("abc")], Some(LensValue::Null))) - ); - assert_eq!( - parse_lens()(r#""abc"="def""#).unwrap(), - ( - "", - ( - vec![Token::KeySelector("abc")], - Some(LensValue::String("def")) - ) - ) - ); + fn check_parse_lenses() { assert_eq!( - parse_lens()(r#""abc"=123"#).unwrap(), - ( - "", + parse_lenses(&mut r#"|={"abc","bcd"=123,"efg"=null,"hij"="test"}"#), + Ok(vec![ + (vec![Token::KeySelector("abc")], None), ( - vec![Token::KeySelector("abc")], + vec![Token::KeySelector("bcd")], Some(LensValue::Number(123)) - ) - ) - ); - assert_eq!( - parse_lens()(r#""abc""bcd"[0]=123"#).unwrap(), - ( - "", + ), + (vec![Token::KeySelector("efg")], Some(LensValue::Null)), ( - vec![ - Token::KeySelector("abc"), - Token::KeySelector("bcd"), - Token::ArrayIndexSelector(vec![Index(0)]) - ], - Some(LensValue::Number(123)) - ) - ) - ); - assert_eq!(parse_lens()("").unwrap(), ("", (vec![], None))); - } - - #[test] - fn check_parse_lenses() { - assert_eq!( - parse_lenses()(r#"|={"abc","bcd"=123,"efg"=null,"hij"="test"}"#).unwrap(), - ( - "", - vec![ - (vec![Token::KeySelector("abc")], None), - ( - vec![Token::KeySelector("bcd")], - Some(LensValue::Number(123)) - ), - (vec![Token::KeySelector("efg")], Some(LensValue::Null)), - ( - vec![Token::KeySelector("hij")], - Some(LensValue::String("test")) - ), - ] - ) + vec![Token::KeySelector("hij")], + Some(LensValue::String("test")) + ), + ]) ); } } diff --git a/crates/jql-parser/src/parser.rs b/crates/jql-parser/src/parser.rs index c00d5be..e347c6f 100644 --- a/crates/jql-parser/src/parser.rs +++ b/crates/jql-parser/src/parser.rs @@ -1,11 +1,10 @@ -use nom::{ - branch::alt, +use winnow::{ combinator::{ + alt, iterator, - map, - value, }, - IResult, + PResult, + Parser, }; use crate::{ @@ -33,19 +32,15 @@ use crate::{ }; /// Parses the provided input and map it to the first matching token. -fn parse_fragment(input: &str) -> IResult<&str, Token> { +fn parse_fragment<'a>(input: &mut &'a str) -> PResult> { alt(( - map(parse_array_index(), Token::ArrayIndexSelector), - map(parse_array_range(), |(start, end)| { - Token::ArrayRangeSelector(Range(start, end)) - }), - map(parse_key(), Token::KeySelector), - map(parse_multi_key(), Token::MultiKeySelector), - map(parse_object_index(), Token::ObjectIndexSelector), - map(parse_object_range(), |(start, end)| { - Token::ObjectRangeSelector(Range(start, end)) - }), - map(parse_lenses(), |lenses| { + parse_array_index.map(Token::ArrayIndexSelector), + parse_array_range.map(|(start, end)| Token::ArrayRangeSelector(Range(start, end))), + parse_key.map(Token::KeySelector), + parse_multi_key.map(Token::MultiKeySelector), + parse_object_index.map(Token::ObjectIndexSelector), + parse_object_range.map(|(start, end)| Token::ObjectRangeSelector(Range(start, end))), + parse_lenses.map(|lenses| { Token::LensSelector( lenses .into_iter() @@ -53,12 +48,13 @@ fn parse_fragment(input: &str) -> IResult<&str, Token> { .collect(), ) }), - value(Token::FlattenOperator, parse_flatten_operator()), - value(Token::GroupSeparator, parse_group_separator()), - value(Token::PipeInOperator, parse_pipe_in_operator()), - value(Token::PipeOutOperator, parse_pipe_out_operator()), - value(Token::TruncateOperator, parse_truncate_operator()), - ))(input) + parse_flatten_operator.value(Token::FlattenOperator), + parse_group_separator.value(Token::GroupSeparator), + parse_pipe_in_operator.value(Token::PipeInOperator), + parse_pipe_out_operator.value(Token::PipeOutOperator), + parse_truncate_operator.value(Token::TruncateOperator), + )) + .parse_next(input) } /// Parses the provided input and returns a vector of `Tokens`. @@ -69,7 +65,7 @@ fn parse_fragment(input: &str) -> IResult<&str, Token> { pub fn parse(input: &str) -> Result, JqlParserError> { let mut parser_iterator = iterator(input, parse_fragment); let tokens = parser_iterator.collect::>(); - let result: IResult<_, _> = parser_iterator.finish(); + let result: PResult<_, _> = parser_iterator.finish(); match result { Ok((unparsed, ())) => { @@ -118,162 +114,163 @@ mod tests { #[test] fn check_array_index_selector() { assert_eq!( - parse_fragment("[0,1,2]"), - Ok(( - "", - Token::ArrayIndexSelector(vec![Index(0), Index(1), Index(2)]) - )) + parse_fragment(&mut "[0,1,2]"), + Ok(Token::ArrayIndexSelector(vec![ + Index(0), + Index(1), + Index(2) + ])) ); assert_eq!( - parse_fragment(" [ 0 , 1 , 2 ] "), - Ok(( - "", - Token::ArrayIndexSelector(vec![Index(0), Index(1), Index(2)]) - )) + parse_fragment(&mut " [ 0 , 1 , 2 ] "), + Ok(Token::ArrayIndexSelector(vec![ + Index(0), + Index(1), + Index(2) + ])) ); } #[test] fn check_array_range_selector() { assert_eq!( - parse_fragment("[0:2]"), - Ok(( - "", - Token::ArrayRangeSelector(Range(Some(Index(0)), Some(Index(2)))) - )) + parse_fragment(&mut "[0:2]"), + Ok(Token::ArrayRangeSelector(Range( + Some(Index(0)), + Some(Index(2)) + ))) ); assert_eq!( - parse_fragment("[:2]"), - Ok(("", Token::ArrayRangeSelector(Range(None, Some(Index(2)))))) + parse_fragment(&mut "[:2]"), + Ok(Token::ArrayRangeSelector(Range(None, Some(Index(2))))) ); assert_eq!( - parse_fragment("[0:]"), - Ok(("", Token::ArrayRangeSelector(Range(Some(Index(0)), None)))) + parse_fragment(&mut "[0:]"), + Ok(Token::ArrayRangeSelector(Range(Some(Index(0)), None))) ); assert_eq!( - parse_fragment("[:]"), - Ok(("", Token::ArrayRangeSelector(Range(None, None)))) + parse_fragment(&mut "[:]"), + Ok(Token::ArrayRangeSelector(Range(None, None))) ); } #[test] fn check_key_selector() { assert_eq!( - parse_fragment(r#""one""#), - Ok(("", Token::KeySelector("one"))) + parse_fragment(&mut r#""one""#), + Ok(Token::KeySelector("one")) ); assert_eq!( - parse_fragment(r#" "one" "#), - Ok(("", Token::KeySelector("one"))) + parse_fragment(&mut r#" "one" "#), + Ok(Token::KeySelector("one")) ); } #[test] fn check_multi_key_selector() { assert_eq!( - parse_fragment(r#"{"one","two","three"}"#), - Ok(("", Token::MultiKeySelector(vec!["one", "two", "three"]))) + parse_fragment(&mut r#"{"one","two","three"}"#), + Ok(Token::MultiKeySelector(vec!["one", "two", "three"])) ); assert_eq!( - parse_fragment(r#" { "one", "two" , "three" } "#), - Ok(("", Token::MultiKeySelector(vec!["one", "two", "three"]))) + parse_fragment(&mut r#" { "one", "two" , "three" } "#), + Ok(Token::MultiKeySelector(vec!["one", "two", "three"])) ); } #[test] fn check_object_index_selector() { assert_eq!( - parse_fragment("{0,1,2}"), - Ok(( - "", - Token::ObjectIndexSelector(vec![Index(0), Index(1), Index(2)]) - )) + parse_fragment(&mut "{0,1,2}"), + Ok(Token::ObjectIndexSelector(vec![ + Index(0), + Index(1), + Index(2) + ])) ); assert_eq!( - parse_fragment(" { 0 , 1 , 2 } "), - Ok(( - "", - Token::ObjectIndexSelector(vec![Index(0), Index(1), Index(2)]) - )) + parse_fragment(&mut " { 0 , 1 , 2 } "), + Ok(Token::ObjectIndexSelector(vec![ + Index(0), + Index(1), + Index(2) + ])) ); } #[test] fn check_object_range_selector() { assert_eq!( - parse_fragment("{0:2}"), - Ok(( - "", - Token::ObjectRangeSelector(Range(Some(Index(0)), Some(Index(2)))) - )) + parse_fragment(&mut "{0:2}"), + Ok(Token::ObjectRangeSelector(Range( + Some(Index(0)), + Some(Index(2)) + ))) ); assert_eq!( - parse_fragment("{:2}"), - Ok(("", Token::ObjectRangeSelector(Range(None, Some(Index(2)))))) + parse_fragment(&mut "{:2}"), + Ok(Token::ObjectRangeSelector(Range(None, Some(Index(2))))) ); assert_eq!( - parse_fragment("{0:}"), - Ok(("", Token::ObjectRangeSelector(Range(Some(Index(0)), None)))) + parse_fragment(&mut "{0:}"), + Ok(Token::ObjectRangeSelector(Range(Some(Index(0)), None))) ); assert_eq!( - parse_fragment("{:}"), - Ok(("", Token::ObjectRangeSelector(Range(None, None)))) + parse_fragment(&mut "{:}"), + Ok(Token::ObjectRangeSelector(Range(None, None))) ); } #[test] fn check_lens_selector() { assert_eq!( - parse_fragment(r#"|={"abc""c","bcd""d"=123,"efg"=null,"hij"="test"}"#), - Ok(( - "", - Token::LensSelector(vec![ - Lens( - vec![Token::KeySelector("abc"), Token::KeySelector("c")], - None - ), - Lens( - vec![Token::KeySelector("bcd"), Token::KeySelector("d")], - Some(LensValue::Number(123)) - ), - Lens(vec![Token::KeySelector("efg")], Some(LensValue::Null)), - Lens( - vec![Token::KeySelector("hij")], - Some(LensValue::String("test")) - ), - ]) - )) + parse_fragment(&mut r#"|={"abc""c","bcd""d"=123,"efg"=null,"hij"="test"}"#), + Ok(Token::LensSelector(vec![ + Lens( + vec![Token::KeySelector("abc"), Token::KeySelector("c")], + None + ), + Lens( + vec![Token::KeySelector("bcd"), Token::KeySelector("d")], + Some(LensValue::Number(123)) + ), + Lens(vec![Token::KeySelector("efg")], Some(LensValue::Null)), + Lens( + vec![Token::KeySelector("hij")], + Some(LensValue::String("test")) + ), + ])) ); } #[test] fn check_flatten_operator() { - assert_eq!(parse_fragment(".."), Ok(("", Token::FlattenOperator))); - assert_eq!(parse_fragment(" .. "), Ok(("", Token::FlattenOperator))); + assert_eq!(parse_fragment(&mut ".."), Ok(Token::FlattenOperator)); + assert_eq!(parse_fragment(&mut " .. "), Ok(Token::FlattenOperator)); } #[test] fn check_pipe_in_operator() { - assert_eq!(parse_fragment("|>"), Ok(("", Token::PipeInOperator))); - assert_eq!(parse_fragment(" |> "), Ok(("", Token::PipeInOperator))); + assert_eq!(parse_fragment(&mut "|>"), Ok(Token::PipeInOperator)); + assert_eq!(parse_fragment(&mut " |> "), Ok(Token::PipeInOperator)); } #[test] fn check_pipe_out_operator() { - assert_eq!(parse_fragment("<|"), Ok(("", Token::PipeOutOperator))); - assert_eq!(parse_fragment(" <| "), Ok(("", Token::PipeOutOperator))); + assert_eq!(parse_fragment(&mut "<|"), Ok(Token::PipeOutOperator)); + assert_eq!(parse_fragment(&mut " <| "), Ok(Token::PipeOutOperator)); } #[test] fn check_truncate_operator() { - assert_eq!(parse_fragment("!"), Ok(("", Token::TruncateOperator))); - assert_eq!(parse_fragment(" ! "), Ok(("", Token::TruncateOperator))); + assert_eq!(parse_fragment(&mut "!"), Ok(Token::TruncateOperator)); + assert_eq!(parse_fragment(&mut " ! "), Ok(Token::TruncateOperator)); } #[test] fn check_group_separator() { - assert_eq!(parse_fragment(","), Ok(("", Token::GroupSeparator))); - assert_eq!(parse_fragment(" , "), Ok(("", Token::GroupSeparator))); + assert_eq!(parse_fragment(&mut ","), Ok(Token::GroupSeparator)); + assert_eq!(parse_fragment(&mut " , "), Ok(Token::GroupSeparator)); } #[test] diff --git a/crates/jql/Cargo.toml b/crates/jql/Cargo.toml index f97084a..89b3ad1 100644 --- a/crates/jql/Cargo.toml +++ b/crates/jql/Cargo.toml @@ -12,7 +12,7 @@ version = { workspace = true } [dependencies] anyhow = "1.0.75" -clap = { version = "4.4.8", features = ["derive"] } +clap = { version = "4.4.10", features = ["derive"] } colored_json = { version = "4.1.0" } jql-runner = { path = "../jql-runner", version = "7.0.7" } serde = "1.0.193"