mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +00:00
Restored before/after handlers.
This commit is contained in:
parent
15893308db
commit
5b9daaf090
42
peglib.h
42
peglib.h
@ -1182,13 +1182,15 @@ public:
|
||||
holder_->accept(v);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
size_t id;
|
||||
Action action;
|
||||
std::function<std::string ()> error_message;
|
||||
bool ignoreSemanticValue;
|
||||
bool enablePackratParsing;
|
||||
bool is_token;
|
||||
std::string name;
|
||||
size_t id;
|
||||
Action action;
|
||||
std::function<void (any& dt)> before;
|
||||
std::function<void (any& dt)> after;
|
||||
std::function<std::string ()> error_message;
|
||||
bool ignoreSemanticValue;
|
||||
bool enablePackratParsing;
|
||||
bool is_token;
|
||||
|
||||
private:
|
||||
friend class DefinitionReference;
|
||||
@ -1225,6 +1227,10 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
|
||||
c.packrat(s, outer_->id, len, val, [&](any& val) {
|
||||
auto& chldsv = c.push();
|
||||
|
||||
if (outer_->before) {
|
||||
outer_->before(dt);
|
||||
}
|
||||
|
||||
const auto& rule = *ope_;
|
||||
len = rule.parse(s, n, chldsv, c, dt);
|
||||
|
||||
@ -1251,6 +1257,10 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
|
||||
}
|
||||
}
|
||||
|
||||
if (outer_->after) {
|
||||
outer_->after(dt);
|
||||
}
|
||||
|
||||
c.pop();
|
||||
});
|
||||
|
||||
@ -1793,8 +1803,13 @@ private:
|
||||
|
||||
if (!r.ret) {
|
||||
if (log) {
|
||||
auto line = line_info(s, r.error_pos);
|
||||
log(line.first, line.second, r.message.empty() ? "syntax error" : r.message);
|
||||
if (r.message_pos) {
|
||||
auto line = line_info(s, r.message_pos);
|
||||
log(line.first, line.second, r.message);
|
||||
} else {
|
||||
auto line = line_info(s, r.error_pos);
|
||||
log(line.first, line.second, "syntax error");
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -2279,8 +2294,13 @@ private:
|
||||
void output_log(const char* s, size_t n, Log log, const Definition::Result& r) const {
|
||||
if (log) {
|
||||
if (!r.ret) {
|
||||
auto line = line_info(s, r.error_pos);
|
||||
log(line.first, line.second, r.message.empty() ? "syntax error" : r.message);
|
||||
if (r.message_pos) {
|
||||
auto line = line_info(s, r.message_pos);
|
||||
log(line.first, line.second, r.message);
|
||||
} else {
|
||||
auto line = line_info(s, r.error_pos);
|
||||
log(line.first, line.second, "syntax error");
|
||||
}
|
||||
} else if (r.len != n) {
|
||||
auto line = line_info(s, s + r.len);
|
||||
log(line.first, line.second, "syntax error");
|
||||
|
42
test/test.cc
42
test/test.cc
@ -213,6 +213,48 @@ TEST_CASE("Lambda action test", "[general]")
|
||||
REQUIRE(ss == "hello");
|
||||
}
|
||||
|
||||
TEST_CASE("before/after handlers test", "[general]")
|
||||
{
|
||||
parser parser(R"(
|
||||
START <- LTOKEN '=' RTOKEN
|
||||
LTOKEN <- TOKEN
|
||||
RTOKEN <- TOKEN
|
||||
TOKEN <- [A-Za-z]+
|
||||
)");
|
||||
|
||||
parser["LTOKEN"].before = [&](any& dt) {
|
||||
auto& require_upper_case = *dt.get<bool*>();
|
||||
require_upper_case = false;
|
||||
};
|
||||
parser["LTOKEN"].after = [&](any& dt) {
|
||||
auto& require_upper_case = *dt.get<bool*>();
|
||||
require_upper_case = true;
|
||||
};
|
||||
|
||||
parser["TOKEN"] = [&](const SemanticValues& sv, any& dt) {
|
||||
auto& require_upper_case = *dt.get<bool*>();
|
||||
if (require_upper_case) {
|
||||
const auto& s = sv.str();
|
||||
if (!std::all_of(s.begin(), s.end(), ::isupper)) {
|
||||
throw parse_error("should be upper case string...");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool require_upper_case = false;
|
||||
any dt = &require_upper_case;
|
||||
REQUIRE(parser.parse("hello=world", dt) == false);
|
||||
REQUIRE(parser.parse("HELLO=world", dt) == false);
|
||||
REQUIRE(parser.parse("hello=WORLD", dt) == true);
|
||||
REQUIRE(parser.parse("HELLO=WORLD", dt) == true);
|
||||
|
||||
parser.log = [&](size_t ln, size_t col, const string& msg) {
|
||||
REQUIRE(ln == 1);
|
||||
REQUIRE(col == 7);
|
||||
};
|
||||
parser.parse("hello=world", dt);
|
||||
}
|
||||
|
||||
TEST_CASE("Skip token test", "[general]")
|
||||
{
|
||||
peg::parser parser(
|
||||
|
Loading…
Reference in New Issue
Block a user