mirror of https://github.com/djcb/mu.git
query-parser: handle naked NOT, add tests
We weren't correctly expanding "naked NOT" -> AND_NOT Fixes #2559.
This commit is contained in:
parent
8fc13ab8f3
commit
b771fd6394
|
@ -178,7 +178,7 @@ unit(Sexp& tokens, ParseContext& ctx)
|
||||||
|
|
||||||
/* special case: interpret "not" as a matcher instead; */
|
/* special case: interpret "not" as a matcher instead; */
|
||||||
if (sub.empty())
|
if (sub.empty())
|
||||||
return Sexp{placeholder_sym, not_sym.name};
|
return matcher(prepend(tokens, Sexp{placeholder_sym, not_sym.name}), ctx);
|
||||||
|
|
||||||
/* we try to optimize: double negations are removed */
|
/* we try to optimize: double negations are removed */
|
||||||
if (sub.head_symbolp(not_sym))
|
if (sub.head_symbolp(not_sym))
|
||||||
|
@ -214,6 +214,8 @@ factor(Sexp& tokens, ParseContext& ctx)
|
||||||
auto implicit_and = [&]() {
|
auto implicit_and = [&]() {
|
||||||
if (tokens.head_symbolp(open_sym))
|
if (tokens.head_symbolp(open_sym))
|
||||||
return true;
|
return true;
|
||||||
|
else if (tokens.head_symbolp(not_sym)) // turn a lone 'not' -> 'and not'
|
||||||
|
return true;
|
||||||
else if (auto&& head{tokens.head()}; head)
|
else if (auto&& head{tokens.head()}; head)
|
||||||
return looks_like_matcher(*head);
|
return looks_like_matcher(*head);
|
||||||
else
|
else
|
||||||
|
@ -222,7 +224,6 @@ factor(Sexp& tokens, ParseContext& ctx)
|
||||||
|
|
||||||
Sexp uns;
|
Sexp uns;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
if (tokens.head_symbolp(and_sym))
|
if (tokens.head_symbolp(and_sym))
|
||||||
tokens.pop_front();
|
tokens.pop_front();
|
||||||
else if (!implicit_and())
|
else if (!implicit_and())
|
||||||
|
@ -362,7 +363,8 @@ test_parser_basic()
|
||||||
TestCase{R"(a and (b or c))", R"((and (_ "a") (or (_ "b") (_ "c"))))"},
|
TestCase{R"(a and (b or c))", R"((and (_ "a") (or (_ "b") (_ "c"))))"},
|
||||||
// not a and not b
|
// not a and not b
|
||||||
TestCase{R"(not a and b)", R"((and (not (_ "a")) (_ "b")))"},
|
TestCase{R"(not a and b)", R"((and (not (_ "a")) (_ "b")))"},
|
||||||
// TODO: add more...
|
// a not b
|
||||||
|
TestCase{R"(a not b)", R"((and (_ "a") (not (_ "b"))))"},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto&& test: cases) {
|
for (auto&& test: cases) {
|
||||||
|
|
|
@ -452,6 +452,13 @@ test_xapian()
|
||||||
R"(Query((Shello world OR (Shello PHRASE 2 Sworld))))"},
|
R"(Query((Shello world OR (Shello PHRASE 2 Sworld))))"},
|
||||||
TestCase{R"(subject:/boo/")", R"(Query())"},
|
TestCase{R"(subject:/boo/")", R"(Query())"},
|
||||||
|
|
||||||
|
// logic
|
||||||
|
TestCase{R"(not)", R"(Query((Tnot OR Cnot OR Hnot OR Fnot OR Snot OR Bnot OR Enot)))"},
|
||||||
|
TestCase{R"(from:a and (from:b or from:c))", R"(Query((Fa AND (Fb OR Fc))))"},
|
||||||
|
// optimize?
|
||||||
|
TestCase{R"(not from:a and to:b)", R"(Query(((<alldocuments> AND_NOT Fa) AND Tb)))"},
|
||||||
|
TestCase{R"(cc:a not bcc:b)", R"(Query((Ca AND (<alldocuments> AND_NOT Hb))))"},
|
||||||
|
|
||||||
// ranges.
|
// ranges.
|
||||||
TestCase{R"(size:1..10")", R"(Query(VALUE_RANGE 17 g1 ga))"},
|
TestCase{R"(size:1..10")", R"(Query(VALUE_RANGE 17 g1 ga))"},
|
||||||
TestCase{R"(size:10..1")", R"(Query(VALUE_RANGE 17 g1 ga))"},
|
TestCase{R"(size:10..1")", R"(Query(VALUE_RANGE 17 g1 ga))"},
|
||||||
|
|
Loading…
Reference in New Issue