Fixed backtrack problem.

This commit is contained in:
yhirose 2015-08-05 22:52:08 -04:00
parent b2a4ad99a0
commit 6b690dd3cb
3 changed files with 34 additions and 6 deletions

View File

@ -58,7 +58,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -75,7 +75,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -88,4 +88,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
</Project> </Project>

View File

@ -221,6 +221,16 @@ struct SemanticValues : protected std::vector<SemanticValue>
return this->transform(beg, end, [](const SemanticValue& v) { return v.get<T>(); }); return this->transform(beg, end, [](const SemanticValue& v) { return v.get<T>(); });
} }
void rewind(const char* s) {
auto it = rbegin();
while (it != rend() && it->s >= s) {
++it;
}
if (it != rbegin()) {
erase(it.base());
}
}
private: private:
template <typename F> template <typename F>
auto transform(F f) const -> vector<typename std::remove_const<decltype(f(SemanticValue()))>::type> { auto transform(F f) const -> vector<typename std::remove_const<decltype(f(SemanticValue()))>::type> {
@ -410,13 +420,14 @@ struct Context
{ {
const char* path; const char* path;
const char* s; const char* s;
size_t l; const size_t l;
const char* error_pos; const char* error_pos;
const char* message_pos; const char* message_pos;
std::string message; // TODO: should be `int`. std::string message; // TODO: should be `int`.
size_t def_count; const size_t def_count;
const bool enablePackratParsing;
std::vector<bool> cache_register; std::vector<bool> cache_register;
std::vector<bool> cache_success; std::vector<bool> cache_success;
@ -432,6 +443,7 @@ struct Context
, error_pos(nullptr) , error_pos(nullptr)
, message_pos(nullptr) , message_pos(nullptr)
, def_count(def_count) , def_count(def_count)
, enablePackratParsing(enablePackratParsing)
, cache_register(enablePackratParsing ? def_count * (l + 1) : 0) , cache_register(enablePackratParsing ? def_count * (l + 1) : 0)
, cache_success(enablePackratParsing ? def_count * (l + 1) : 0) , cache_success(enablePackratParsing ? def_count * (l + 1) : 0)
, stack_size(0) , stack_size(0)
@ -440,7 +452,7 @@ struct Context
template <typename T> template <typename T>
void packrat(const char* s, size_t def_id, size_t& len, any& val, T fn) { void packrat(const char* s, size_t def_id, size_t& len, any& val, T fn) {
if (cache_register.empty()) { if (!enablePackratParsing) {
fn(val); fn(val);
return; return;
} }
@ -611,6 +623,7 @@ public:
const auto& rule = *ope_; const auto& rule = *ope_;
auto len = rule.parse(s + i, n - i, sv, c, dt); auto len = rule.parse(s + i, n - i, sv, c, dt);
if (fail(len)) { if (fail(len)) {
sv.rewind(s + i);
break; break;
} }
i += len; i += len;

View File

@ -251,6 +251,21 @@ TEST_CASE("Backtracking test", "[general]")
REQUIRE(count == 1); // Skip second time 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> ast;
bool ret = parser.parse("ba", ast);
REQUIRE(ret == true);
REQUIRE(ast->nodes.size() == 2);
}
TEST_CASE("Octal/Hex value test", "[general]") TEST_CASE("Octal/Hex value test", "[general]")
{ {
peglib::peg parser( peglib::peg parser(