From 1fd30c62bece027eb55b06499e49fdddb2ed25f5 Mon Sep 17 00:00:00 2001 From: Darkheir Date: Wed, 28 Jan 2026 10:37:51 +0100 Subject: [PATCH] fix(query-grammar): Fix regexes between parentheses Signed-off-by: Darkheir --- query-grammar/src/query_grammar.rs | 18 +++++++++++++++--- query-grammar/src/user_input_ast.rs | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/query-grammar/src/query_grammar.rs b/query-grammar/src/query_grammar.rs index f759f5316..410a8c6a4 100644 --- a/query-grammar/src/query_grammar.rs +++ b/query-grammar/src/query_grammar.rs @@ -704,7 +704,11 @@ fn regex(inp: &str) -> IResult<&str, UserInputLeaf> { many1(alt((preceded(char('\\'), char('/')), none_of("/")))), char('/'), ), - peek(alt((multispace1, eof))), + peek(alt(( + value((), multispace1), + value((), char(')')), + value((), eof), + ))), ), |elements| UserInputLeaf::Regex { field: None, @@ -721,8 +725,12 @@ fn regex_infallible(inp: &str) -> JResult<&str, UserInputLeaf> { opt_i_err(char('/'), "missing delimiter /"), ), opt_i_err( - peek(alt((multispace1, eof))), - "expected whitespace or end of input", + peek(alt(( + value((), multispace1), + value((), char(')')), + value((), eof), + ))), + "expected whitespace, closing parenthesis, or end of input", ), )(inp) { @@ -1707,6 +1715,10 @@ mod test { test_parse_query_to_ast_helper("foo:(A OR B)", "(?\"foo\":A ?\"foo\":B)"); test_parse_query_to_ast_helper("foo:(A* OR B*)", "(?\"foo\":A* ?\"foo\":B*)"); test_parse_query_to_ast_helper("foo:(*A OR *B)", "(?\"foo\":*A ?\"foo\":*B)"); + + // Regexes between parentheses + test_parse_query_to_ast_helper("foo:(/A.*/)", "\"foo\":/A.*/"); + test_parse_query_to_ast_helper("foo:(/A.*/ OR /B.*/)", "(?\"foo\":/A.*/ ?\"foo\":/B.*/)"); } #[test] diff --git a/query-grammar/src/user_input_ast.rs b/query-grammar/src/user_input_ast.rs index e6b4858fd..b607e56cd 100644 --- a/query-grammar/src/user_input_ast.rs +++ b/query-grammar/src/user_input_ast.rs @@ -66,6 +66,7 @@ impl UserInputLeaf { } UserInputLeaf::Range { field, .. } if field.is_none() => *field = Some(default_field), UserInputLeaf::Set { field, .. } if field.is_none() => *field = Some(default_field), + UserInputLeaf::Regex { field, .. } if field.is_none() => *field = Some(default_field), _ => (), // field was already set, do nothing } }