summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2020-02-01 17:12:35 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2020-02-03 12:55:54 +0100
commitd6f38436a229dc4421e77b58bf42d07bdb28b808 (patch)
treeb281d073ceea4e4d670d243e88b0bf1201b45c29
parentcfec457d599373e6014b1f4472f48d5f989d76a5 (diff)
Implement | as or
-rw-r--r--apt-pkg/cachefilter-patterns.cc44
-rw-r--r--apt-pkg/cachefilter-patterns.h1
-rw-r--r--test/libapt/pattern_test.cc3
3 files changed, 45 insertions, 3 deletions
diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc
index dbe42b83f..8c0b35de2 100644
--- a/apt-pkg/cachefilter-patterns.cc
+++ b/apt-pkg/cachefilter-patterns.cc
@@ -70,7 +70,45 @@ std::unique_ptr<PatternTreeParser::Node> PatternTreeParser::parseTop()
// Parse any pattern
std::unique_ptr<PatternTreeParser::Node> PatternTreeParser::parse()
{
- return parseAnd();
+ return parseOr();
+}
+
+std::unique_ptr<PatternTreeParser::Node> PatternTreeParser::parseOr()
+{
+ auto start = state.offset;
+ std::vector<std::unique_ptr<PatternTreeParser::Node>> nodes;
+
+ auto firstNode = parseAnd();
+
+ if (firstNode == nullptr)
+ return nullptr;
+
+ nodes.push_back(std::move(firstNode));
+ for (skipSpace(); sentence[state.offset] == '|'; skipSpace())
+ {
+ state.offset++;
+ skipSpace();
+ auto node = parseAnd();
+
+ if (node == nullptr)
+ throw Error{Node{state.offset, sentence.size()}, "Expected pattern after |"};
+
+ nodes.push_back(std::move(node));
+ }
+
+ if (nodes.size() == 0)
+ return nullptr;
+ if (nodes.size() == 1)
+ return std::move(nodes[0]);
+
+ auto node = std::make_unique<PatternNode>();
+ node->start = start;
+ node->end = nodes[nodes.size() - 1]->end;
+ node->term = "?or";
+ node->arguments = std::move(nodes);
+ node->haveArgumentList = true;
+
+ return node;
}
std::unique_ptr<PatternTreeParser::Node> PatternTreeParser::parseAnd()
@@ -266,8 +304,8 @@ std::unique_ptr<PatternTreeParser::Node> PatternTreeParser::parseQuotedWord()
// Parse a bare word atom
std::unique_ptr<PatternTreeParser::Node> PatternTreeParser::parseWord()
{
- static const constexpr auto DISALLOWED_START = "!?~,()\0"_sv;
- static const constexpr auto DISALLOWED = ",()\0"_sv;
+ static const constexpr auto DISALLOWED_START = "!?~|,()\0"_sv;
+ static const constexpr auto DISALLOWED = "|,()\0"_sv;
if (DISALLOWED_START.find(sentence[state.offset]) != APT::StringView::npos)
return nullptr;
diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h
index 7f30a3ea0..c6e701880 100644
--- a/apt-pkg/cachefilter-patterns.h
+++ b/apt-pkg/cachefilter-patterns.h
@@ -95,6 +95,7 @@ struct PatternTreeParser
private:
std::unique_ptr<Node> parse();
+ std::unique_ptr<Node> parseOr();
std::unique_ptr<Node> parseAnd();
std::unique_ptr<Node> parseUnary();
std::unique_ptr<Node> parsePrimary();
diff --git a/test/libapt/pattern_test.cc b/test/libapt/pattern_test.cc
index 00d356d47..d8d962758 100644
--- a/test/libapt/pattern_test.cc
+++ b/test/libapt/pattern_test.cc
@@ -184,4 +184,7 @@ TEST(TreeParserTest, ParseShortPattern)
EXPECT_PATTERN_EQ("!~F ~T", "?and(?not(?false), ?true)");
EXPECT_PATTERN_EQ("!~F~T", "?and(?not(?false), ?true)");
+ EXPECT_PATTERN_EQ("!~F~T | ~T", "?or(?and(?not(?false), ?true), ?true)");
+ EXPECT_PATTERN_EQ("~ramd64|~rall", "?or(?architecture(amd64), ?architecture(all))");
+
}