diff --git a/include/boost/parser/parser.hpp b/include/boost/parser/parser.hpp index ef0d469e..caf72e85 100644 --- a/include/boost/parser/parser.hpp +++ b/include/boost/parser/parser.hpp @@ -5549,8 +5549,9 @@ namespace boost { namespace parser { locals_type locals = detail::make_locals(context); auto params = detail::resolve_rule_params(context, params_); tag_type * const tag_ptr = nullptr; + attr_type attr{}; auto const rule_context = detail::make_rule_context( - context, tag_ptr, retval, locals, params); + context, tag_ptr, attr, locals, params); [[maybe_unused]] auto _ = detail::scoped_trace( *this, first, last, rule_context, flags, retval); @@ -5565,9 +5566,22 @@ namespace boost { namespace parser { flags, success, dont_assign, - retval); - if (!success || dont_assign) - retval = Attribute_(); + attr); + + if (dont_assign) + return; + + if (!success) + attr = attr_type{}; + + if constexpr (detail::is_nope_v) { + return; + } else if constexpr ( + container && container) { + detail::move_back(retval, attr, detail::gen_attrs(flags)); + } else { + detail::assign(retval, attr); + } } } diff --git a/test/github_issues.cpp b/test/github_issues.cpp index 23ace318..b36d872c 100644 --- a/test/github_issues.cpp +++ b/test/github_issues.cpp @@ -512,6 +512,45 @@ void github_pr_290() BOOST_TEST(*result == "foo"); } +namespace github_issue_294_ { + namespace bp = boost::parser; + struct Foo + {}; + constexpr bp::rule> foo_parser = + "foo_parser"; + constexpr auto foo_parser_action = [](auto & ctx) { + std::shared_ptr & val = _val(ctx); + val = std::shared_ptr(new Foo{}); + }; + constexpr auto foo_parser_def = bp::eps[foo_parser_action]; + struct Bar + { + std::shared_ptr foo; + }; + constexpr bp::rule> bar_parser = + "bar_parser"; + constexpr auto bar_parser_action = [](auto & ctx) { + std::shared_ptr & val = _val(ctx); + val = std::shared_ptr(new Bar{}); + std::optional> & attr = _attr(ctx); + if (attr) { + val->foo = attr.value(); + } + }; + constexpr auto bar_parser_def = + (bp::lit("(") > -foo_parser > bp::lit(")"))[bar_parser_action]; + + BOOST_PARSER_DEFINE_RULES(bar_parser, foo_parser); +} + +void github_issue_294() +{ + namespace bp = boost::parser; + using namespace github_issue_294_; + + bp::parse("()", bar_parser, bp::blank); +} + namespace github_pr_297_ { namespace bp = boost::parser; constexpr auto bar_required_f = [](auto& ctx) -> bool { @@ -558,6 +597,7 @@ void github_pr_297() } } + int main() { github_issue_36(); @@ -573,6 +613,7 @@ int main() github_issue_279(); github_issue_285(); github_pr_290(); + github_issue_294(); github_pr_297(); return boost::report_errors(); }