mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 11:55:30 +00:00
Fix #67
This commit is contained in:
parent
9ee03a9211
commit
3482a08465
42
peglib.h
42
peglib.h
@ -432,6 +432,23 @@ inline std::pair<size_t, size_t> line_info(const char* start, const char* cur) {
|
||||
return std::make_pair(no, col);
|
||||
}
|
||||
|
||||
/*
|
||||
* String tag
|
||||
*/
|
||||
#ifndef PEGLIB_NO_CONSTEXPR_SUPPORT
|
||||
inline constexpr unsigned int str2tag(const char* str, int h = 0) {
|
||||
return !str[h] ? 5381 : (str2tag(str, h + 1) * 33) ^ static_cast<unsigned char>(str[h]);
|
||||
}
|
||||
|
||||
namespace udl {
|
||||
|
||||
inline constexpr unsigned int operator "" _(const char* s, size_t) {
|
||||
return str2tag(s);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Semantic values
|
||||
*/
|
||||
@ -452,6 +469,10 @@ struct SemanticValues : protected std::vector<any>
|
||||
// Definition name
|
||||
const std::string& name() const { return name_; }
|
||||
|
||||
#ifndef PEGLIB_NO_CONSTEXPR_SUPPORT
|
||||
std::vector<unsigned int> tags;
|
||||
#endif
|
||||
|
||||
// Line number and column at which the matched string is
|
||||
std::pair<size_t, size_t> line_info() const {
|
||||
return peg::line_info(ss, s_);
|
||||
@ -860,6 +881,7 @@ public:
|
||||
auto& sv = *value_stack[value_stack_size++];
|
||||
if (!sv.empty()) {
|
||||
sv.clear();
|
||||
sv.tags.clear();
|
||||
}
|
||||
sv.reset();
|
||||
sv.path = path;
|
||||
@ -961,6 +983,7 @@ public:
|
||||
i += len;
|
||||
}
|
||||
sv.insert(sv.end(), chldsv.begin(), chldsv.end());
|
||||
sv.tags.insert(sv.tags.end(), chldsv.tags.begin(), chldsv.tags.end());
|
||||
sv.s_ = chldsv.c_str();
|
||||
sv.n_ = chldsv.length();
|
||||
sv.tokens.insert(sv.tokens.end(), chldsv.tokens.begin(), chldsv.tokens.end());
|
||||
@ -1010,6 +1033,7 @@ public:
|
||||
auto len = rule.parse(s, n, chldsv, c, dt);
|
||||
if (success(len)) {
|
||||
sv.insert(sv.end(), chldsv.begin(), chldsv.end());
|
||||
sv.tags.insert(sv.tags.end(), chldsv.tags.begin(), chldsv.tags.end());
|
||||
sv.s_ = chldsv.c_str();
|
||||
sv.n_ = chldsv.length();
|
||||
sv.choice_count_ = opes_.size();
|
||||
@ -1056,6 +1080,7 @@ public:
|
||||
} else {
|
||||
if (sv.size() != save_sv_size) {
|
||||
sv.erase(sv.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
|
||||
sv.tags.erase(sv.tags.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
|
||||
}
|
||||
if (sv.tokens.size() != save_tok_size) {
|
||||
sv.tokens.erase(sv.tokens.begin() + static_cast<std::ptrdiff_t>(save_tok_size));
|
||||
@ -1114,6 +1139,7 @@ public:
|
||||
} else {
|
||||
if (sv.size() != save_sv_size) {
|
||||
sv.erase(sv.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
|
||||
sv.tags.erase(sv.tags.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
|
||||
}
|
||||
if (sv.tokens.size() != save_tok_size) {
|
||||
sv.tokens.erase(sv.tokens.begin() + static_cast<std::ptrdiff_t>(save_tok_size));
|
||||
@ -1155,6 +1181,7 @@ public:
|
||||
} else {
|
||||
if (sv.size() != save_sv_size) {
|
||||
sv.erase(sv.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
|
||||
sv.tags.erase(sv.tags.begin() + static_cast<std::ptrdiff_t>(save_sv_size));
|
||||
}
|
||||
if (sv.tokens.size() != save_tok_size) {
|
||||
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
|
||||
if (success(len)) {
|
||||
if (!outer_->ignoreSemanticValue) {
|
||||
sv.emplace_back(val);
|
||||
sv.tags.emplace_back(str2tag(outer_->name.c_str()));
|
||||
}
|
||||
} else {
|
||||
if (outer_->error_message) {
|
||||
@ -2957,20 +2985,6 @@ private:
|
||||
* AST
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
const int AstDefaultTag = -1;
|
||||
|
||||
#ifndef PEGLIB_NO_CONSTEXPR_SUPPORT
|
||||
inline constexpr unsigned int str2tag(const char* str, int h = 0) {
|
||||
return !str[h] ? 5381 : (str2tag(str, h + 1) * 33) ^ static_cast<unsigned char>(str[h]);
|
||||
}
|
||||
|
||||
namespace udl {
|
||||
inline constexpr unsigned int operator "" _(const char* s, size_t) {
|
||||
return str2tag(s);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Annotation>
|
||||
struct AstBase : public Annotation
|
||||
{
|
||||
|
45
test/test.cc
45
test/test.cc
@ -842,6 +842,51 @@ TEST_CASE("Ordered choice count 2", "[general]")
|
||||
parser.parse("b");
|
||||
}
|
||||
|
||||
TEST_CASE("Semantic value tag", "[general]")
|
||||
{
|
||||
parser parser(R"(
|
||||
S <- A? B* C?
|
||||
A <- 'a'
|
||||
B <- 'b'
|
||||
C <- 'c'
|
||||
)");
|
||||
|
||||
{
|
||||
using namespace udl;
|
||||
parser["S"] = [](const SemanticValues& sv) {
|
||||
REQUIRE(sv.size() == 1);
|
||||
REQUIRE(sv.tags.size() == 1);
|
||||
REQUIRE(sv.tags[0] == "C"_);
|
||||
};
|
||||
auto ret = parser.parse("c");
|
||||
REQUIRE(ret == true);
|
||||
}
|
||||
|
||||
{
|
||||
using namespace udl;
|
||||
parser["S"] = [](const SemanticValues& sv) {
|
||||
REQUIRE(sv.size() == 2);
|
||||
REQUIRE(sv.tags.size() == 2);
|
||||
REQUIRE(sv.tags[0] == "B"_);
|
||||
REQUIRE(sv.tags[1] == "B"_);
|
||||
};
|
||||
auto ret = parser.parse("bb");
|
||||
REQUIRE(ret == true);
|
||||
}
|
||||
|
||||
{
|
||||
using namespace udl;
|
||||
parser["S"] = [](const SemanticValues& sv) {
|
||||
REQUIRE(sv.size() == 2);
|
||||
REQUIRE(sv.tags.size() == 2);
|
||||
REQUIRE(sv.tags[0] == "A"_);
|
||||
REQUIRE(sv.tags[1] == "C"_);
|
||||
};
|
||||
auto ret = parser.parse("ac");
|
||||
REQUIRE(ret == true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Packrat parser test with %whitespace%", "[packrat]")
|
||||
{
|
||||
peg::parser parser(R"(
|
||||
|
Loading…
Reference in New Issue
Block a user