mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +00:00
fix #52. Changed to allow Action handler taking non const SemanticValues
parameter
This commit is contained in:
parent
5b3ad705c4
commit
757e81e63d
84
peglib.h
84
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 <typename R>
|
||||
struct TypeAdaptor {
|
||||
TypeAdaptor(std::function<R (const SemanticValues& sv)> fn)
|
||||
struct TypeAdaptor_sv {
|
||||
TypeAdaptor_sv(std::function<R (SemanticValues& sv)> fn)
|
||||
: fn_(fn) {}
|
||||
any operator()(const SemanticValues& sv, any& /*dt*/) {
|
||||
any operator()(SemanticValues& sv, any& /*dt*/) {
|
||||
return call<R>(fn_, sv);
|
||||
}
|
||||
std::function<R (SemanticValues& sv)> fn_;
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
struct TypeAdaptor_csv {
|
||||
TypeAdaptor_csv(std::function<R (const SemanticValues& sv)> fn)
|
||||
: fn_(fn) {}
|
||||
any operator()(SemanticValues& sv, any& /*dt*/) {
|
||||
return call<R>(fn_, sv);
|
||||
}
|
||||
std::function<R (const SemanticValues& sv)> fn_;
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
struct TypeAdaptor_c {
|
||||
TypeAdaptor_c(std::function<R (const SemanticValues& sv, any& dt)> fn)
|
||||
struct TypeAdaptor_sv_dt {
|
||||
TypeAdaptor_sv_dt(std::function<R (SemanticValues& sv, any& dt)> fn)
|
||||
: fn_(fn) {}
|
||||
any operator()(const SemanticValues& sv, any& dt) {
|
||||
any operator()(SemanticValues& sv, any& dt) {
|
||||
return call<R>(fn_, sv, dt);
|
||||
}
|
||||
std::function<R (SemanticValues& sv, any& dt)> fn_;
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
struct TypeAdaptor_csv_dt {
|
||||
TypeAdaptor_csv_dt(std::function<R (const SemanticValues& sv, any& dt)> fn)
|
||||
: fn_(fn) {}
|
||||
any operator()(SemanticValues& sv, any& dt) {
|
||||
return call<R>(fn_, sv, dt);
|
||||
}
|
||||
std::function<R (const SemanticValues& sv, any& dt)> fn_;
|
||||
};
|
||||
|
||||
typedef std::function<any (const SemanticValues& sv, any& dt)> Fty;
|
||||
typedef std::function<any (SemanticValues& sv, any& dt)> Fty;
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv) const) {
|
||||
return TypeAdaptor_sv<R>(fn);
|
||||
}
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv) const) {
|
||||
return TypeAdaptor<R>(fn);
|
||||
return TypeAdaptor_csv<R>(fn);
|
||||
}
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv)) {
|
||||
return TypeAdaptor_sv<R>(fn);
|
||||
}
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv)) {
|
||||
return TypeAdaptor<R>(fn);
|
||||
return TypeAdaptor_csv<R>(fn);
|
||||
}
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R (* /*mf*/)(SemanticValues& sv)) {
|
||||
return TypeAdaptor_sv<R>(fn);
|
||||
}
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R (* /*mf*/)(const SemanticValues& sv)) {
|
||||
return TypeAdaptor<R>(fn);
|
||||
return TypeAdaptor_csv<R>(fn);
|
||||
}
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv, any& dt) const) {
|
||||
return TypeAdaptor_sv_dt<R>(fn);
|
||||
}
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv, any& dt) const) {
|
||||
return TypeAdaptor_c<R>(fn);
|
||||
return TypeAdaptor_csv_dt<R>(fn);
|
||||
}
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv, any& dt)) {
|
||||
return TypeAdaptor_sv_dt<R>(fn);
|
||||
}
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv, any& dt)) {
|
||||
return TypeAdaptor_c<R>(fn);
|
||||
return TypeAdaptor_csv_dt<R>(fn);
|
||||
}
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R(* /*mf*/)(SemanticValues& sv, any& dt)) {
|
||||
return TypeAdaptor_sv_dt<R>(fn);
|
||||
}
|
||||
|
||||
template<typename F, typename R>
|
||||
Fty make_adaptor(F fn, R(* /*mf*/)(const SemanticValues& sv, any& dt)) {
|
||||
return TypeAdaptor_c<R>(fn);
|
||||
return TypeAdaptor_csv_dt<R>(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> 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
23
test/test.cc
23
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<std::string>();
|
||||
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(
|
||||
|
Loading…
Reference in New Issue
Block a user