This commit is contained in:
yhirose 2018-11-29 20:19:46 -05:00
parent b76e4fe305
commit 15c19e4a0f
2 changed files with 34 additions and 4 deletions

View File

@ -510,6 +510,7 @@ struct SemanticValues : protected std::vector<any>
private: private:
friend class Context; friend class Context;
friend class Sequence;
friend class PrioritizedChoice; friend class PrioritizedChoice;
friend class Holder; 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 { size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
c.trace("Sequence", s, n, sv, dt); c.trace("Sequence", s, n, sv, dt);
auto& chldsv = c.push();
size_t i = 0; size_t i = 0;
for (const auto& ope : opes_) { for (const auto& ope : opes_) {
c.nest_level++; c.nest_level++;
auto se = make_scope_exit([&]() { c.nest_level--; }); auto se = make_scope_exit([&]() { c.nest_level--; });
const auto& rule = *ope; 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)) { if (fail(len)) {
return static_cast<size_t>(-1); return static_cast<size_t>(-1);
} }
i += len; 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; return i;
} }
@ -1004,9 +1010,7 @@ public:
const auto& rule = *ope; const auto& rule = *ope;
auto len = rule.parse(s, n, chldsv, c, dt); auto len = rule.parse(s, n, chldsv, c, dt);
if (success(len)) { 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.s_ = chldsv.c_str();
sv.n_ = chldsv.length(); sv.n_ = chldsv.length();
sv.choice_count_ = opes_.size(); sv.choice_count_ = opes_.size();

View File

@ -741,6 +741,32 @@ TEST_CASE("Definition duplicates test", "[general]")
REQUIRE(!parser); 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<string>() == "a at 0");
REQUIRE(sv[1].get<string>() == "b at 1");
REQUIRE(sv[2].get<string>() == "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]") TEST_CASE("Packrat parser test with %whitespace%", "[packrat]")
{ {
peg::parser parser(R"( peg::parser parser(R"(