mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-21 01:42:15 -07:00
Support fixed CFG
This commit is contained in:
parent
07669b1461
commit
67abc08bfd
1 changed files with 72 additions and 72 deletions
|
|
@ -42,10 +42,11 @@ ColorQuery <- [cC] 'olor'? <[iI]?> <[:!]> ColorEx*
|
||||||
|
|
||||||
FieldQuery <- String [:] RegexString / String ws? NumericExpression
|
FieldQuery <- String [:] RegexString / String ws? NumericExpression
|
||||||
|
|
||||||
NonDoubleQuoteUnlessEscaped <- !["]. / '\"'.
|
NonDoubleQuoteUnlessEscaped <- '\\\"'. / !["].
|
||||||
NonSingleQuoteUnlessEscaped <- ![']. / "\'".
|
NonSingleQuoteUnlessEscaped <- "\\\'". / !['].
|
||||||
UnescapedStringListPart <- !['":<>=! ].
|
UnescapedStringListPart <- !['":<>=! ].
|
||||||
String <- UnescapedStringListPart+ / ["] <NonDoubleQuoteUnlessEscaped*> ["] / ['] <NonSingleQuoteUnlessEscaped*> [']
|
SingleApostropheString <- (UnescapedStringListPart+ ws*)* ['] (UnescapedStringListPart+ ws*)*
|
||||||
|
String <- UnescapedStringListPart+ / ["] <NonDoubleQuoteUnlessEscaped*> ["] / ['] <NonSingleQuoteUnlessEscaped*> ['] / SingleApostropheString
|
||||||
StringValue <- String / [(] StringList [)]
|
StringValue <- String / [(] StringList [)]
|
||||||
StringList <- StringListString (ws? [,] ws? StringListString)*
|
StringList <- StringListString (ws? [,] ws? StringListString)*
|
||||||
StringListString <- UnescapedStringListPart+
|
StringListString <- UnescapedStringListPart+
|
||||||
|
|
@ -58,7 +59,6 @@ CompactStringSet <- StringListString ([,+] StringListString)+
|
||||||
NumericExpression <- NumericOperator ws? NumericValue
|
NumericExpression <- NumericOperator ws? NumericValue
|
||||||
NumericOperator <- [=:] / <[><!][=]?>
|
NumericOperator <- [=:] / <[><!][=]?>
|
||||||
NumericValue <- [0-9]+
|
NumericValue <- [0-9]+
|
||||||
|
|
||||||
)");
|
)");
|
||||||
|
|
||||||
std::once_flag init;
|
std::once_flag init;
|
||||||
|
|
@ -85,15 +85,15 @@ static void setupParserRules()
|
||||||
search["SomewhatComplexQueryPart"] = passthru;
|
search["SomewhatComplexQueryPart"] = passthru;
|
||||||
search["QueryPart"] = passthru;
|
search["QueryPart"] = passthru;
|
||||||
search["NotQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["NotQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
Filter dependent = std::any_cast<Filter>(sv[0]);
|
const auto dependent = std::any_cast<Filter>(sv[0]);
|
||||||
return [=](const CardData &x) -> bool { return !dependent(x); };
|
return [=](const CardData &x) -> bool { return !dependent(x); };
|
||||||
};
|
};
|
||||||
search["TypeQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["TypeQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
StringMatcher matcher = std::any_cast<StringMatcher>(sv[0]);
|
const auto matcher = std::any_cast<StringMatcher>(sv[0]);
|
||||||
return [=](const CardData &x) -> bool { return matcher(x->getCardType()); };
|
return [=](const CardData &x) -> bool { return matcher(x->getCardType()); };
|
||||||
};
|
};
|
||||||
search["SetQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["SetQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
StringMatcher matcher = std::any_cast<StringMatcher>(sv[0]);
|
auto matcher = std::any_cast<StringMatcher>(sv[0]);
|
||||||
return [=](const CardData &x) -> bool {
|
return [=](const CardData &x) -> bool {
|
||||||
QList<QString> sets = x->getSets().keys();
|
QList<QString> sets = x->getSets().keys();
|
||||||
|
|
||||||
|
|
@ -102,7 +102,7 @@ static void setupParserRules()
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
search["RarityQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["RarityQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
StringMatcher matcher = std::any_cast<StringMatcher>(sv[0]);
|
auto matcher = std::any_cast<StringMatcher>(sv[0]);
|
||||||
return [=](const CardData &x) -> bool {
|
return [=](const CardData &x) -> bool {
|
||||||
QList<CardInfoPerSet> infos = x->getSets().values();
|
QList<CardInfoPerSet> infos = x->getSets().values();
|
||||||
|
|
||||||
|
|
@ -112,15 +112,14 @@ static void setupParserRules()
|
||||||
};
|
};
|
||||||
search["FormatQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["FormatQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
if (sv.choice() == 0) {
|
if (sv.choice() == 0) {
|
||||||
QString format = std::any_cast<QString>(sv[0]);
|
const auto format = std::any_cast<QString>(sv[0]);
|
||||||
return
|
return
|
||||||
[=](const CardData &x) -> bool { return x->getProperty(QString("format-%1").arg(format)) == "legal"; };
|
[=](const CardData &x) -> bool { return x->getProperty(QString("format-%1").arg(format)) == "legal"; };
|
||||||
} else {
|
|
||||||
QString format = std::any_cast<QString>(sv[1]);
|
|
||||||
QString legality = std::any_cast<QString>(sv[0]);
|
|
||||||
return
|
|
||||||
[=](const CardData &x) -> bool { return x->getProperty(QString("format-%1").arg(format)) == legality; };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto format = std::any_cast<QString>(sv[1]);
|
||||||
|
const auto legality = std::any_cast<QString>(sv[0]);
|
||||||
|
return [=](const CardData &x) -> bool { return x->getProperty(QString("format-%1").arg(format)) == legality; };
|
||||||
};
|
};
|
||||||
search["Legality"] = [](const peg::SemanticValues &sv) -> QString {
|
search["Legality"] = [](const peg::SemanticValues &sv) -> QString {
|
||||||
switch (tolower(std::string(sv.sv())[0])) {
|
switch (tolower(std::string(sv.sv())[0])) {
|
||||||
|
|
@ -153,45 +152,43 @@ static void setupParserRules()
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return QString::fromStdString(std::string(sv.sv())).toLower();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return QString::fromStdString(std::string(sv.sv())).toLower();
|
||||||
};
|
};
|
||||||
search["StringValue"] = [](const peg::SemanticValues &sv) -> StringMatcher {
|
search["StringValue"] = [](const peg::SemanticValues &sv) -> StringMatcher {
|
||||||
if (sv.choice() == 0) {
|
if (sv.choice() == 0) {
|
||||||
auto target = std::any_cast<QString>(sv[0]);
|
const auto target = std::any_cast<QString>(sv[0]);
|
||||||
return [=](const QString &s) { return s.split(" ").contains(target, Qt::CaseInsensitive); };
|
return [=](const QString &s) { return s.split(" ").contains(target, Qt::CaseInsensitive); };
|
||||||
} else {
|
}
|
||||||
auto target = std::any_cast<QStringList>(sv[0]);
|
|
||||||
|
const auto target = std::any_cast<QStringList>(sv[0]);
|
||||||
return [=](const QString &s) {
|
return [=](const QString &s) {
|
||||||
auto containsString = [&s](const QString &str) {
|
auto containsString = [&s](const QString &str) { return s.split(" ").contains(str, Qt::CaseInsensitive); };
|
||||||
return s.split(" ").contains(str, Qt::CaseInsensitive);
|
|
||||||
};
|
|
||||||
return std::any_of(target.begin(), target.end(), containsString);
|
return std::any_of(target.begin(), target.end(), containsString);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
search["String"] = [](const peg::SemanticValues &sv) -> QString {
|
search["String"] = [](const peg::SemanticValues &sv) -> QString {
|
||||||
if (sv.choice() == 0) {
|
if (sv.choice() == 0) {
|
||||||
return QString::fromStdString(std::string(sv.sv()));
|
return QString::fromStdString(std::string(sv.sv()));
|
||||||
} else {
|
|
||||||
return QString::fromStdString(std::string(sv.token(0)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return QString::fromStdString(std::string(sv.token(0)));
|
||||||
};
|
};
|
||||||
search["FlexStringValue"] = [](const peg::SemanticValues &sv) -> StringMatcher {
|
search["FlexStringValue"] = [](const peg::SemanticValues &sv) -> StringMatcher {
|
||||||
if (sv.choice() != 1) {
|
if (sv.choice() != 1) {
|
||||||
auto target = std::any_cast<QStringList>(sv[0]);
|
const auto target = std::any_cast<QStringList>(sv[0]);
|
||||||
return [=](const QString &s) {
|
return [=](const QString &s) {
|
||||||
auto containsString = [&s](const QString &str) {
|
auto containsString = [&s](const QString &str) {
|
||||||
return s.split(" ").contains(str, Qt::CaseInsensitive);
|
return s.split(" ").contains(str, Qt::CaseInsensitive);
|
||||||
};
|
};
|
||||||
return std::any_of(target.begin(), target.end(), containsString);
|
return std::any_of(target.begin(), target.end(), containsString);
|
||||||
};
|
};
|
||||||
} else {
|
|
||||||
auto target = std::any_cast<QString>(sv[0]);
|
|
||||||
return [=](const QString &s) { return s.split(" ").contains(target, Qt::CaseInsensitive); };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto target = std::any_cast<QString>(sv[0]);
|
||||||
|
return [=](const QString &s) { return s.split(" ").contains(target, Qt::CaseInsensitive); };
|
||||||
};
|
};
|
||||||
search["CompactStringSet"] = [](const peg::SemanticValues &sv) -> QStringList {
|
search["CompactStringSet"] = [](const peg::SemanticValues &sv) -> QStringList {
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
|
@ -212,23 +209,23 @@ static void setupParserRules()
|
||||||
};
|
};
|
||||||
|
|
||||||
search["NumericExpression"] = [](const peg::SemanticValues &sv) -> NumberMatcher {
|
search["NumericExpression"] = [](const peg::SemanticValues &sv) -> NumberMatcher {
|
||||||
auto arg = std::any_cast<int>(sv[1]);
|
const auto arg = std::any_cast<int>(sv[1]);
|
||||||
auto op = std::any_cast<QString>(sv[0]);
|
const auto op = std::any_cast<QString>(sv[0]);
|
||||||
|
|
||||||
if (op == ">")
|
if (op == ">")
|
||||||
return [=](int s) { return s > arg; };
|
return [=](const int s) { return s > arg; };
|
||||||
if (op == ">=")
|
if (op == ">=")
|
||||||
return [=](int s) { return s >= arg; };
|
return [=](const int s) { return s >= arg; };
|
||||||
if (op == "<")
|
if (op == "<")
|
||||||
return [=](int s) { return s < arg; };
|
return [=](const int s) { return s < arg; };
|
||||||
if (op == "<=")
|
if (op == "<=")
|
||||||
return [=](int s) { return s <= arg; };
|
return [=](const int s) { return s <= arg; };
|
||||||
if (op == "=")
|
if (op == "=")
|
||||||
return [=](int s) { return s == arg; };
|
return [=](const int s) { return s == arg; };
|
||||||
if (op == ":")
|
if (op == ":")
|
||||||
return [=](int s) { return s == arg; };
|
return [=](const int s) { return s == arg; };
|
||||||
if (op == "!=")
|
if (op == "!=")
|
||||||
return [=](int s) { return s != arg; };
|
return [=](const int s) { return s != arg; };
|
||||||
return [](int) { return false; };
|
return [](int) { return false; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -246,12 +243,12 @@ static void setupParserRules()
|
||||||
auto sanitizedTarget = QString(target);
|
auto sanitizedTarget = QString(target);
|
||||||
sanitizedTarget.replace("\\\"", "\"");
|
sanitizedTarget.replace("\\\"", "\"");
|
||||||
sanitizedTarget.replace("\\'", "'");
|
sanitizedTarget.replace("\\'", "'");
|
||||||
return s.QString::contains(sanitizedTarget, Qt::CaseInsensitive);
|
return s.contains(sanitizedTarget, Qt::CaseInsensitive);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
search["OracleQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["OracleQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
StringMatcher matcher = std::any_cast<StringMatcher>(sv[0]);
|
const auto matcher = std::any_cast<StringMatcher>(sv[0]);
|
||||||
return [=](const CardData &x) { return matcher(x->getText()); };
|
return [=](const CardData &x) { return matcher(x->getText()); };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -260,13 +257,14 @@ static void setupParserRules()
|
||||||
for (const auto &i : sv) {
|
for (const auto &i : sv) {
|
||||||
parts += std::any_cast<char>(i);
|
parts += std::any_cast<char>(i);
|
||||||
}
|
}
|
||||||
bool identity = sv.tokens[0][0] != 'i';
|
const bool identity = sv.tokens[0][0] != 'i';
|
||||||
if (sv.tokens[1][0] == ':') {
|
if (sv.tokens[1][0] == ':') {
|
||||||
return [=](const CardData &x) {
|
return [=](const CardData &x) {
|
||||||
QString match = identity ? x->getColors() : x->getProperty("coloridentity");
|
QString match = identity ? x->getColors() : x->getProperty("coloridentity");
|
||||||
if (parts.contains("m") && match.length() < 2) {
|
if (parts.contains("m") && match.length() < 2) {
|
||||||
return false;
|
return false;
|
||||||
} else if (parts == "m") {
|
}
|
||||||
|
if (parts == "m") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,55 +274,57 @@ static void setupParserRules()
|
||||||
auto containsColor = [&parts](const QString &s) { return parts.contains(s); };
|
auto containsColor = [&parts](const QString &s) { return parts.contains(s); };
|
||||||
return std::any_of(match.begin(), match.end(), containsColor);
|
return std::any_of(match.begin(), match.end(), containsColor);
|
||||||
};
|
};
|
||||||
} else {
|
}
|
||||||
|
|
||||||
return [=](const CardData &x) {
|
return [=](const CardData &x) {
|
||||||
QString match = identity ? x->getColors() : x->getProperty("colorIdentity");
|
QString match = identity ? x->getColors() : x->getProperty("colorIdentity");
|
||||||
if (parts.contains("m") && match.length() < 2)
|
if (parts.contains("m") && match.length() < 2) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (parts.contains("c") && match.length() != 0)
|
if (parts.contains("c") && match.length() != 0) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto &part : parts) {
|
for (const auto &part : parts) {
|
||||||
if (!match.contains(part))
|
if (!match.contains(part)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto containsColor = [&parts](const QString &s) { return parts.contains(s); };
|
auto containsColor = [&parts](const QString &s) { return parts.contains(s); };
|
||||||
return std::all_of(match.begin(), match.end(), containsColor);
|
return std::all_of(match.begin(), match.end(), containsColor);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
search["CMCQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["CMCQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
NumberMatcher matcher = std::any_cast<NumberMatcher>(sv[0]);
|
const auto matcher = std::any_cast<NumberMatcher>(sv[0]);
|
||||||
return [=](const CardData &x) -> bool { return matcher(x->getProperty("cmc").toInt()); };
|
return [=](const CardData &x) -> bool { return matcher(x->getProperty("cmc").toInt()); };
|
||||||
};
|
};
|
||||||
search["PowerQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["PowerQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
NumberMatcher matcher = std::any_cast<NumberMatcher>(sv[0]);
|
const auto matcher = std::any_cast<NumberMatcher>(sv[0]);
|
||||||
return [=](const CardData &x) -> bool { return matcher(x->getPowTough().split("/")[0].toInt()); };
|
return [=](const CardData &x) -> bool { return matcher(x->getPowTough().split("/")[0].toInt()); };
|
||||||
};
|
};
|
||||||
search["ToughnessQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["ToughnessQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
NumberMatcher matcher = std::any_cast<NumberMatcher>(sv[0]);
|
const auto matcher = std::any_cast<NumberMatcher>(sv[0]);
|
||||||
return [=](const CardData &x) -> bool {
|
return [=](const CardData &x) -> bool {
|
||||||
auto parts = x->getPowTough().split("/");
|
auto parts = x->getPowTough().split("/");
|
||||||
return matcher(parts.length() == 2 ? parts[1].toInt() : 0);
|
return matcher(parts.length() == 2 ? parts[1].toInt() : 0);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
search["FieldQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["FieldQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
QString field = std::any_cast<QString>(sv[0]);
|
const auto field = std::any_cast<QString>(sv[0]);
|
||||||
if (sv.choice() == 0) {
|
if (sv.choice() == 0) {
|
||||||
StringMatcher matcher = std::any_cast<StringMatcher>(sv[1]);
|
const auto matcher = std::any_cast<StringMatcher>(sv[1]);
|
||||||
return [=](const CardData &x) -> bool { return x->hasProperty(field) && matcher(x->getProperty(field)); };
|
return [=](const CardData &x) -> bool { return x->hasProperty(field) && matcher(x->getProperty(field)); };
|
||||||
} else {
|
|
||||||
NumberMatcher matcher = std::any_cast<NumberMatcher>(sv[1]);
|
|
||||||
return [=](const CardData &x) -> bool {
|
|
||||||
return x->hasProperty(field) && matcher(x->getProperty(field).toInt());
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto matcher = std::any_cast<NumberMatcher>(sv[1]);
|
||||||
|
return
|
||||||
|
[=](const CardData &x) -> bool { return x->hasProperty(field) && matcher(x->getProperty(field).toInt()); };
|
||||||
};
|
};
|
||||||
search["GenericQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["GenericQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
StringMatcher matcher = std::any_cast<StringMatcher>(sv[0]);
|
const auto matcher = std::any_cast<StringMatcher>(sv[0]);
|
||||||
return [=](const CardData &x) { return matcher(x->getName()); };
|
return [=](const CardData &x) { return matcher(x->getName()); };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue