diff --git a/peglib.h b/peglib.h index ccdc28b..c663dbd 100644 --- a/peglib.h +++ b/peglib.h @@ -3904,13 +3904,17 @@ struct AstOptimizer { std::shared_ptr parent = nullptr) { auto found = std::find(rules_.begin(), rules_.end(), original->name) != rules_.end(); - bool opt = mode_ ? !found : found; + auto opt = mode_ ? !found : found; if (opt && original->nodes.size() == 1) { auto child = optimize(original->nodes[0], parent); - return std::make_shared(*child, original->name.data(), - original->choice_count, original->position, - original->length, original->choice); + auto ast = std::make_shared(*child, original->name.data(), + original->choice_count, original->position, + original->length, original->choice); + for (auto node : ast->nodes) { + node->parent = ast; + } + return ast; } auto ast = std::make_shared(*original); diff --git a/test/test1.cc b/test/test1.cc index dcee09f..4247dce 100644 --- a/test/test1.cc +++ b/test/test1.cc @@ -967,3 +967,18 @@ TEST(GeneralTest, token_to_number_float_test) { EXPECT_TRUE(ast->nodes.empty()); } +TEST(GeneralTest, ParentReferencesShouldNotBeExpired) { + auto parser = peg::parser(R"( + ROOT <- OPTIMIZES_AWAY + OPTIMIZES_AWAY <- ITEM+ + ITEM <- 'a' + )"); + parser.enable_ast(); + + std::shared_ptr ast; + parser.parse("aaa", ast); + ast = parser.optimize_ast(ast); + + EXPECT_FALSE(ast->nodes[0]->parent.expired()); +} +