95 const auto len = requirements.length();
96 if (len >= 2 && ((requirements[0] ==
'\'' && requirements[len - 1] ==
'\'') ||
97 (requirements[0] ==
'"' && requirements[len - 1] ==
'"')))
98 requirements = requirements.substr(1, len - 2);
106 if (requirements.length() == 0)
112 static parser parser(R
"(
113 Expression <- _ Bool _ LogicOperator _ Expression / Bool _
114 Bool <- Comparison / '!' Bool / '!' Identifier / Identifier / '(' _ Expression _ ')'
115 Comparison <- Identifier _ Operator _ Version / Identifier _ Operator _ String
116 String <- [a-zA-Z0-9_-]+
117 Identifier <- [a-zA-Z][a-zA-Z0-9_]*
119 LogicOperator <- [&|]
120 Version <- Number '.' Version / Number
125 if (!
static_cast<bool>(parser))
130 std::set<std::string> unknown_capabilities;
131 const auto add_unknown_capability = [&unknown_capabilities](
const auto & name)
139 parser[
"Number"] = [](
const SemanticValues & vs) {
return vs.token_to_number<
int>(); };
141 parser[
"Version"] = [](
const SemanticValues & vs)
147 std::vector<int> ret{std::any_cast<int>(vs[0])};
148 const auto & vs1 = std::any_cast<std::vector<int>>(vs[1]);
149 ret.insert(ret.end(), vs1.begin(), vs1.end());
154 return std::vector<int>{std::any_cast<int>(vs[0])};
166 parser[
"LogicOperator"] = [](
const SemanticValues & vs)
168 const auto op = vs.token();
186 parser[
"Operator"] = [](
const SemanticValues & vs)
188 const auto op = vs.token();
192 return OP_GREATER_EQ;
199 if (op ==
"=" || op ==
"==")
204 parser[
"String"] = [](
const SemanticValues & vs) {
return vs.token_to_string(); };
205 parser[
"Identifier"] = [](
const SemanticValues & vs) {
return vs.token_to_string(); };
207 parser[
"Comparison"] =
208 [
this, &add_unknown_capability, &options, &result](
const SemanticValues & vs)
210 const auto left = std::any_cast<std::string>(vs[0]);
211 const auto op = std::any_cast<Operator>(vs[1]);
214 const auto capability_ptr =
query(left);
219 add_unknown_capability(left);
224 const auto & capability = *capability_ptr;
225 const auto & name = capability.getName();
231 const auto is_ignored = [&name, &options]() {
return options.
ignore_capabilities.count(name); };
234 if (
const auto bool_ptr = capability.queryBoolValue(); (bool_ptr && !(*bool_ptr)))
238 auto comp = [&is_ignored](
const int i,
const auto & a,
const auto & b)
245 const auto do_comp = [&i, &a, &b]()
268 std::vector<int> app_value_version;
275 const auto right = std::any_cast<std::vector<int>>(vs[2]);
276 if (
const auto int_ptr = capability.queryIntValue())
278 if (right.size() != 1)
279 checkException(vs,
"cannot be compared to a version.", capability);
281 return comp(op, *int_ptr, right[0]);
284 const auto string_ptr = capability.queryStringValue();
287 "cannot be compared to a " +
288 std::string(right.size() == 1 ?
"number" :
"version number") +
".",
292 checkException(vs,
"cannot be compared to a version.", capability);
295 return comp(op, app_value_version, right);
303 const auto string_ptr = capability.queryStringValue();
305 checkException(vs,
"cannot be compared to a string.", capability);
309 if (!capability.hasEnumeration(right))
311 "'" + right +
"' invalid for capability '" + left +
312 "'; valid values: " + capability.enumerationToString());
316 checkException(vs,
"cannot be compared to a string.", capability);
318 return comp(op, *string_ptr, right);
325 parser[
"Bool"] = [
this, &add_unknown_capability, &options, &result](
const SemanticValues & vs)
331 return std::any_cast<CheckState>(vs[0]);
334 switch (std::any_cast<CheckState>(vs[0]))
353 const bool negated = vs.choice() == 2;
354 const auto identifier = std::any_cast<std::string>(vs[0]);
355 if (
const auto capability_ptr =
query(identifier))
357 const auto & capability = *capability_ptr;
358 const auto & name = capability.getName();
361 if (capability.getExplicit())
363 std::string message =
"capability '" + name +
364 "' requires a value and cannot be used in a boolean expression";
365 if (capability.queryEnumeration())
366 message +=
"; valid values: " + capability.enumerationToString();
377 const auto bool_to_pass = [&negated](
const bool val)
380 if (
const auto bool_ptr = capability.queryBoolValue())
381 return bool_to_pass(!*bool_ptr);
383 return bool_to_pass(
false);
386 add_unknown_capability(identifier);
395 parser[
"Expression"] = [](
const SemanticValues & vs)
401 const auto left = std::any_cast<CheckState>(vs[0]);
402 const auto right = std::any_cast<CheckState>(vs[2]);
403 const auto op = std::any_cast<LogicOperator>(vs[1]);
417 if (left == state || right == state)
429 if (left == state || right == state)
439 return std::any_cast<CheckState>(vs[0]);
447 parser.enable_packrat_parsing();
449 if (!parser.parse(requirements, result.
state))
453 if (options.
certain && unknown_capabilities.size())