Skip to content

Commit 757e81e

Browse files
committed
fix yhirose#52. Changed to allow Action handler taking non const SemanticValues
parameter
1 parent 5b3ad70 commit 757e81e

File tree

2 files changed

+90
-17
lines changed

2 files changed

+90
-17
lines changed

peglib.h

Lines changed: 67 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -599,61 +599,111 @@ class Action
599599
return bool(fn_);
600600
}
601601

602-
any operator()(const SemanticValues& sv, any& dt) const {
602+
any operator()(SemanticValues& sv, any& dt) const {
603603
return fn_(sv, dt);
604604
}
605605

606606
private:
607607
template <typename R>
608-
struct TypeAdaptor {
609-
TypeAdaptor(std::function<R (const SemanticValues& sv)> fn)
608+
struct TypeAdaptor_sv {
609+
TypeAdaptor_sv(std::function<R (SemanticValues& sv)> fn)
610610
: fn_(fn) {}
611-
any operator()(const SemanticValues& sv, any& /*dt*/) {
611+
any operator()(SemanticValues& sv, any& /*dt*/) {
612+
return call<R>(fn_, sv);
613+
}
614+
std::function<R (SemanticValues& sv)> fn_;
615+
};
616+
617+
template <typename R>
618+
struct TypeAdaptor_csv {
619+
TypeAdaptor_csv(std::function<R (const SemanticValues& sv)> fn)
620+
: fn_(fn) {}
621+
any operator()(SemanticValues& sv, any& /*dt*/) {
612622
return call<R>(fn_, sv);
613623
}
614624
std::function<R (const SemanticValues& sv)> fn_;
615625
};
616626

617627
template <typename R>
618-
struct TypeAdaptor_c {
619-
TypeAdaptor_c(std::function<R (const SemanticValues& sv, any& dt)> fn)
628+
struct TypeAdaptor_sv_dt {
629+
TypeAdaptor_sv_dt(std::function<R (SemanticValues& sv, any& dt)> fn)
620630
: fn_(fn) {}
621-
any operator()(const SemanticValues& sv, any& dt) {
631+
any operator()(SemanticValues& sv, any& dt) {
632+
return call<R>(fn_, sv, dt);
633+
}
634+
std::function<R (SemanticValues& sv, any& dt)> fn_;
635+
};
636+
637+
template <typename R>
638+
struct TypeAdaptor_csv_dt {
639+
TypeAdaptor_csv_dt(std::function<R (const SemanticValues& sv, any& dt)> fn)
640+
: fn_(fn) {}
641+
any operator()(SemanticValues& sv, any& dt) {
622642
return call<R>(fn_, sv, dt);
623643
}
624644
std::function<R (const SemanticValues& sv, any& dt)> fn_;
625645
};
626646

627-
typedef std::function<any (const SemanticValues& sv, any& dt)> Fty;
647+
typedef std::function<any (SemanticValues& sv, any& dt)> Fty;
648+
649+
template<typename F, typename R>
650+
Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv) const) {
651+
return TypeAdaptor_sv<R>(fn);
652+
}
628653

629654
template<typename F, typename R>
630655
Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv) const) {
631-
return TypeAdaptor<R>(fn);
656+
return TypeAdaptor_csv<R>(fn);
657+
}
658+
659+
template<typename F, typename R>
660+
Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv)) {
661+
return TypeAdaptor_sv<R>(fn);
632662
}
633663

634664
template<typename F, typename R>
635665
Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv)) {
636-
return TypeAdaptor<R>(fn);
666+
return TypeAdaptor_csv<R>(fn);
667+
}
668+
669+
template<typename F, typename R>
670+
Fty make_adaptor(F fn, R (* /*mf*/)(SemanticValues& sv)) {
671+
return TypeAdaptor_sv<R>(fn);
637672
}
638673

639674
template<typename F, typename R>
640675
Fty make_adaptor(F fn, R (* /*mf*/)(const SemanticValues& sv)) {
641-
return TypeAdaptor<R>(fn);
676+
return TypeAdaptor_csv<R>(fn);
677+
}
678+
679+
template<typename F, typename R>
680+
Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv, any& dt) const) {
681+
return TypeAdaptor_sv_dt<R>(fn);
642682
}
643683

644684
template<typename F, typename R>
645685
Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv, any& dt) const) {
646-
return TypeAdaptor_c<R>(fn);
686+
return TypeAdaptor_csv_dt<R>(fn);
687+
}
688+
689+
template<typename F, typename R>
690+
Fty make_adaptor(F fn, R (F::* /*mf*/)(SemanticValues& sv, any& dt)) {
691+
return TypeAdaptor_sv_dt<R>(fn);
647692
}
648693

649694
template<typename F, typename R>
650695
Fty make_adaptor(F fn, R (F::* /*mf*/)(const SemanticValues& sv, any& dt)) {
651-
return TypeAdaptor_c<R>(fn);
696+
return TypeAdaptor_csv_dt<R>(fn);
697+
}
698+
699+
template<typename F, typename R>
700+
Fty make_adaptor(F fn, R(* /*mf*/)(SemanticValues& sv, any& dt)) {
701+
return TypeAdaptor_sv_dt<R>(fn);
652702
}
653703

654704
template<typename F, typename R>
655705
Fty make_adaptor(F fn, R(* /*mf*/)(const SemanticValues& sv, any& dt)) {
656-
return TypeAdaptor_c<R>(fn);
706+
return TypeAdaptor_csv_dt<R>(fn);
657707
}
658708

659709
Fty fn_;
@@ -1387,7 +1437,7 @@ class Holder : public Ope
13871437

13881438
void accept(Visitor& v) override;
13891439

1390-
any reduce(const SemanticValues& sv, any& dt) const;
1440+
any reduce(SemanticValues& sv, any& dt) const;
13911441

13921442
std::shared_ptr<Ope> ope_;
13931443
Definition* outer_;
@@ -2177,13 +2227,13 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
21772227
return len;
21782228
}
21792229

2180-
inline any Holder::reduce(const SemanticValues& sv, any& dt) const {
2230+
inline any Holder::reduce(SemanticValues& sv, any& dt) const {
21812231
if (outer_->action) {
21822232
return outer_->action(sv, dt);
21832233
} else if (sv.empty()) {
21842234
return any();
21852235
} else {
2186-
return sv.front();
2236+
return std::move(sv.front());
21872237
}
21882238
}
21892239

test/test.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,29 @@ TEST_CASE("Empty syntax test", "[general]")
3636
REQUIRE(ret == false);
3737
}
3838

39+
TEST_CASE("Action taking non const Semantic Values parameter", "[general]")
40+
{
41+
peg::parser parser(R"(
42+
ROOT <- TEXT
43+
TEXT <- [a-zA-Z]+
44+
)");
45+
46+
parser["ROOT"] = [&](peg::SemanticValues& sv) {
47+
auto& s = sv[0].get<std::string>();
48+
s[0] = 'H'; // mutate
49+
return std::string(std::move(s)); // move
50+
};
51+
52+
parser["TEXT"] = [&](peg::SemanticValues& sv) {
53+
return sv.token();
54+
};
55+
56+
std::string val;
57+
auto ret = parser.parse("hello", val);
58+
REQUIRE(ret == true);
59+
REQUIRE(val == "Hello");
60+
}
61+
3962
TEST_CASE("String capture test", "[general]")
4063
{
4164
peg::parser parser(

0 commit comments

Comments
 (0)