From e575cbd9f35259948a0cb9d780aa41da1af52142 Mon Sep 17 00:00:00 2001 From: Zach Laine Date: Sat, 14 Dec 2024 14:28:20 -0600 Subject: [PATCH] WIP --- include/boost/parser/parser.hpp | 125 +++++++++++++++++++++------- include/boost/parser/parser_fwd.hpp | 2 + 2 files changed, 96 insertions(+), 31 deletions(-) diff --git a/include/boost/parser/parser.hpp b/include/boost/parser/parser.hpp index 0c6f62b9..2272f04b 100644 --- a/include/boost/parser/parser.hpp +++ b/include/boost/parser/parser.hpp @@ -3004,13 +3004,15 @@ namespace boost { namespace parser { return action_t{std::move(action)}; } - template - using final_attribute_type_impl = - std::conditional_t; + template + using final_attribute_type_impl = std:: + conditional_t, nope, Attribute>; template - using final_attribute_type = - final_attribute_type_impl; + using final_attribute_type = final_attribute_type_impl< + Attribute, + ParserMods::omit_attr, + typename ParserMods::action_type>; template using action_direct_call_expr = @@ -3080,32 +3082,23 @@ namespace boost { namespace parser { std::is_same_v && !std::is_same_v; - template< - typename Parser, - typename Action, - typename Iter, - typename Sentinel, - typename Context, - typename SkipParser> - void use_action( - Parser const & parser, - Action const & action, - Iter & first, - Sentinel last, - Context const & context, - SkipParser const & skip, - detail::flags flags, - bool & success) - { - auto const initial_first = first; - auto attr = parser.call( - first, - last, - context, - skip, - detail::enable_attrs(flags), - success); + template + constexpr bool has_action_v = + !is_nope_v; + template< + typename Action, + typename Attribute, + typename Iter, + typename Context> + void use_action( + Action const & action, + Attribute attr, + Iter initial_first, + Iter first, + Context const & context, + bool success) + { if (!success) return; @@ -3361,6 +3354,8 @@ namespace boost { namespace parser { : flags, retval); + Iter const initial_first = first; + if constexpr (detail::is_optional_v) { detail::optional_type attr; detail::apply_parser( @@ -3439,6 +3434,16 @@ namespace boost { namespace parser { if constexpr (detail::gen_attrs()) detail::move_back(retval, std::move(attr)); } + + if constexpr (detail::has_action_v) { + detail::use_action( + mods_.action, + std::move(retval), + initial_first, + first, + context, + success); + } } } @@ -3474,6 +3479,7 @@ namespace boost { namespace parser { }; #endif + // TODO: Can these three conveniently be removed? template struct zero_plus_parser : repeat_parser @@ -3613,6 +3619,8 @@ namespace boost { namespace parser { //] //[ opt_parser_no_gen_attr_path + Iter const initial_first = first; + if (!detail::gen_attrs()) { parser_.call(first, last, context, skip, flags, success); success = true; @@ -3624,9 +3632,25 @@ namespace boost { namespace parser { parser_.call(first, last, context, skip, flags, success, retval); success = true; //] + + // TODO: Update the "writing your own parsers" section to reflect + // this and other changes, like with_parser_mods(). + + //[ opt_parser_apply_action + if constexpr (detail::has_action_v) { + detail::use_action( + mods_.action, + std::move(retval), + initial_first, + first, + context, + success); + } + //] } //] + //[ opt_parser_with_parser_mods template constexpr auto with_parser_mods(F f) const { @@ -3637,6 +3661,7 @@ namespace boost { namespace parser { return parser::opt_parser(parser_, f(mods_)); } } + //] //[ opt_parser_end Parser parser_; @@ -3787,6 +3812,8 @@ namespace boost { namespace parser { [[maybe_unused]] auto _ = detail::scoped_trace( *this, first, last, context, flags, retval); + Iter const initial_first = first; + use_parser_t const use_parser{ first, last, context, skip, flags, success}; @@ -3812,6 +3839,16 @@ namespace boost { namespace parser { if (!done) success = false; + + if constexpr (detail::has_action_v) { + detail::use_action( + mods_.action, + std::move(retval), + initial_first, + first, + context, + success); + } } #ifndef BOOST_PARSER_DOXYGEN @@ -3955,6 +3992,8 @@ namespace boost { namespace parser { [[maybe_unused]] auto _ = detail::scoped_trace( *this, first_, last, context, flags, retval); + Iter const initial_first = first; + Iter first = first_; use_parser_t const use_parser{ first, last, context, skip, flags, success}; @@ -4041,6 +4080,16 @@ namespace boost { namespace parser { if (success) first_ = first; + + if constexpr (detail::has_action_v) { + detail::use_action( + mods_.action, + std::move(retval), + initial_first, + first, + context, + success); + } } template< @@ -4953,8 +5002,22 @@ namespace boost { namespace parser { [[maybe_unused]] auto _ = detail::scoped_trace( *this, first, last, context, flags, retval); + auto const initial_first = first; + auto attr = parser.call( + first, + last, + context, + skip, + detail::enable_attrs(flags), + success); + detail::use_action( - parser_, action_, first, last, context, skip, flags, success); + action_, + std::move(attr), + initial_first, + first, + context, + success); } template diff --git a/include/boost/parser/parser_fwd.hpp b/include/boost/parser/parser_fwd.hpp index 920293fa..5a92b58a 100644 --- a/include/boost/parser/parser_fwd.hpp +++ b/include/boost/parser/parser_fwd.hpp @@ -152,6 +152,8 @@ namespace boost { namespace parser { template struct parser_modifiers { + using action_type = Action; + static constexpr bool omit_attr = OmitAttr; [[no_unique_address]] Action action;