Skip to content

Commit

Permalink
allow_any_combination_of_operators (#57)
Browse files Browse the repository at this point in the history
* allow_any_combination_of_operators

* restore formatting
  • Loading branch information
dkuku authored Nov 2, 2024
1 parent f72f2ee commit e4217f2
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 27 deletions.
81 changes: 81 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,87 @@ mod tests {
and colb = 3"
);

assert_eq!(format(input, &QueryParams::None, &options), expected);
}
#[test]
fn it_correctly_parses_all_operators() {
let operators = [
"!!", "!~~*", "!~~", "!~*", "!~", "##", "#>>", "#>", "#-", "&<|", "&<", "&>", "&&",
"*<>", "*<=", "*>=", "*>", "*=", "*<", "<<|", "<<=", "<<", "<->", "<@", "<^", "<=",
"<>", "<", ">=", ">>=", ">>", ">^", "->>", "->", "-|-", "-", "+", "/", "=", "%", "?||",
"?|", "?-|", "?-", "?#", "?&", "?", "@@@", "@@", "@>", "@?", "@-@", "@", "^@", "^",
"|&>", "|>>", "|/", "|", "||/", "||", "~>=~", "~>~", "~<=~", "~<~", "~=", "~*", "~~*",
"~~", "~",
];

// Test each operator individually
for &operator in &operators {
let input = format!("left {} right", operator);
let expected = format!("left {} right", operator);
let options = FormatOptions {
uppercase: None,
..FormatOptions::default()
};

assert_eq!(
format(&input, &QueryParams::None, &options),
expected,
"Failed to parse operator: {}",
operator
);
}
}
#[test]
fn it_correctly_splits_operators() {
let input = "
SELECT
left <@ right,
left << right,
left >> right,
left &< right,
left &> right,
left -|- right,
@@ left,
@-@ left,
left <-> right,
left <<| right,
left |>> right,
left &<| right,
left |>& right,
left <^ right,
left >^ right,
?- left,
left ?-| right,
left ?|| right,
left ~= right";
let options = FormatOptions {
uppercase: None,
..FormatOptions::default()
};
let expected = indoc!(
"
SELECT
left <@ right,
left << right,
left >> right,
left &< right,
left &> right,
left -|- right,
@@ left,
@-@ left,
left <-> right,
left <<| right,
left |>> right,
left &<| right,
left |>& right,
left <^ right,
left >^ right,
?- left,
left ?-| right,
left ?|| right,
left ~= right"
);

assert_eq!(format(input, &QueryParams::None, &options), expected);
}
}
64 changes: 37 additions & 27 deletions src/tokenizer.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use nom::branch::alt;
use nom::bytes::complete::{tag, tag_no_case, take, take_until, take_while1};
use nom::character::complete::{anychar, char, digit0, digit1, not_line_ending};
use nom::combinator::{eof, opt, peek, recognize, verify};
use nom::combinator::{eof, map, opt, peek, recognize, verify};
use nom::error::ParseError;
use nom::error::{Error, ErrorKind};
use nom::multi::many0;
use nom::multi::{many0, many_m_n};
use nom::sequence::{terminated, tuple};
use nom::{AsChar, Err, IResult};
use std::borrow::Cow;
Expand Down Expand Up @@ -107,9 +107,10 @@ fn get_next_token<'a>(
last_reserved_top_level_token,
)
})
.or_else(|_| get_operator_token(input))
.or_else(|_| get_placeholder_token(input, named_placeholders))
.or_else(|_| get_word_token(input))
.or_else(|_| get_operator_token(input))
.or_else(|_| get_any_other_char(input))
}

fn get_whitespace_token(input: &str) -> IResult<&str, Token<'_>> {
Expand Down Expand Up @@ -998,30 +999,39 @@ fn get_word_token(input: &str) -> IResult<&str, Token<'_>> {
}

fn get_operator_token(input: &str) -> IResult<&str, Token<'_>> {
alt((
tag("!="),
tag("<>"),
tag("=="),
tag("<="),
tag(">="),
tag("!<"),
tag("!>"),
tag("||"),
tag("::"),
tag("->>"),
tag("->"),
tag("~~*"),
tag("~~"),
tag("!~~*"),
tag("!~~"),
tag("~*"),
tag("!~*"),
tag("!~"),
tag(":="),
recognize(verify(take(1usize), |token: &str| {
token != "\n" && token != "\r"
})),
))(input)
// Define the allowed operator characters
let allowed_operators = alt((
tag("!"),
tag("<"),
tag(">"),
tag("="),
tag("|"),
tag(":"),
tag("-"),
tag("~"),
tag("*"),
tag("&"),
tag("@"),
tag("^"),
tag("?"),
tag("#"),
tag("/"),
));

map(
recognize(many_m_n(2, 5, allowed_operators)),
|token: &str| Token {
kind: TokenKind::Operator,
value: token,
key: None,
},
)(input)
}
fn get_any_other_char(input: &str) -> IResult<&str, Token<'_>> {
alt((recognize(verify(
nom::character::complete::anychar,
|&token: &char| token != '\n' && token != '\r',
)),))(input)
.map(|(input, token)| {
(
input,
Expand Down

0 comments on commit e4217f2

Please sign in to comment.