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>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -75,7 +75,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -88,4 +88,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</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>(); });
}
void rewind(const char* s) {
auto it = rbegin();
while (it != rend() && it->s >= s) {
++it;
}
if (it != rbegin()) {
erase(it.base());
}
}
private:
template <typename F>
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* 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<bool> cache_register;
std::vector<bool> 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 <typename T>
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;

View File

@ -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> 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(