From 2dcdafe3cb99acd998144ce6f25536d5880bf68d Mon Sep 17 00:00:00 2001 From: yhirose Date: Tue, 12 Feb 2019 22:50:23 -0500 Subject: [PATCH] Fixed problem with choice and choice count --- peglib.h | 51 ++++++++++++++++++++++++++++++--------------------- test/test.cc | 28 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/peglib.h b/peglib.h index 2b2709a..09b516f 100644 --- a/peglib.h +++ b/peglib.h @@ -1643,8 +1643,6 @@ struct Ope::Visitor struct AssignIDToDefinition : public Ope::Visitor { - using Ope::Visitor::visit; - void visit(Sequence& ope) override { for (auto op: ope.opes_) { op->accept(*this); @@ -1676,8 +1674,6 @@ struct TokenChecker : public Ope::Visitor { TokenChecker() : has_token_boundary_(false), has_rule_(false) {} - using Ope::Visitor::visit; - void visit(Sequence& ope) override { for (auto op: ope.opes_) { op->accept(*this); @@ -1699,8 +1695,10 @@ struct TokenChecker : public Ope::Visitor void visit(Reference& ope) override; void visit(Whitespace& ope) override { ope.ope_->accept(*this); } - bool is_token() const { - return has_token_boundary_ || !has_rule_; + static bool is_token(Ope& ope) { + TokenChecker vis; + ope.accept(vis); + return vis.has_token_boundary_ || !vis.has_rule_; } private: @@ -1712,8 +1710,6 @@ struct DetectLeftRecursion : public Ope::Visitor { DetectLeftRecursion(const std::string& name) : error_s(nullptr), name_(name), done_(false) {} - using Ope::Visitor::visit; - void visit(Sequence& ope) override { for (auto op: ope.opes_) { op->accept(*this); @@ -1768,8 +1764,6 @@ struct ReferenceChecker : public Ope::Visitor { const std::vector& params) : grammar_(grammar), params_(params) {} - using Ope::Visitor::visit; - void visit(Sequence& ope) override { for (auto op: ope.opes_) { op->accept(*this); @@ -1808,8 +1802,6 @@ struct LinkReferences : public Ope::Visitor { const std::vector& params) : grammar_(grammar), params_(params) {} - using Ope::Visitor::visit; - void visit(Sequence& ope) override { for (auto op: ope.opes_) { op->accept(*this); @@ -1845,8 +1837,6 @@ struct FindReference : public Ope::Visitor { const std::vector& params) : args_(args), params_(params) {} - using Ope::Visitor::visit; - void visit(Sequence& ope) override { std::vector> opes; for (auto o: ope.opes_) { @@ -1888,6 +1878,24 @@ private: const std::vector& params_; }; +struct IsPrioritizedChoice : public Ope::Visitor +{ + IsPrioritizedChoice() : is_prioritized_choice_(false) {} + + void visit(PrioritizedChoice& /*ope*/) override { + is_prioritized_choice_ = true; + } + + static bool is_prioritized_choice(Ope& ope) { + IsPrioritizedChoice vis; + ope.accept(vis); + return vis.is_prioritized_choice_; + } + +private: + bool is_prioritized_choice_; +}; + /* * Keywords */ @@ -2038,9 +2046,7 @@ public: bool is_token() const { std::call_once(is_token_init_, [this]() { - TokenChecker vis; - get_core_operator()->accept(vis); - is_token_ = vis.is_token(); + is_token_ = TokenChecker::is_token(*get_core_operator()); }); return is_token_; } @@ -2179,8 +2185,7 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context // Macro reference // TODO: need packrat support if (outer_->is_macro) { - const auto& rule = *ope_; - return rule.parse(s, n, sv, c, dt); + return ope_->parse(s, n, sv, c, dt); } size_t len; @@ -2201,14 +2206,18 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context auto& chldsv = c.push(); - const auto& rule = *ope_; - len = rule.parse(s, n, chldsv, c, dt); + len = ope_->parse(s, n, chldsv, c, dt); // Invoke action if (success(len)) { chldsv.s_ = s; chldsv.n_ = len; + if (!IsPrioritizedChoice::is_prioritized_choice(*ope_)) { + chldsv.choice_count_ = 0; + chldsv.choice_ = 0; + } + try { a_val = reduce(chldsv, dt); } catch (const parse_error& e) { diff --git a/test/test.cc b/test/test.cc index cde1129..6f381c0 100644 --- a/test/test.cc +++ b/test/test.cc @@ -767,6 +767,34 @@ TEST_CASE("Semantic values test", "[general]") REQUIRE(parser.parse("abc")); } +TEST_CASE("Ordered choice count", "[general]") +{ + auto syntax = R"(S <- 'a' / 'b')"; + + parser parser(syntax); + + parser["S"] = [](const SemanticValues& sv) { + REQUIRE(sv.choice() == 1); + REQUIRE(sv.choice_count() == 2); + }; + + parser.parse("b"); +} + +TEST_CASE("Ordered choice count 2", "[general]") +{ + auto syntax = R"(S <- ('a' / 'b')*)"; + + parser parser(syntax); + + parser["S"] = [](const SemanticValues& sv) { + REQUIRE(sv.choice() == 0); + REQUIRE(sv.choice_count() == 0); + }; + + parser.parse("b"); +} + TEST_CASE("Packrat parser test with %whitespace%", "[packrat]") { peg::parser parser(R"(