Skip to content

Commit 2dcdafe

Browse files
committed
Fixed problem with choice and choice count
1 parent 51234df commit 2dcdafe

File tree

2 files changed

+58
-21
lines changed

2 files changed

+58
-21
lines changed

peglib.h

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,8 +1643,6 @@ struct Ope::Visitor
16431643

16441644
struct AssignIDToDefinition : public Ope::Visitor
16451645
{
1646-
using Ope::Visitor::visit;
1647-
16481646
void visit(Sequence& ope) override {
16491647
for (auto op: ope.opes_) {
16501648
op->accept(*this);
@@ -1676,8 +1674,6 @@ struct TokenChecker : public Ope::Visitor
16761674
{
16771675
TokenChecker() : has_token_boundary_(false), has_rule_(false) {}
16781676

1679-
using Ope::Visitor::visit;
1680-
16811677
void visit(Sequence& ope) override {
16821678
for (auto op: ope.opes_) {
16831679
op->accept(*this);
@@ -1699,8 +1695,10 @@ struct TokenChecker : public Ope::Visitor
16991695
void visit(Reference& ope) override;
17001696
void visit(Whitespace& ope) override { ope.ope_->accept(*this); }
17011697

1702-
bool is_token() const {
1703-
return has_token_boundary_ || !has_rule_;
1698+
static bool is_token(Ope& ope) {
1699+
TokenChecker vis;
1700+
ope.accept(vis);
1701+
return vis.has_token_boundary_ || !vis.has_rule_;
17041702
}
17051703

17061704
private:
@@ -1712,8 +1710,6 @@ struct DetectLeftRecursion : public Ope::Visitor {
17121710
DetectLeftRecursion(const std::string& name)
17131711
: error_s(nullptr), name_(name), done_(false) {}
17141712

1715-
using Ope::Visitor::visit;
1716-
17171713
void visit(Sequence& ope) override {
17181714
for (auto op: ope.opes_) {
17191715
op->accept(*this);
@@ -1768,8 +1764,6 @@ struct ReferenceChecker : public Ope::Visitor {
17681764
const std::vector<std::string>& params)
17691765
: grammar_(grammar), params_(params) {}
17701766

1771-
using Ope::Visitor::visit;
1772-
17731767
void visit(Sequence& ope) override {
17741768
for (auto op: ope.opes_) {
17751769
op->accept(*this);
@@ -1808,8 +1802,6 @@ struct LinkReferences : public Ope::Visitor {
18081802
const std::vector<std::string>& params)
18091803
: grammar_(grammar), params_(params) {}
18101804

1811-
using Ope::Visitor::visit;
1812-
18131805
void visit(Sequence& ope) override {
18141806
for (auto op: ope.opes_) {
18151807
op->accept(*this);
@@ -1845,8 +1837,6 @@ struct FindReference : public Ope::Visitor {
18451837
const std::vector<std::string>& params)
18461838
: args_(args), params_(params) {}
18471839

1848-
using Ope::Visitor::visit;
1849-
18501840
void visit(Sequence& ope) override {
18511841
std::vector<std::shared_ptr<Ope>> opes;
18521842
for (auto o: ope.opes_) {
@@ -1888,6 +1878,24 @@ struct FindReference : public Ope::Visitor {
18881878
const std::vector<std::string>& params_;
18891879
};
18901880

1881+
struct IsPrioritizedChoice : public Ope::Visitor
1882+
{
1883+
IsPrioritizedChoice() : is_prioritized_choice_(false) {}
1884+
1885+
void visit(PrioritizedChoice& /*ope*/) override {
1886+
is_prioritized_choice_ = true;
1887+
}
1888+
1889+
static bool is_prioritized_choice(Ope& ope) {
1890+
IsPrioritizedChoice vis;
1891+
ope.accept(vis);
1892+
return vis.is_prioritized_choice_;
1893+
}
1894+
1895+
private:
1896+
bool is_prioritized_choice_;
1897+
};
1898+
18911899
/*
18921900
* Keywords
18931901
*/
@@ -2038,9 +2046,7 @@ class Definition
20382046

20392047
bool is_token() const {
20402048
std::call_once(is_token_init_, [this]() {
2041-
TokenChecker vis;
2042-
get_core_operator()->accept(vis);
2043-
is_token_ = vis.is_token();
2049+
is_token_ = TokenChecker::is_token(*get_core_operator());
20442050
});
20452051
return is_token_;
20462052
}
@@ -2179,8 +2185,7 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
21792185
// Macro reference
21802186
// TODO: need packrat support
21812187
if (outer_->is_macro) {
2182-
const auto& rule = *ope_;
2183-
return rule.parse(s, n, sv, c, dt);
2188+
return ope_->parse(s, n, sv, c, dt);
21842189
}
21852190

21862191
size_t len;
@@ -2201,14 +2206,18 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
22012206

22022207
auto& chldsv = c.push();
22032208

2204-
const auto& rule = *ope_;
2205-
len = rule.parse(s, n, chldsv, c, dt);
2209+
len = ope_->parse(s, n, chldsv, c, dt);
22062210

22072211
// Invoke action
22082212
if (success(len)) {
22092213
chldsv.s_ = s;
22102214
chldsv.n_ = len;
22112215

2216+
if (!IsPrioritizedChoice::is_prioritized_choice(*ope_)) {
2217+
chldsv.choice_count_ = 0;
2218+
chldsv.choice_ = 0;
2219+
}
2220+
22122221
try {
22132222
a_val = reduce(chldsv, dt);
22142223
} catch (const parse_error& e) {

test/test.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,34 @@ TEST_CASE("Semantic values test", "[general]")
767767
REQUIRE(parser.parse("abc"));
768768
}
769769

770+
TEST_CASE("Ordered choice count", "[general]")
771+
{
772+
auto syntax = R"(S <- 'a' / 'b')";
773+
774+
parser parser(syntax);
775+
776+
parser["S"] = [](const SemanticValues& sv) {
777+
REQUIRE(sv.choice() == 1);
778+
REQUIRE(sv.choice_count() == 2);
779+
};
780+
781+
parser.parse("b");
782+
}
783+
784+
TEST_CASE("Ordered choice count 2", "[general]")
785+
{
786+
auto syntax = R"(S <- ('a' / 'b')*)";
787+
788+
parser parser(syntax);
789+
790+
parser["S"] = [](const SemanticValues& sv) {
791+
REQUIRE(sv.choice() == 0);
792+
REQUIRE(sv.choice_count() == 0);
793+
};
794+
795+
parser.parse("b");
796+
}
797+
770798
TEST_CASE("Packrat parser test with %whitespace%", "[packrat]")
771799
{
772800
peg::parser parser(R"(

0 commit comments

Comments
 (0)