From dc6144eeb45a5bf809df862887ae729bd330aee2 Mon Sep 17 00:00:00 2001 From: Zach Laine Date: Fri, 31 Oct 2025 12:37:40 -0500 Subject: [PATCH] Correct tuple/struct confusion in the logic of the if constexpr chain in perm_parser. Test case by Andreas Buhr. Fixes #268. --- include/boost/parser/parser.hpp | 24 +++++++++------- test/github_issues.cpp | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/include/boost/parser/parser.hpp b/include/boost/parser/parser.hpp index 5c58df3c..8cdea90c 100644 --- a/include/boost/parser/parser.hpp +++ b/include/boost/parser/parser.hpp @@ -3680,9 +3680,7 @@ namespace boost { namespace parser { call(first, last, context, skip, flags, success, attr); if (success) detail::assign(retval, std::move(attr)); - } else if constexpr ( - detail::is_tuple{} || - detail::is_struct_compatible_v) { + } else if constexpr (detail::is_tuple{}) { call_impl( first, last, @@ -3695,9 +3693,9 @@ namespace boost { namespace parser { if (!success) detail::assign(retval, Attribute()); - } else if constexpr (detail::is_constructible_from_tuple_v< - Attribute, - result_t>) { + } else if constexpr ( + detail::is_struct_compatible_v || + detail::is_constructible_from_tuple_v) { result_t temp_retval{}; call_impl( first, @@ -3710,10 +3708,16 @@ namespace boost { namespace parser { indices); if (success && detail::gen_attrs(flags)) { - detail::assign( - retval, - detail::make_from_tuple( - std::move(temp_retval))); + if constexpr (detail::is_struct_compatible_v< + Attribute, + result_t>) { + detail::assign(retval, temp_retval); + } else { + detail::assign( + retval, + detail::make_from_tuple( + std::move(temp_retval))); + } } } else { #if 0 // TODO Seems incompatible with this parser. diff --git a/test/github_issues.cpp b/test/github_issues.cpp index f64beccb..be2497ca 100644 --- a/test/github_issues.cpp +++ b/test/github_issues.cpp @@ -344,6 +344,55 @@ void github_issue_248() } } +namespace github_issue_268_ { + namespace bp = boost::parser; + constexpr bp::rule name = "name"; + auto name_def = bp::string_view[bp::lexeme[+(bp::lower | bp::upper | bp::digit | bp::char_("_"))]]; + BOOST_PARSER_DEFINE_RULES(name) + constexpr bp::rule> qd_vec = "qd_vec"; + auto qd_vec_def = bp::lit("\"") >> bp::double_ % (bp::lit(",") | (bp::lit("\"") >> bp::lit(",") >> bp::lit("\""))) >> bp::lit('\"'); + BOOST_PARSER_DEFINE_RULES(qd_vec) + struct lu_table_template_1 + { + std::vector index_1; + std::string_view variable_1; + }; + constexpr boost::parser::rule lu_table_template_1_rule = "lu_table_template_1"; + auto lu_table_template_1_rule_def = (bp::lit("index_1") >> '(' >> qd_vec >> ')' >> ';') >> (bp::lit("variable_1") >> ':' >> name >> ';'); + BOOST_PARSER_DEFINE_RULES(lu_table_template_1_rule) + + constexpr boost::parser::rule lu_table_template_1_permut_rule = "lu_table_template_1"; + auto lu_table_template_1_permut_rule_def = (bp::lit("index_1") >> '(' >> qd_vec >> ')' >> ';') || (bp::lit("variable_1") >> ':' >> name >> ';'); + BOOST_PARSER_DEFINE_RULES(lu_table_template_1_permut_rule) +} + +void github_issue_268() +{ + namespace bp = boost::parser; + using namespace github_issue_268_; + std::string inputstring = "index_1 ( \"1\" ) ; variable_1 : bier;"; + + auto const def_result = bp::parse( + inputstring, lu_table_template_1_rule_def, bp::blank, bp::trace::off); + std::cout<< "seq_parser generates this type:\n" << typeid(def_result.value()).name() << std::endl; + BOOST_TEST(def_result); + + auto const permut_def_result = bp::parse( + inputstring, lu_table_template_1_permut_rule_def, bp::blank, bp::trace::off); + std::cout<< "permut_parser generates this type:\n" << typeid(permut_def_result.value()).name() << std::endl; + BOOST_TEST(permut_def_result); + + auto const result = bp::parse( + inputstring, lu_table_template_1_rule, bp::blank, bp::trace::off); + std::cout<< "seq_parser in rule generates this type:\n" << typeid(result.value()).name() << std::endl; + BOOST_TEST(result); + + auto const permut_result = bp::parse( + inputstring, lu_table_template_1_permut_rule, bp::blank, bp::trace::off); + std::cout<< "permut_parser generates this type:\n" << typeid(permut_result.value()).name() << std::endl; + BOOST_TEST(permut_result); +} + void github_issue_279() { namespace bp = boost::parser; @@ -373,6 +422,7 @@ int main() github_issue_209(); github_issue_223(); github_issue_248(); + github_issue_268(); github_issue_279(); return boost::report_errors(); }