yhirose / cpp-peglib

A single file C++ header-only PEG (Parsing Expression Grammars) library
MIT License
916 stars 113 forks source link

Parents lost during optimization #187

Closed zestier closed 2 years ago

zestier commented 2 years ago

https://github.com/yhirose/cpp-peglib/blob/4d67d96d7ace0830549908a6fae9064d74683f5a/peglib.h#L3911-L3913

The tree produced after optimizing will produce invalid parent references for child nodes of nodes that were optimized away. The cause is that when the referenced lines duplicate the node it effectively orphans child, but the children of the newly produced node are still referencing the old child as their parents.

#include "peglib.h"
#include <catch2/catch.hpp>

TEST_CASE("Parent references should not be expired") {
    auto parser = peg::parser(R"(
        ROOT            <- OPTIMIZES_AWAY
        OPTIMIZES_AWAY  <- ITEM+
        ITEM            <- 'a'
    )");
    parser.enable_ast<peg::Ast>();

    std::shared_ptr<peg::Ast> ast;
    parser.parse("aaa", ast);
    ast = parser.optimize_ast(ast);

    REQUIRE(!ast->nodes[0]->parent.expired());
}

is the test I used to isolate the issue and

      child = std::make_shared<T>(*child, original->name.data(),
                                 original->choice_count, original->position,
                                 original->length, original->choice);
      for (auto node : child->nodes)
          node->parent = child;
      return child;

has been working fine as a fix.

yhirose commented 2 years ago

@zestier, thanks for the bug report! I have just fixed it according to your suggestion.