mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +00:00
Fixed backtrack problem.
This commit is contained in:
parent
b2a4ad99a0
commit
6b690dd3cb
@ -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>
|
19
peglib.h
19
peglib.h
@ -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;
|
||||||
|
15
test/test.cc
15
test/test.cc
@ -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(
|
||||||
|
Loading…
Reference in New Issue
Block a user