mirror of
https://github.com/boostorg/parser.git
synced 2026-01-19 04:22:13 +00:00
Add special-casing of nope attributes in seq_parser, so that seq_parser does
not assign over valid values in a sequence's attribute after successfully parsing a subsquent nope-attributes parser. Test cases by Andreas Buhr. Fixes #279 Fixes #285
This commit is contained in:
@@ -4533,7 +4533,8 @@ namespace boost { namespace parser {
|
||||
|
||||
if constexpr (
|
||||
(out_container == attr_container &&
|
||||
!was_merged_into_adjacent_container) ||
|
||||
!was_merged_into_adjacent_container &&
|
||||
!detail::is_nope_v<attr_t>) ||
|
||||
is_in_a_group) {
|
||||
parser.call(
|
||||
first, last, context, skip, flags, success, out);
|
||||
@@ -4559,7 +4560,9 @@ namespace boost { namespace parser {
|
||||
}
|
||||
using just_x = attr_t;
|
||||
using just_out = detail::remove_cv_ref_t<decltype(out)>;
|
||||
if constexpr (
|
||||
if constexpr (detail::is_nope_v<attr_t>) {
|
||||
// nothing to do
|
||||
} if constexpr (
|
||||
(!out_container ||
|
||||
!std::is_same_v<just_x, just_out>) &&
|
||||
std::is_assignable_v<just_out &, just_x &&> &&
|
||||
@@ -4732,7 +4735,7 @@ namespace boost { namespace parser {
|
||||
} else {
|
||||
// If you see an error here, it's because you are using an
|
||||
// invocable for a semantic action that returns a non-void
|
||||
// type Ret, but values fo type Ret is not assignable to
|
||||
// type Ret, but values of type Ret is not assignable to
|
||||
// _val(ctx). To fix this, only use this invocable within
|
||||
// a rule whose attribute type is assignable from Ret, or
|
||||
// remove the non-void return statement(s) from your
|
||||
|
||||
@@ -348,22 +348,36 @@ void github_issue_248()
|
||||
namespace github_issue_268_ {
|
||||
namespace bp = boost::parser;
|
||||
constexpr bp::rule<struct name, std::string_view> name = "name";
|
||||
auto name_def = bp::string_view[bp::lexeme[+(bp::lower | bp::upper | bp::digit | bp::char_("_"))]];
|
||||
auto name_def = bp::string_view[bp::lexeme[+(
|
||||
bp::lower | bp::upper | bp::digit | bp::char_("_"))]];
|
||||
BOOST_PARSER_DEFINE_RULES(name)
|
||||
constexpr bp::rule<struct qd_vec, std::vector<double>> qd_vec = "qd_vec";
|
||||
auto qd_vec_def = bp::lit("\"") >> bp::double_ % (bp::lit(",") | (bp::lit("\"") >> bp::lit(",") >> bp::lit("\""))) >> bp::lit('\"');
|
||||
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<double> index_1;
|
||||
std::string_view variable_1;
|
||||
};
|
||||
constexpr boost::parser::rule<struct lu_table_template_1_tag, lu_table_template_1> 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 >> ';');
|
||||
constexpr boost::parser::
|
||||
rule<struct lu_table_template_1_tag, lu_table_template_1>
|
||||
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<struct lu_table_template_1_permut_tag, lu_table_template_1> 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 >> ';');
|
||||
constexpr boost::parser::
|
||||
rule<struct lu_table_template_1_permut_tag, lu_table_template_1>
|
||||
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)
|
||||
}
|
||||
#endif
|
||||
@@ -377,22 +391,32 @@ void github_issue_268()
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
@@ -401,17 +425,80 @@ void github_issue_279()
|
||||
{
|
||||
namespace bp = boost::parser;
|
||||
|
||||
constexpr auto condition_clause = bp::lit(U"while") >
|
||||
bp::lit(U"someexpression") >> bp::attr(true);
|
||||
{
|
||||
constexpr auto condition_clause =
|
||||
bp::lit(U"while") > bp::lit(U"someexpression") >> bp::attr(true);
|
||||
|
||||
constexpr auto do_statement =
|
||||
bp::lexeme[bp::lit(U"do") >> &bp::ws] > -condition_clause > bp::eol;
|
||||
constexpr auto do_statement =
|
||||
bp::lexeme[bp::lit(U"do") >> &bp::ws] > -condition_clause > bp::eol;
|
||||
|
||||
auto const result = bp::parse(
|
||||
U"do\n", do_statement, bp::blank, bp::trace::off);
|
||||
auto const result =
|
||||
bp::parse(U"do\n", do_statement, bp::blank, bp::trace::off);
|
||||
BOOST_TEST(result);
|
||||
std::optional<bool> const & condition = result.value();
|
||||
BOOST_TEST(!condition.has_value());
|
||||
}
|
||||
|
||||
{
|
||||
constexpr auto condition_clause =
|
||||
bp::lit(U"while") > bp::lit(U"someexpression") >> bp::attr(true);
|
||||
|
||||
constexpr auto do_statement_reverse =
|
||||
-condition_clause > bp::lexeme[bp::lit(U"do") >> &bp::ws] > bp::eol;
|
||||
|
||||
auto const result =
|
||||
bp::parse(U"do\n", do_statement_reverse, bp::blank, bp::trace::off);
|
||||
BOOST_TEST(result);
|
||||
std::optional<bool> const & condition = result.value();
|
||||
BOOST_TEST(!condition.has_value());
|
||||
}
|
||||
}
|
||||
|
||||
namespace github_issue_285_ {
|
||||
namespace bp = boost::parser;
|
||||
|
||||
struct Content
|
||||
{
|
||||
~Content()
|
||||
{
|
||||
int setbreakpointhere = 0;
|
||||
(void)setbreakpointhere;
|
||||
}
|
||||
};
|
||||
constexpr bp::rule<struct content_tag, std::shared_ptr<Content>> content =
|
||||
"content";
|
||||
constexpr auto content_action = [](auto & ctx) {
|
||||
std::shared_ptr<Content> & result = _val(ctx);
|
||||
result = std::make_shared<Content>();
|
||||
};
|
||||
constexpr auto content_def =
|
||||
(bp::lit(U"content") >> bp::eol)[content_action];
|
||||
BOOST_PARSER_DEFINE_RULES(content);
|
||||
}
|
||||
|
||||
void github_issue_285()
|
||||
{
|
||||
using namespace github_issue_285_;
|
||||
namespace bp = boost::parser;
|
||||
|
||||
constexpr auto prolog = bp::lit(U"prolog") >> bp::eol;
|
||||
|
||||
constexpr auto epilog =
|
||||
bp::no_case[bp::lexeme[bp::lit(U"epi") >> bp::lit(U"log")]] >> bp::eol;
|
||||
|
||||
constexpr auto full_parser = prolog >> content >> epilog;
|
||||
|
||||
std::string teststring =
|
||||
"prolog\n"
|
||||
"content\n"
|
||||
"epilog\n";
|
||||
|
||||
// "content" produces a shared_ptr with the result.
|
||||
// The "epilog" parser must not delete the result.
|
||||
|
||||
auto const result = bp::parse(teststring, full_parser, bp::blank);
|
||||
BOOST_TEST(result);
|
||||
std::optional<bool> const & condition = result.value();
|
||||
BOOST_TEST(!condition.has_value());
|
||||
BOOST_TEST(result.value().get() != nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -428,5 +515,6 @@ int main()
|
||||
github_issue_248();
|
||||
github_issue_268();
|
||||
github_issue_279();
|
||||
github_issue_285();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user