mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +00:00
Allow literal operators in infix expression
This commit is contained in:
parent
a248d8689e
commit
e26a9e88f5
22
peglib.h
22
peglib.h
@ -560,7 +560,7 @@ private:
|
|||||||
/*
|
/*
|
||||||
* Semantic action
|
* Semantic action
|
||||||
*/
|
*/
|
||||||
template <typename F, typename... Args> std::any call(F fn, Args &&... args) {
|
template <typename F, typename... Args> std::any call(F fn, Args &&...args) {
|
||||||
using R = decltype(fn(std::forward<Args>(args)...));
|
using R = decltype(fn(std::forward<Args>(args)...));
|
||||||
if constexpr (std::is_void<R>::value) {
|
if constexpr (std::is_void<R>::value) {
|
||||||
fn(std::forward<Args>(args)...);
|
fn(std::forward<Args>(args)...);
|
||||||
@ -976,7 +976,7 @@ public:
|
|||||||
class Sequence : public Ope {
|
class Sequence : public Ope {
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
Sequence(const Args &... args)
|
Sequence(const Args &...args)
|
||||||
: opes_{static_cast<std::shared_ptr<Ope>>(args)...} {}
|
: opes_{static_cast<std::shared_ptr<Ope>>(args)...} {}
|
||||||
Sequence(const std::vector<std::shared_ptr<Ope>> &opes) : opes_(opes) {}
|
Sequence(const std::vector<std::shared_ptr<Ope>> &opes) : opes_(opes) {}
|
||||||
Sequence(std::vector<std::shared_ptr<Ope>> &&opes) : opes_(opes) {}
|
Sequence(std::vector<std::shared_ptr<Ope>> &&opes) : opes_(opes) {}
|
||||||
@ -1019,7 +1019,7 @@ public:
|
|||||||
class PrioritizedChoice : public Ope {
|
class PrioritizedChoice : public Ope {
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
PrioritizedChoice(bool for_label, const Args &... args)
|
PrioritizedChoice(bool for_label, const Args &...args)
|
||||||
: opes_{static_cast<std::shared_ptr<Ope>>(args)...},
|
: opes_{static_cast<std::shared_ptr<Ope>>(args)...},
|
||||||
for_label_(for_label) {}
|
for_label_(for_label) {}
|
||||||
PrioritizedChoice(const std::vector<std::shared_ptr<Ope>> &opes)
|
PrioritizedChoice(const std::vector<std::shared_ptr<Ope>> &opes)
|
||||||
@ -1577,16 +1577,16 @@ public:
|
|||||||
/*
|
/*
|
||||||
* Factories
|
* Factories
|
||||||
*/
|
*/
|
||||||
template <typename... Args> std::shared_ptr<Ope> seq(Args &&... args) {
|
template <typename... Args> std::shared_ptr<Ope> seq(Args &&...args) {
|
||||||
return std::make_shared<Sequence>(static_cast<std::shared_ptr<Ope>>(args)...);
|
return std::make_shared<Sequence>(static_cast<std::shared_ptr<Ope>>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args> std::shared_ptr<Ope> cho(Args &&... args) {
|
template <typename... Args> std::shared_ptr<Ope> cho(Args &&...args) {
|
||||||
return std::make_shared<PrioritizedChoice>(
|
return std::make_shared<PrioritizedChoice>(
|
||||||
false, static_cast<std::shared_ptr<Ope>>(args)...);
|
false, static_cast<std::shared_ptr<Ope>>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args> std::shared_ptr<Ope> cho4label_(Args &&... args) {
|
template <typename... Args> std::shared_ptr<Ope> cho4label_(Args &&...args) {
|
||||||
return std::make_shared<PrioritizedChoice>(
|
return std::make_shared<PrioritizedChoice>(
|
||||||
true, static_cast<std::shared_ptr<Ope>>(args)...);
|
true, static_cast<std::shared_ptr<Ope>>(args)...);
|
||||||
}
|
}
|
||||||
@ -3184,8 +3184,14 @@ private:
|
|||||||
seq(g["PrecedenceAssoc"],
|
seq(g["PrecedenceAssoc"],
|
||||||
oom(seq(ign(g["SpacesOom"]), g["PrecedenceOpe"])));
|
oom(seq(ign(g["SpacesOom"]), g["PrecedenceOpe"])));
|
||||||
g["PrecedenceOpe"] <=
|
g["PrecedenceOpe"] <=
|
||||||
tok(oom(
|
cho(seq(cls("'"),
|
||||||
seq(npd(cho(g["PrecedenceAssoc"], g["Space"], chr('}'))), dot())));
|
tok(zom(seq(npd(cho(g["Space"], cls("'"))), g["Char"]))),
|
||||||
|
cls("'")),
|
||||||
|
seq(cls("\""),
|
||||||
|
tok(zom(seq(npd(cho(g["Space"], cls("\""))), g["Char"]))),
|
||||||
|
cls("\"")),
|
||||||
|
tok(oom(seq(npd(cho(g["PrecedenceAssoc"], g["Space"], chr('}'))),
|
||||||
|
dot()))));
|
||||||
g["PrecedenceAssoc"] <= cls("LR");
|
g["PrecedenceAssoc"] <= cls("LR");
|
||||||
|
|
||||||
// Error message instruction
|
// Error message instruction
|
||||||
|
@ -300,6 +300,68 @@ TEST_CASE("Precedence climbing", "[precedence]") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Precedence climbing with literal operator", "[precedence]") {
|
||||||
|
parser parser(R"(
|
||||||
|
START <- _ EXPRESSION
|
||||||
|
EXPRESSION <- ATOM (OPERATOR ATOM)* {
|
||||||
|
precedence
|
||||||
|
L '#plus#' - # weaker
|
||||||
|
L '#multiply#' / # stronger
|
||||||
|
}
|
||||||
|
ATOM <- NUMBER / T('(') EXPRESSION T(')')
|
||||||
|
OPERATOR <- T('#plus#' / '#multiply#' / [-/])
|
||||||
|
NUMBER <- T('-'? [0-9]+)
|
||||||
|
~_ <- [ \t]*
|
||||||
|
T(S) <- < S > _
|
||||||
|
)");
|
||||||
|
|
||||||
|
REQUIRE(!!parser); // OK
|
||||||
|
|
||||||
|
parser.enable_packrat_parsing();
|
||||||
|
|
||||||
|
// Setup actions
|
||||||
|
parser["EXPRESSION"] = [](const SemanticValues &vs) -> long {
|
||||||
|
auto result = std::any_cast<long>(vs[0]);
|
||||||
|
if (vs.size() > 1) {
|
||||||
|
auto ope = std::any_cast<std::string>(vs[1]);
|
||||||
|
auto num = std::any_cast<long>(vs[2]);
|
||||||
|
if (ope == "#plus#") {
|
||||||
|
result += num;
|
||||||
|
} else if (ope == "-") {
|
||||||
|
result -= num;
|
||||||
|
} else if (ope == "#multiply#") {
|
||||||
|
result *= num;
|
||||||
|
} else if (ope == "/") {
|
||||||
|
result /= num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
parser["OPERATOR"] = [](const SemanticValues &vs) { return vs.token_to_string(); };
|
||||||
|
parser["NUMBER"] = [](const SemanticValues &vs) { return vs.token_to_number<long>(); };
|
||||||
|
|
||||||
|
bool ret = parser;
|
||||||
|
REQUIRE(ret == true);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto expr = " 1 #plus# 2 #multiply# 3 #multiply# (4 - 5 #plus# 6) / 7 - 8 ";
|
||||||
|
long val = 0;
|
||||||
|
ret = parser.parse(expr, val);
|
||||||
|
|
||||||
|
REQUIRE(ret == true);
|
||||||
|
REQUIRE(val == -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto expr = "-1#plus#-2--3"; // -1 + -2 - -3 = 0
|
||||||
|
long val = 0;
|
||||||
|
ret = parser.parse(expr, val);
|
||||||
|
|
||||||
|
REQUIRE(ret == true);
|
||||||
|
REQUIRE(val == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Precedence climbing with macro", "[precedence]") {
|
TEST_CASE("Precedence climbing with macro", "[precedence]") {
|
||||||
// Create a PEG parser
|
// Create a PEG parser
|
||||||
parser parser(R"(
|
parser parser(R"(
|
||||||
|
Loading…
Reference in New Issue
Block a user