mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-23 04:15:31 +00:00
Fixed problem with choice and choice count
This commit is contained in:
parent
51234df3df
commit
2dcdafe3cb
51
peglib.h
51
peglib.h
@ -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) {
|
||||||
|
28
test/test.cc
28
test/test.cc
@ -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"(
|
||||||
|
Loading…
Reference in New Issue
Block a user