From 6b690dd3cb5904a6333c9a682f3021ca0b4f1343 Mon Sep 17 00:00:00 2001 From: yhirose Date: Wed, 5 Aug 2015 22:52:08 -0400 Subject: [PATCH] Fixed backtrack problem. --- lint/cmdline/peglint.vcxproj | 6 +++--- peglib.h | 19 ++++++++++++++++--- test/test.cc | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/lint/cmdline/peglint.vcxproj b/lint/cmdline/peglint.vcxproj index 6d9586a..54ab492 100644 --- a/lint/cmdline/peglint.vcxproj +++ b/lint/cmdline/peglint.vcxproj @@ -58,7 +58,7 @@ Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - .. + ../.. Console @@ -75,7 +75,7 @@ true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - .. + ../.. Console @@ -88,4 +88,4 @@ - + \ No newline at end of file diff --git a/peglib.h b/peglib.h index daa5dfe..110008c 100644 --- a/peglib.h +++ b/peglib.h @@ -221,6 +221,16 @@ struct SemanticValues : protected std::vector return this->transform(beg, end, [](const SemanticValue& v) { return v.get(); }); } + void rewind(const char* s) { + auto it = rbegin(); + while (it != rend() && it->s >= s) { + ++it; + } + if (it != rbegin()) { + erase(it.base()); + } + } + private: template auto transform(F f) const -> vector::type> { @@ -410,13 +420,14 @@ struct Context { const char* path; const char* s; - size_t l; + const size_t l; const char* error_pos; const char* message_pos; std::string message; // TODO: should be `int`. - size_t def_count; + const size_t def_count; + const bool enablePackratParsing; std::vector cache_register; std::vector cache_success; @@ -432,6 +443,7 @@ struct Context , error_pos(nullptr) , message_pos(nullptr) , def_count(def_count) + , enablePackratParsing(enablePackratParsing) , cache_register(enablePackratParsing ? def_count * (l + 1) : 0) , cache_success(enablePackratParsing ? def_count * (l + 1) : 0) , stack_size(0) @@ -440,7 +452,7 @@ struct Context template void packrat(const char* s, size_t def_id, size_t& len, any& val, T fn) { - if (cache_register.empty()) { + if (!enablePackratParsing) { fn(val); return; } @@ -611,6 +623,7 @@ public: const auto& rule = *ope_; auto len = rule.parse(s + i, n - i, sv, c, dt); if (fail(len)) { + sv.rewind(s + i); break; } i += len; diff --git a/test/test.cc b/test/test.cc index 93350e8..751baef 100644 --- a/test/test.cc +++ b/test/test.cc @@ -251,6 +251,21 @@ TEST_CASE("Backtracking test", "[general]") REQUIRE(count == 1); // Skip second time } +TEST_CASE("Backtracking with AST", "[general]") +{ + peg parser(R"( + S <- A? B (A B)* A + A <- 'a' + B <- 'b' + )"); + + parser.enable_ast(); + shared_ptr ast; + bool ret = parser.parse("ba", ast); + REQUIRE(ret == true); + REQUIRE(ast->nodes.size() == 2); +} + TEST_CASE("Octal/Hex value test", "[general]") { peglib::peg parser(