Skip to content

Commit d75ced2

Browse files
committed
1 parent 6974923 commit d75ced2

File tree

2 files changed

+79
-15
lines changed

2 files changed

+79
-15
lines changed

peglib.h

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,6 +1674,33 @@ struct AssignIDToDefinition : public Ope::Visitor
16741674
std::unordered_map<void*, size_t> ids;
16751675
};
16761676

1677+
struct IsLiteralToken : public Ope::Visitor
1678+
{
1679+
IsLiteralToken() : result_(false) {}
1680+
1681+
void visit(PrioritizedChoice& ope) override {
1682+
for (auto op: ope.opes_) {
1683+
if (!IsLiteralToken::check(*op)) {
1684+
return;
1685+
}
1686+
}
1687+
result_ = true;
1688+
}
1689+
1690+
void visit(LiteralString& /*ope*/) override {
1691+
result_ = true;
1692+
}
1693+
1694+
static bool check(Ope& ope) {
1695+
IsLiteralToken vis;
1696+
ope.accept(vis);
1697+
return vis.result_;
1698+
}
1699+
1700+
private:
1701+
bool result_;
1702+
};
1703+
16771704
struct TokenChecker : public Ope::Visitor
16781705
{
16791706
TokenChecker() : has_token_boundary_(false), has_rule_(false) {}
@@ -1700,6 +1727,10 @@ struct TokenChecker : public Ope::Visitor
17001727
void visit(Whitespace& ope) override { ope.ope_->accept(*this); }
17011728

17021729
static bool is_token(Ope& ope) {
1730+
if (IsLiteralToken::check(ope)) {
1731+
return true;
1732+
}
1733+
17031734
TokenChecker vis;
17041735
ope.accept(vis);
17051736
return vis.has_token_boundary_ || !vis.has_rule_;
@@ -1884,20 +1915,20 @@ struct FindReference : public Ope::Visitor {
18841915

18851916
struct IsPrioritizedChoice : public Ope::Visitor
18861917
{
1887-
IsPrioritizedChoice() : is_prioritized_choice_(false) {}
1918+
IsPrioritizedChoice() : result_(false) {}
18881919

18891920
void visit(PrioritizedChoice& /*ope*/) override {
1890-
is_prioritized_choice_ = true;
1921+
result_ = true;
18911922
}
18921923

1893-
static bool is_prioritized_choice(Ope& ope) {
1924+
static bool check(Ope& ope) {
18941925
IsPrioritizedChoice vis;
18951926
ope.accept(vis);
1896-
return vis.is_prioritized_choice_;
1927+
return vis.result_;
18971928
}
18981929

18991930
private:
1900-
bool is_prioritized_choice_;
1931+
bool result_;
19011932
};
19021933

19031934
/*
@@ -2218,7 +2249,7 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
22182249
chldsv.n_ = len;
22192250
chldsv.name_ = outer_->name;
22202251

2221-
if (!IsPrioritizedChoice::is_prioritized_choice(*ope_)) {
2252+
if (!IsPrioritizedChoice::check(*ope_)) {
22222253
chldsv.choice_count_ = 0;
22232254
chldsv.choice_ = 0;
22242255
}
@@ -2885,6 +2916,14 @@ class ParserGenerator
28852916

28862917
// Automatic whitespace skipping
28872918
if (grammar.count(WHITESPACE_DEFINITION_NAME)) {
2919+
for (auto& x: grammar) {
2920+
auto& rule = x.second;
2921+
auto ope = rule.get_core_operator();
2922+
if (IsLiteralToken::check(*ope)) {
2923+
rule <= tok(ope);
2924+
}
2925+
}
2926+
28882927
auto& rule = (*data.grammar)[start];
28892928
rule.whitespaceOpe = wsp((*data.grammar)[WHITESPACE_DEFINITION_NAME].get_core_operator());
28902929
}

test/test.cc

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,15 @@ TEST_CASE("Visit test", "[general]")
155155

156156
TEST_CASE("Token check test", "[general]")
157157
{
158-
parser parser(
159-
" EXPRESSION <- _ TERM (TERM_OPERATOR TERM)* "
160-
" TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* "
161-
" FACTOR <- NUMBER / '(' _ EXPRESSION ')' _ "
162-
" TERM_OPERATOR <- < [-+] > _ "
163-
" FACTOR_OPERATOR <- < [/*] > _ "
164-
" NUMBER <- < [0-9]+ > _ "
165-
" _ <- [ \t\r\n]* "
166-
);
158+
parser parser(R"(
159+
EXPRESSION <- _ TERM (TERM_OPERATOR TERM)*
160+
TERM <- FACTOR (FACTOR_OPERATOR FACTOR)*
161+
FACTOR <- NUMBER / '(' _ EXPRESSION ')' _
162+
TERM_OPERATOR <- < [-+] > _
163+
FACTOR_OPERATOR <- < [/*] > _
164+
NUMBER <- < [0-9]+ > _
165+
_ <- [ \t\r\n]*
166+
)");
167167

168168
REQUIRE(parser["EXPRESSION"].is_token() == false);
169169
REQUIRE(parser["FACTOR"].is_token() == false);
@@ -295,6 +295,31 @@ TEST_CASE("WHITESPACE test3", "[general]") {
295295
REQUIRE(ret == true);
296296
}
297297

298+
TEST_CASE("WHITESPACE test4", "[general]") {
299+
peg::parser parser(R"(
300+
ROOT <- HELLO OPE WORLD
301+
HELLO <- 'hello'
302+
OPE <- < [-+] >
303+
WORLD <- 'world' / 'WORLD'
304+
%whitespace <- [ \t\r\n]*
305+
)");
306+
307+
parser["HELLO"] = [](const SemanticValues& sv) {
308+
REQUIRE(sv.token() == "hello");
309+
};
310+
311+
parser["OPE"] = [](const SemanticValues& sv) {
312+
REQUIRE(sv.token() == "+");
313+
};
314+
315+
parser["WORLD"] = [](const SemanticValues& sv) {
316+
REQUIRE(sv.token() == "world");
317+
};
318+
319+
auto ret = parser.parse(" hello + world ");
320+
REQUIRE(ret == true);
321+
}
322+
298323
TEST_CASE("Word expression test", "[general]") {
299324
peg::parser parser(R"(
300325
ROOT <- 'hello' ','? 'world'

0 commit comments

Comments
 (0)