2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-19 04:22:13 +00:00

Don't reuse the attribute-generating path in rule_parser's out-param overload

of call.  Doing so was wiping out previous partial results, in cases like foo
>> bar, where foo produces a T, and bar is a rule that produces vector<T>.

Fixes #248.
This commit is contained in:
Zach Laine
2025-07-27 17:50:38 -05:00
parent 84ee288b02
commit c674e94c3d
2 changed files with 80 additions and 3 deletions

View File

@@ -5411,9 +5411,28 @@ namespace boost { namespace parser {
if constexpr (CanUseCallbacks && Context::use_callbacks) {
call(first, last, context, skip, flags, success);
} else {
auto attr = call(first, last, context, skip, flags, success);
if (success)
detail::assign(retval, std::move(attr));
locals_type locals = detail::make_locals<locals_type>(context);
auto params = detail::resolve_rule_params(context, params_);
tag_type * const tag_ptr = nullptr;
auto const rule_context = detail::make_rule_context(
context, tag_ptr, retval, locals, params);
[[maybe_unused]] auto _ = detail::scoped_trace(
*this, first, last, rule_context, flags, retval);
bool dont_assign = false;
parse_rule(
tag_ptr,
first,
last,
rule_context,
skip,
flags,
success,
dont_assign,
retval);
if (!success || dont_assign)
retval = Attribute_();
}
}

View File

@@ -287,6 +287,63 @@ void github_issue_223()
}
}
namespace github_issue_248_ {
namespace bp = boost::parser;
static constexpr bp::rule<struct symbol, int> symbol = "//";
static constexpr bp::rule<struct vector, std::vector<int>> list =
"<int>(,<int>)*";
static constexpr bp::rule<struct working, std::vector<int>> working =
"working";
static constexpr bp::rule<struct failing, std::vector<int>> failing =
"failing";
static auto const symbol_def = bp::symbols<int>{{"//", 0}};
static constexpr auto list_def = bp::int_ % ',';
static constexpr auto working_def = -symbol >> (bp::int_ % ',');
static constexpr auto failing_def = -symbol >> list;
BOOST_PARSER_DEFINE_RULES(symbol, list, working, failing);
}
void github_issue_248()
{
namespace bp = boost::parser;
using namespace github_issue_248_;
{
auto const result = bp::parse("//1,2,3", working, bp::ws);
auto const expected = std::vector<int>{0, 1, 2, 3};
BOOST_TEST(result.has_value());
bool const equal = std::equal(
result->begin(), result->end(), expected.begin(), expected.end());
BOOST_TEST(equal);
if (!equal) {
std::cout << "contents of *result:\n";
for (auto x : *result) {
std::cout << x << '\n';
}
std::cout << '\n';
}
}
{
auto const result = bp::parse("//1,2,3", failing, bp::ws);
auto const expected = std::vector<int>{0, 1, 2, 3};
BOOST_TEST(result.has_value());
bool const equal = std::equal(
result->begin(), result->end(), expected.begin(), expected.end());
BOOST_TEST(equal);
if (!equal) {
std::cout << "contents of *result:\n";
for (auto x : *result) {
std::cout << x << '\n';
}
std::cout << '\n';
}
}
}
int main()
{
@@ -298,5 +355,6 @@ int main()
github_issue_125();
github_issue_209();
github_issue_223();
github_issue_248();
return boost::report_errors();
}