Skip to content

Commit 3482a08

Browse files
committed
1 parent 9ee03a9 commit 3482a08

File tree

2 files changed

+73
-14
lines changed

2 files changed

+73
-14
lines changed

peglib.h

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,23 @@ inline std::pair<size_t, size_t> line_info(const char* start, const char* cur) {
432432
return std::make_pair(no, col);
433433
}
434434

435+
/*
436+
* String tag
437+
*/
438+
#ifndef PEGLIB_NO_CONSTEXPR_SUPPORT
439+
inline constexpr unsigned int str2tag(const char* str, int h = 0) {
440+
return !str[h] ? 5381 : (str2tag(str, h + 1) * 33) ^ static_cast<unsigned char>(str[h]);
441+
}
442+
443+
namespace udl {
444+
445+
inline constexpr unsigned int operator "" _(const char* s, size_t) {
446+
return str2tag(s);
447+
}
448+
449+
}
450+
#endif
451+
435452
/*
436453
* Semantic values
437454
*/
@@ -452,6 +469,10 @@ struct SemanticValues : protected std::vector<any>
452469
// Definition name
453470
const std::string& name() const { return name_; }
454471

472+
#ifndef PEGLIB_NO_CONSTEXPR_SUPPORT
473+
std::vector<unsigned int> tags;
474+
#endif
475+
455476
// Line number and column at which the matched string is
456477
std::pair<size_t, size_t> line_info() const {
457478
return peg::line_info(ss, s_);
@@ -860,6 +881,7 @@ class Context
860881
auto& sv = *value_stack[value_stack_size++];
861882
if (!sv.empty()) {
862883
sv.clear();
884+
sv.tags.clear();
863885
}
864886
sv.reset();
865887
sv.path = path;
@@ -961,6 +983,7 @@ class Sequence : public Ope
961983
i += len;
962984
}
963985
sv.insert(sv.end(), chldsv.begin(), chldsv.end());
986+
sv.tags.insert(sv.tags.end(), chldsv.tags.begin(), chldsv.tags.end());
964987
sv.s_ = chldsv.c_str();
965988
sv.n_ = chldsv.length();
966989
sv.tokens.insert(sv.tokens.end(), chldsv.tokens.begin(), chldsv.tokens.end());
@@ -1010,6 +1033,7 @@ class PrioritizedChoice : public Ope
10101033
auto len = rule.parse(s, n, chldsv, c, dt);
10111034
if (success(len)) {
10121035
sv.insert(sv.end(), chldsv.begin(), chldsv.end());
1036+
sv.tags.insert(sv.tags.end(), chldsv.tags.begin(), chldsv.tags.end());
10131037
sv.s_ = chldsv.c_str();
10141038
sv.n_ = chldsv.length();
10151039
sv.choice_count_ = opes_.size();
@@ -1056,6 +1080,7 @@ class ZeroOrMore : public Ope
10561080
} else {
10571081
if (sv.size() != save_sv_size) {
10581082
sv.erase(sv.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
1083+
sv.tags.erase(sv.tags.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
10591084
}
10601085
if (sv.tokens.size() != save_tok_size) {
10611086
sv.tokens.erase(sv.tokens.begin() + static_cast<std::ptrdiff_t>(save_tok_size));
@@ -1114,6 +1139,7 @@ class OneOrMore : public Ope
11141139
} else {
11151140
if (sv.size() != save_sv_size) {
11161141
sv.erase(sv.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
1142+
sv.tags.erase(sv.tags.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
11171143
}
11181144
if (sv.tokens.size() != save_tok_size) {
11191145
sv.tokens.erase(sv.tokens.begin() + static_cast<std::ptrdiff_t>(save_tok_size));
@@ -1155,6 +1181,7 @@ class Option : public Ope
11551181
} else {
11561182
if (sv.size() != save_sv_size) {
11571183
sv.erase(sv.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
1184+
sv.tags.erase(sv.tags.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
11581185
}
11591186
if (sv.tokens.size() != save_tok_size) {
11601187
sv.tokens.erase(sv.tokens.begin() + static_cast<std::ptrdiff_t>(save_tok_size));
@@ -2278,6 +2305,7 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
22782305
if (success(len)) {
22792306
if (!outer_->ignoreSemanticValue) {
22802307
sv.emplace_back(val);
2308+
sv.tags.emplace_back(str2tag(outer_->name.c_str()));
22812309
}
22822310
} else {
22832311
if (outer_->error_message) {
@@ -2957,20 +2985,6 @@ class ParserGenerator
29572985
* AST
29582986
*---------------------------------------------------------------------------*/
29592987

2960-
const int AstDefaultTag = -1;
2961-
2962-
#ifndef PEGLIB_NO_CONSTEXPR_SUPPORT
2963-
inline constexpr unsigned int str2tag(const char* str, int h = 0) {
2964-
return !str[h] ? 5381 : (str2tag(str, h + 1) * 33) ^ static_cast<unsigned char>(str[h]);
2965-
}
2966-
2967-
namespace udl {
2968-
inline constexpr unsigned int operator "" _(const char* s, size_t) {
2969-
return str2tag(s);
2970-
}
2971-
}
2972-
#endif
2973-
29742988
template <typename Annotation>
29752989
struct AstBase : public Annotation
29762990
{

test/test.cc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,51 @@ TEST_CASE("Ordered choice count 2", "[general]")
842842
parser.parse("b");
843843
}
844844

845+
TEST_CASE("Semantic value tag", "[general]")
846+
{
847+
parser parser(R"(
848+
S <- A? B* C?
849+
A <- 'a'
850+
B <- 'b'
851+
C <- 'c'
852+
)");
853+
854+
{
855+
using namespace udl;
856+
parser["S"] = [](const SemanticValues& sv) {
857+
REQUIRE(sv.size() == 1);
858+
REQUIRE(sv.tags.size() == 1);
859+
REQUIRE(sv.tags[0] == "C"_);
860+
};
861+
auto ret = parser.parse("c");
862+
REQUIRE(ret == true);
863+
}
864+
865+
{
866+
using namespace udl;
867+
parser["S"] = [](const SemanticValues& sv) {
868+
REQUIRE(sv.size() == 2);
869+
REQUIRE(sv.tags.size() == 2);
870+
REQUIRE(sv.tags[0] == "B"_);
871+
REQUIRE(sv.tags[1] == "B"_);
872+
};
873+
auto ret = parser.parse("bb");
874+
REQUIRE(ret == true);
875+
}
876+
877+
{
878+
using namespace udl;
879+
parser["S"] = [](const SemanticValues& sv) {
880+
REQUIRE(sv.size() == 2);
881+
REQUIRE(sv.tags.size() == 2);
882+
REQUIRE(sv.tags[0] == "A"_);
883+
REQUIRE(sv.tags[1] == "C"_);
884+
};
885+
auto ret = parser.parse("ac");
886+
REQUIRE(ret == true);
887+
}
888+
}
889+
845890
TEST_CASE("Packrat parser test with %whitespace%", "[packrat]")
846891
{
847892
peg::parser parser(R"(

0 commit comments

Comments
 (0)