From 15c19e4a0fd8c157d507eb6fa85c49522bb17ed0 Mon Sep 17 00:00:00 2001 From: yhirose Date: Thu, 29 Nov 2018 20:19:46 -0500 Subject: [PATCH] fix #55 --- peglib.h | 12 ++++++++---- test/test.cc | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/peglib.h b/peglib.h index a54fb2e..f8d5b62 100644 --- a/peglib.h +++ b/peglib.h @@ -510,6 +510,7 @@ struct SemanticValues : protected std::vector private: friend class Context; + friend class Sequence; friend class PrioritizedChoice; friend class Holder; @@ -948,17 +949,22 @@ public: size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { c.trace("Sequence", s, n, sv, dt); + auto& chldsv = c.push(); size_t i = 0; for (const auto& ope : opes_) { c.nest_level++; auto se = make_scope_exit([&]() { c.nest_level--; }); const auto& rule = *ope; - auto len = rule.parse(s + i, n - i, sv, c, dt); + auto len = rule.parse(s + i, n - i, chldsv, c, dt); if (fail(len)) { return static_cast(-1); } i += len; } + sv.insert(sv.end(), chldsv.begin(), chldsv.end()); + sv.s_ = chldsv.c_str(); + sv.n_ = chldsv.length(); + sv.tokens.insert(sv.tokens.end(), chldsv.tokens.begin(), chldsv.tokens.end()); return i; } @@ -1004,9 +1010,7 @@ public: const auto& rule = *ope; auto len = rule.parse(s, n, chldsv, c, dt); if (success(len)) { - if (!chldsv.empty()) { - sv.insert(sv.end(), chldsv.begin(), chldsv.end()); - } + sv.insert(sv.end(), chldsv.begin(), chldsv.end()); sv.s_ = chldsv.c_str(); sv.n_ = chldsv.length(); sv.choice_count_ = opes_.size(); diff --git a/test/test.cc b/test/test.cc index 6a76c3d..cde1129 100644 --- a/test/test.cc +++ b/test/test.cc @@ -741,6 +741,32 @@ TEST_CASE("Definition duplicates test", "[general]") REQUIRE(!parser); } +TEST_CASE("Semantic values test", "[general]") +{ + parser parser(R"( + term <- ( a b c x )? a b c + a <- 'a' + b <- 'b' + c <- 'c' + x <- 'x' + )"); + + for (const auto& rule: parser.get_rule_names()){ + parser[rule.c_str()] = [rule](const SemanticValues& sv, any&) { + if (rule == "term") { + REQUIRE(sv[0].get() == "a at 0"); + REQUIRE(sv[1].get() == "b at 1"); + REQUIRE(sv[2].get() == "c at 2"); + return string(); + } else { + return rule + " at " + to_string(sv.c_str() - sv.ss); + } + }; + } + + REQUIRE(parser.parse("abc")); +} + TEST_CASE("Packrat parser test with %whitespace%", "[packrat]") { peg::parser parser(R"(