Restored before/after handlers.

pull/3/head
yhirose 9 years ago
parent 15893308db
commit 5b9daaf090
  1. 42
      peglib.h
  2. 42
      test/test.cc

@ -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");

@ -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…
Cancel
Save