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