Fixed problem with choice and choice count

This commit is contained in:
yhirose 2019-02-12 22:50:23 -05:00
parent 51234df3df
commit 2dcdafe3cb
2 changed files with 58 additions and 21 deletions

View File

@ -1643,8 +1643,6 @@ struct Ope::Visitor
struct AssignIDToDefinition : public Ope::Visitor struct AssignIDToDefinition : public Ope::Visitor
{ {
using Ope::Visitor::visit;
void visit(Sequence& ope) override { void visit(Sequence& ope) override {
for (auto op: ope.opes_) { for (auto op: ope.opes_) {
op->accept(*this); op->accept(*this);
@ -1676,8 +1674,6 @@ struct TokenChecker : public Ope::Visitor
{ {
TokenChecker() : has_token_boundary_(false), has_rule_(false) {} TokenChecker() : has_token_boundary_(false), has_rule_(false) {}
using Ope::Visitor::visit;
void visit(Sequence& ope) override { void visit(Sequence& ope) override {
for (auto op: ope.opes_) { for (auto op: ope.opes_) {
op->accept(*this); op->accept(*this);
@ -1699,8 +1695,10 @@ struct TokenChecker : public Ope::Visitor
void visit(Reference& ope) override; void visit(Reference& ope) override;
void visit(Whitespace& ope) override { ope.ope_->accept(*this); } void visit(Whitespace& ope) override { ope.ope_->accept(*this); }
bool is_token() const { static bool is_token(Ope& ope) {
return has_token_boundary_ || !has_rule_; TokenChecker vis;
ope.accept(vis);
return vis.has_token_boundary_ || !vis.has_rule_;
} }
private: private:
@ -1712,8 +1710,6 @@ struct DetectLeftRecursion : public Ope::Visitor {
DetectLeftRecursion(const std::string& name) DetectLeftRecursion(const std::string& name)
: error_s(nullptr), name_(name), done_(false) {} : error_s(nullptr), name_(name), done_(false) {}
using Ope::Visitor::visit;
void visit(Sequence& ope) override { void visit(Sequence& ope) override {
for (auto op: ope.opes_) { for (auto op: ope.opes_) {
op->accept(*this); op->accept(*this);
@ -1768,8 +1764,6 @@ struct ReferenceChecker : public Ope::Visitor {
const std::vector<std::string>& params) const std::vector<std::string>& params)
: grammar_(grammar), params_(params) {} : grammar_(grammar), params_(params) {}
using Ope::Visitor::visit;
void visit(Sequence& ope) override { void visit(Sequence& ope) override {
for (auto op: ope.opes_) { for (auto op: ope.opes_) {
op->accept(*this); op->accept(*this);
@ -1808,8 +1802,6 @@ struct LinkReferences : public Ope::Visitor {
const std::vector<std::string>& params) const std::vector<std::string>& params)
: grammar_(grammar), params_(params) {} : grammar_(grammar), params_(params) {}
using Ope::Visitor::visit;
void visit(Sequence& ope) override { void visit(Sequence& ope) override {
for (auto op: ope.opes_) { for (auto op: ope.opes_) {
op->accept(*this); op->accept(*this);
@ -1845,8 +1837,6 @@ struct FindReference : public Ope::Visitor {
const std::vector<std::string>& params) const std::vector<std::string>& params)
: args_(args), params_(params) {} : args_(args), params_(params) {}
using Ope::Visitor::visit;
void visit(Sequence& ope) override { void visit(Sequence& ope) override {
std::vector<std::shared_ptr<Ope>> opes; std::vector<std::shared_ptr<Ope>> opes;
for (auto o: ope.opes_) { for (auto o: ope.opes_) {
@ -1888,6 +1878,24 @@ private:
const std::vector<std::string>& params_; const std::vector<std::string>& 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 * Keywords
*/ */
@ -2038,9 +2046,7 @@ public:
bool is_token() const { bool is_token() const {
std::call_once(is_token_init_, [this]() { std::call_once(is_token_init_, [this]() {
TokenChecker vis; is_token_ = TokenChecker::is_token(*get_core_operator());
get_core_operator()->accept(vis);
is_token_ = vis.is_token();
}); });
return is_token_; return is_token_;
} }
@ -2179,8 +2185,7 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
// Macro reference // Macro reference
// TODO: need packrat support // TODO: need packrat support
if (outer_->is_macro) { if (outer_->is_macro) {
const auto& rule = *ope_; return ope_->parse(s, n, sv, c, dt);
return rule.parse(s, n, sv, c, dt);
} }
size_t len; 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(); auto& chldsv = c.push();
const auto& rule = *ope_; len = ope_->parse(s, n, chldsv, c, dt);
len = rule.parse(s, n, chldsv, c, dt);
// Invoke action // Invoke action
if (success(len)) { if (success(len)) {
chldsv.s_ = s; chldsv.s_ = s;
chldsv.n_ = len; chldsv.n_ = len;
if (!IsPrioritizedChoice::is_prioritized_choice(*ope_)) {
chldsv.choice_count_ = 0;
chldsv.choice_ = 0;
}
try { try {
a_val = reduce(chldsv, dt); a_val = reduce(chldsv, dt);
} catch (const parse_error& e) { } catch (const parse_error& e) {

View File

@ -767,6 +767,34 @@ TEST_CASE("Semantic values test", "[general]")
REQUIRE(parser.parse("abc")); 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]") TEST_CASE("Packrat parser test with %whitespace%", "[packrat]")
{ {
peg::parser parser(R"( peg::parser parser(R"(