From 757e81e63d5b359739f5daf42506c0b84a1dfa9a Mon Sep 17 00:00:00 2001 From: yhirose Date: Sun, 7 Oct 2018 09:25:12 -0400 Subject: [PATCH] fix #52. Changed to allow Action handler taking non const SemanticValues parameter --- peglib.h | 84 +++++++++++++++++++++++++++++++++++++++++----------- test/test.cc | 23 ++++++++++++++ 2 files changed, 90 insertions(+), 17 deletions(-) diff --git a/peglib.h b/peglib.h index b2b3513..98c41aa 100644 --- a/peglib.h +++ b/peglib.h @@ -599,61 +599,111 @@ public: return bool(fn_); } - any operator()(const SemanticValues& sv, any& dt) const { + any operator()(SemanticValues& sv, any& dt) const { return fn_(sv, dt); } private: template - struct TypeAdaptor { - TypeAdaptor(std::function fn) + struct TypeAdaptor_sv { + TypeAdaptor_sv(std::function fn) : fn_(fn) {} - any operator()(const SemanticValues& sv, any& /*dt*/) { + any operator()(SemanticValues& sv, any& /*dt*/) { + return call(fn_, sv); + } + std::function fn_; + }; + + template + struct TypeAdaptor_csv { + TypeAdaptor_csv(std::function fn) + : fn_(fn) {} + any operator()(SemanticValues& sv, any& /*dt*/) { return call(fn_, sv); } std::function fn_; }; template - struct TypeAdaptor_c { - TypeAdaptor_c(std::function fn) + struct TypeAdaptor_sv_dt { + TypeAdaptor_sv_dt(std::function fn) : fn_(fn) {} - any operator()(const SemanticValues& sv, any& dt) { + any operator()(SemanticValues& sv, any& dt) { + return call(fn_, sv, dt); + } + std::function fn_; + }; + + template + struct TypeAdaptor_csv_dt { + TypeAdaptor_csv_dt(std::function fn) + : fn_(fn) {} + any operator()(SemanticValues& sv, any& dt) { return call(fn_, sv, dt); } std::function fn_; }; - typedef std::function Fty; + typedef std::function Fty; + + template + Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv) const) { + return TypeAdaptor_sv(fn); + } template Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv) const) { - return TypeAdaptor(fn); + return TypeAdaptor_csv(fn); + } + + template + Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv)) { + return TypeAdaptor_sv(fn); } template Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv)) { - return TypeAdaptor(fn); + return TypeAdaptor_csv(fn); + } + + template + Fty make_adaptor(F fn, R (* /*mf*/)(SemanticValues& sv)) { + return TypeAdaptor_sv(fn); } template Fty make_adaptor(F fn, R (* /*mf*/)(const SemanticValues& sv)) { - return TypeAdaptor(fn); + return TypeAdaptor_csv(fn); + } + + template + Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv, any& dt) const) { + return TypeAdaptor_sv_dt(fn); } template Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv, any& dt) const) { - return TypeAdaptor_c(fn); + return TypeAdaptor_csv_dt(fn); + } + + template + Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv, any& dt)) { + return TypeAdaptor_sv_dt(fn); } template Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv, any& dt)) { - return TypeAdaptor_c(fn); + return TypeAdaptor_csv_dt(fn); + } + + template + Fty make_adaptor(F fn, R(* /*mf*/)(SemanticValues& sv, any& dt)) { + return TypeAdaptor_sv_dt(fn); } template Fty make_adaptor(F fn, R(* /*mf*/)(const SemanticValues& sv, any& dt)) { - return TypeAdaptor_c(fn); + return TypeAdaptor_csv_dt(fn); } Fty fn_; @@ -1387,7 +1437,7 @@ public: void accept(Visitor& v) override; - any reduce(const SemanticValues& sv, any& dt) const; + any reduce(SemanticValues& sv, any& dt) const; std::shared_ptr ope_; Definition* outer_; @@ -2177,13 +2227,13 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context return len; } -inline any Holder::reduce(const SemanticValues& sv, any& dt) const { +inline any Holder::reduce(SemanticValues& sv, any& dt) const { if (outer_->action) { return outer_->action(sv, dt); } else if (sv.empty()) { return any(); } else { - return sv.front(); + return std::move(sv.front()); } } diff --git a/test/test.cc b/test/test.cc index d851b21..6a76c3d 100644 --- a/test/test.cc +++ b/test/test.cc @@ -36,6 +36,29 @@ TEST_CASE("Empty syntax test", "[general]") REQUIRE(ret == false); } +TEST_CASE("Action taking non const Semantic Values parameter", "[general]") +{ + peg::parser parser(R"( + ROOT <- TEXT + TEXT <- [a-zA-Z]+ + )"); + + parser["ROOT"] = [&](peg::SemanticValues& sv) { + auto& s = sv[0].get(); + s[0] = 'H'; // mutate + return std::string(std::move(s)); // move + }; + + parser["TEXT"] = [&](peg::SemanticValues& sv) { + return sv.token(); + }; + + std::string val; + auto ret = parser.parse("hello", val); + REQUIRE(ret == true); + REQUIRE(val == "Hello"); +} + TEST_CASE("String capture test", "[general]") { peg::parser parser(