commit 04d8296a62a5a7c84e88ff9c32b16189eab6e3bc
parent 3757ac72991202f18c674b423ed94186f4f3d562
Author: cfillion <cfillion@users.noreply.github.com>
Date: Fri, 2 Sep 2016 21:45:25 -0400
filter: fix NOT ( a OR b ) OR c
Diffstat:
2 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/src/filter.cpp b/src/filter.cpp
@@ -88,7 +88,7 @@ Filter::Group *Filter::Group::push(string buf, int *flags)
else if(buf == "OR") {
if(m_nodes.empty())
return this;
- else if(m_type == Group::MatchAny) {
+ else if(m_type == MatchAny) {
m_open = true;
return this;
}
@@ -99,7 +99,7 @@ Filter::Group *Filter::Group::push(string buf, int *flags)
m_nodes.pop_back();
}
- auto newGroup = make_shared<Group>(Group::MatchAny, 0, this);
+ auto newGroup = make_shared<Group>(MatchAny, 0, this);
m_nodes.push_back(newGroup);
if(prev)
@@ -108,13 +108,24 @@ Filter::Group *Filter::Group::push(string buf, int *flags)
return newGroup.get();
}
else if(buf == "(") {
- auto newGroup = make_shared<Group>(Group::MatchAll, *flags, this);
+ auto newGroup = make_shared<Group>(MatchAll, *flags, this);
m_nodes.push_back(newGroup);
*flags = 0;
return newGroup.get();
}
- else if(buf == ")")
- return m_parent ? m_parent : this;
+ else if(buf == ")") {
+ Group *parent = this;
+
+ while(parent->m_parent) {
+ const Type type = parent->m_type;
+ parent = parent->m_parent;
+
+ if(type == MatchAll)
+ break;
+ }
+
+ return parent;
+ }
}
if(size > 1 && buf[0] == '^') {
@@ -128,10 +139,7 @@ Filter::Group *Filter::Group::push(string buf, int *flags)
size--;
}
- Group *group = this;
-
- while(!group->m_open)
- group = group->m_parent;
+ Group *group = m_open ? this : m_parent;
group->push(make_shared<Token>(buf, *flags));
*flags = 0;
diff --git a/test/filter.cpp b/test/filter.cpp
@@ -270,10 +270,30 @@ TEST_CASE("AND grouping", M) {
}
SECTION("NOT + AND grouping") {
- f.set("NOT ( apple OR orange )");
+ f.set("NOT ( apple orange ) bacon");
+
+ REQUIRE(f.match({"bacon"}));
+ REQUIRE_FALSE(f.match({"apple bacon"}));
+ REQUIRE_FALSE(f.match({"orange bacon"}));
+ }
+
+ SECTION("NOT + AND + OR grouping") {
+ f.set("NOT ( apple OR orange ) OR bacon");
+
+ REQUIRE_FALSE(f.match({"apple"}));
+ REQUIRE_FALSE(f.match({"orange"}));
+ REQUIRE(f.match({"test"}));
+ REQUIRE(f.match({"apple bacon"}));
+ REQUIRE(f.match({"bacon"}));
+ }
+
+ SECTION("nested groups") {
+ f.set("NOT ( ( apple OR orange ) OR bacon )");
REQUIRE_FALSE(f.match({"apple"}));
REQUIRE_FALSE(f.match({"orange"}));
REQUIRE(f.match({"test"}));
+ REQUIRE_FALSE(f.match({"apple bacon"}));
+ REQUIRE_FALSE(f.match({"bacon"}));
}
}