Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:40:36

0001 #ifndef BOOST_PARSER_TRANSFORM_REPLACE_HPP
0002 #define BOOST_PARSER_TRANSFORM_REPLACE_HPP
0003 
0004 #include <boost/parser/replace.hpp>
0005 
0006 #if (!defined(_MSC_VER) || BOOST_PARSER_USE_CONCEPTS) &&                       \
0007     (!defined(BOOST_PARSER_GCC) || 12 <= __GNUC__ ||                           \
0008      !BOOST_PARSER_USE_CONCEPTS)
0009 
0010 
0011 namespace boost::parser {
0012 
0013     namespace detail {
0014 
0015         template<typename F>
0016         constexpr bool tidy_func = std::is_trivially_copyable_v<F> &&
0017                                    sizeof(F) <= sizeof(void *) * 2;
0018 
0019         template<typename I, typename S, typename Parser>
0020         using attr_type = decltype(std::declval<Parser const &>().call(
0021             std::declval<I &>(),
0022             std::declval<S>(),
0023             std::declval<
0024                 parse_context<false, false, I, S, default_error_handler>>(),
0025             ws,
0026             detail::default_flags(),
0027             std::declval<bool &>()));
0028         template<typename R, typename Parser>
0029         using range_attr_t = attr_type<iterator_t<R>, sentinel_t<R>, Parser>;
0030 
0031 #if BOOST_PARSER_USE_CONCEPTS
0032         template<typename F, typename V, typename Parser>
0033         concept transform_replacement_for =
0034             std::regular_invocable<F &, range_attr_t<V, Parser>> &&
0035             detail::replacement_for<
0036                 std::invoke_result_t<F &, range_attr_t<V, Parser>>,
0037                 V> &&
0038             (detail::range_utf_format_v<V> ==
0039              detail::range_utf_format_v<
0040                  std::invoke_result_t<F &, range_attr_t<V, Parser>>>);
0041 #else
0042         template<typename F, typename V, typename Parser>
0043         using transform_replacement_for_expr = decltype(std::declval<F &>()(
0044             std::declval<range_attr_t<V, Parser>>()));
0045         template<
0046             typename F,
0047             typename V,
0048             typename Parser,
0049             bool = is_detected_v<transform_replacement_for_expr, F, V, Parser>>
0050         constexpr bool transform_replacement_for = false;
0051         template<typename F, typename V, typename Parser>
0052         constexpr bool transform_replacement_for<F, V, Parser, true> =
0053             replacement_for<transform_replacement_for_expr<F, V, Parser>, V> &&
0054             (detail::range_utf_format_v<V> ==
0055              detail::range_utf_format_v<
0056                  transform_replacement_for_expr<F, V, Parser>>);
0057 #endif
0058 
0059         template<
0060             typename R,
0061             typename Result,
0062             text::format OtherFormat = range_utf_format_v<remove_cv_ref_t<R>>,
0063             text::format Format = range_utf_format_v<remove_cv_ref_t<Result>>>
0064         struct utf_wrap
0065         {
0066             template<typename R_ = R>
0067             static auto call(R_ && r)
0068             {
0069                 return (R_ &&) r | as_utf<OtherFormat>;
0070             }
0071         };
0072         template<typename R, typename Result, text::format Format>
0073         struct utf_wrap<R, Result, Format, Format>
0074         {
0075             template<typename R_ = R>
0076             static R_ && call(R_ && r)
0077             {
0078                 return (R_ &&) r;
0079             }
0080         };
0081         template<typename R, typename Result>
0082         struct utf_wrap<R, Result, no_format, no_format>
0083         {
0084             template<typename R_ = R>
0085             static R_ && call(R_ && r)
0086             {
0087                 return (R_ &&) r;
0088             }
0089         };
0090         template<typename R, typename Result, text::format Format>
0091         struct utf_wrap<R, Result, no_format, Format>
0092         {
0093             // Looks like you tried to use transform_replace() to replace
0094             // subranges of chars with subranges of some UTF-N (for N=8, 16,
0095             // or 32).  Transcoding from char (unkown encoding) is not
0096             // supported.  Check the return type of your transform function.
0097         };
0098         template<typename R, typename Result, text::format Format>
0099         struct utf_wrap<R, Result, Format, no_format>
0100         {
0101             // Looks like you tried to use transform_replace() to replace
0102             // subranges of some UTF-N (for N=8, 16, or 32) with subranges of
0103             // chars.  Transcoding to char (unkown encoding) is not supported.
0104             // Check the return type of your transform function.
0105         };
0106 
0107         template<typename T>
0108         struct regular_ref_wrapper
0109         {
0110             regular_ref_wrapper() = default;
0111             regular_ref_wrapper(T & ref) : ptr_(&ref) {}
0112 
0113             T & get() const { return *ptr_; }
0114 
0115             T * ptr_;
0116         };
0117 
0118         // This type catches results of calling F, to accommodate when F
0119         // returns an rvalue or a type that needs to be transcoded to a
0120         // different UTF.
0121         template<typename R, typename F, typename Attr>
0122         struct utf_rvalue_shim
0123         {
0124             using result_type = std::invoke_result_t<F &, Attr>;
0125             using maybe_wrapped_result_type =
0126                 decltype(utf_wrap<R, result_type>::call(
0127                     std::declval<result_type>()));
0128             static constexpr bool final_type_is_reference =
0129                 std::is_lvalue_reference_v<maybe_wrapped_result_type>;
0130             using final_type = std::conditional_t<
0131                 final_type_is_reference,
0132                 regular_ref_wrapper<
0133                     std::remove_reference_t<maybe_wrapped_result_type>>,
0134                 remove_cv_ref_t<maybe_wrapped_result_type>>;
0135 
0136             template<typename F_ = F>
0137             utf_rvalue_shim(F_ && f) : f_((F_ &&) f)
0138             {}
0139 
0140             // These two only have return values for testing and metaprogramming
0141             // purposes.
0142             template<
0143                 bool B = final_type_is_reference,
0144                 typename Enable = std::enable_if_t<B>>
0145             decltype(auto) operator()(Attr && attr) const
0146             {
0147                 result_ = final_type(
0148                     utf_wrap<R, result_type>::call((*f_)((Attr &&) attr)));
0149                 return result_->get();
0150             }
0151             template<
0152                 bool B = final_type_is_reference,
0153                 typename Enable = std::enable_if_t<B>>
0154             decltype(auto) operator()(Attr && attr)
0155             {
0156                 result_ = final_type(
0157                     utf_wrap<R, result_type>::call((*f_)((Attr &&) attr)));
0158                 return result_->get();
0159             }
0160             template<
0161                 bool B = final_type_is_reference,
0162                 typename Enable = std::enable_if_t<!B>>
0163             final_type & operator()(Attr && attr) const
0164             {
0165                 result_ = utf_wrap<R, result_type>::call((*f_)((Attr &&) attr));
0166                 return *result_;
0167             }
0168             template<
0169                 bool B = final_type_is_reference,
0170                 typename Enable = std::enable_if_t<!B>>
0171             final_type & operator()(Attr && attr)
0172             {
0173                 result_ = utf_wrap<R, result_type>::call((*f_)((Attr &&) attr));
0174                 return *result_;
0175             }
0176 
0177             template<
0178                 bool B = final_type_is_reference,
0179                 typename Enable = std::enable_if_t<B>>
0180             decltype(auto) get() const
0181             {
0182                 return result_->get();
0183             }
0184             template<
0185                 bool B = final_type_is_reference,
0186                 typename Enable = std::enable_if_t<B>>
0187             decltype(auto) get()
0188             {
0189                 return result_->get();
0190             }
0191             template<
0192                 bool B = final_type_is_reference,
0193                 typename Enable = std::enable_if_t<!B>>
0194             final_type & get() const
0195             {
0196                 return *result_;
0197             }
0198             template<
0199                 bool B = final_type_is_reference,
0200                 typename Enable = std::enable_if_t<!B>>
0201             final_type & get()
0202             {
0203                 return *result_;
0204             }
0205 
0206             std::optional<F> f_;
0207             mutable std::optional<final_type> result_;
0208         };
0209 
0210         template<
0211             typename R,
0212             typename Parser,
0213             typename GlobalState,
0214             typename ErrorHandler,
0215             typename SkipParser>
0216         auto attr_search_impl(
0217             R && r,
0218             parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0219             parser_interface<SkipParser> const & skip,
0220             trace trace_mode)
0221         {
0222             auto first = text::detail::begin(r);
0223             auto const last = text::detail::end(r);
0224 
0225             auto match_first = first;
0226             auto match_last = first;
0227             auto before = [&match_first](auto & ctx) {
0228                 match_first = _where(ctx).begin();
0229             };
0230             auto after = [&match_last](auto & ctx) {
0231                 match_last = _where(ctx).begin();
0232             };
0233 
0234             auto const search_parser =
0235                 omit[*(char_ - parser)] >>
0236                 -lexeme[eps[before] >> parser::skip[parser] >> eps[after]];
0237 
0238             using parse_result_outer = decltype(parser::prefix_parse(
0239                 first, last, search_parser, trace_mode));
0240 
0241             static_assert(
0242                 !std::is_same_v<parse_result_outer, bool>,
0243                 "If you're seeing this error, you passed a parser to "
0244                 "transform_replace() that has no attribute.  Please fix.");
0245 
0246             using parse_result =
0247                 remove_cv_ref_t<decltype(**std::declval<parse_result_outer>())>;
0248 
0249             using return_tuple = tuple<
0250                 decltype(BOOST_PARSER_SUBRANGE(first, first)),
0251                 parse_result>;
0252 
0253             if (first == last) {
0254                 return return_tuple(
0255                     BOOST_PARSER_SUBRANGE(first, first), parse_result{});
0256             }
0257 
0258             if constexpr (std::is_same_v<SkipParser, eps_parser<phony>>) {
0259                 auto result = parser::prefix_parse(
0260                     first, last, search_parser, trace_mode);
0261                 if (*result) {
0262                     return return_tuple(
0263                         BOOST_PARSER_SUBRANGE(match_first, match_last),
0264                         std::move(**result));
0265                 }
0266             } else {
0267                 auto result = parser::prefix_parse(
0268                     first, last, search_parser, skip, trace_mode);
0269                 if (*result) {
0270                     return return_tuple(
0271                         BOOST_PARSER_SUBRANGE(match_first, match_last),
0272                         std::move(**result));
0273                 }
0274             }
0275 
0276             return return_tuple(
0277                 BOOST_PARSER_SUBRANGE(first, first), parse_result{});
0278         }
0279 
0280         template<
0281             typename R,
0282             typename Parser,
0283             typename GlobalState,
0284             typename ErrorHandler,
0285             typename SkipParser>
0286         auto attr_search_repack_shim(
0287             R && r,
0288             parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0289             parser_interface<SkipParser> const & skip,
0290             trace trace_mode)
0291         {
0292             using value_type = range_value_t<decltype(r)>;
0293             if constexpr (std::is_same_v<value_type, char>) {
0294                 return detail::attr_search_impl(
0295                     (R &&) r, parser, skip, trace_mode);
0296             } else {
0297                 auto r_unpacked = detail::text::unpack_iterator_and_sentinel(
0298                     text::detail::begin(r), text::detail::end(r));
0299                 auto result = detail::attr_search_impl(
0300                     r | as_utf32, parser, skip, trace_mode);
0301                 auto subrng = parser::get(result, llong<0>{});
0302                 auto & attr = parser::get(result, llong<1>{});
0303                 return tuple<
0304                     decltype(BOOST_PARSER_SUBRANGE(
0305                         r_unpacked.repack(subrng.begin().base()),
0306                         r_unpacked.repack(subrng.end().base()))),
0307                     remove_cv_ref_t<decltype(attr)>>(
0308                     BOOST_PARSER_SUBRANGE(
0309                         r_unpacked.repack(subrng.begin().base()),
0310                         r_unpacked.repack(subrng.end().base())),
0311                     std::move(attr));
0312             }
0313         }
0314     }
0315 
0316     /** Produces a range of subranges of a given range `base`.  Each subrange
0317         is either a subrange of `base` that does not match the given parser
0318         `parser`, or is `f(*boost::parser::parse(match, parser))`, where `f`
0319         is the given invocable and `match` is the matching subrange.
0320 
0321         In addition to the template parameter constraints, `F` must be
0322         invocable with the attribute type of `Parser`; `V` and the range type
0323         produced by `F`, "`Rf`" must be ranges of `char`, or must have the
0324         same UTF format; and `V` and `Rf` must meet the same compatibility
0325         requirements as described in `std::ranges::join_view`. */
0326     template<
0327 #if BOOST_PARSER_USE_CONCEPTS
0328         std::ranges::viewable_range V,
0329         std::move_constructible F,
0330 #else
0331         typename V,
0332         typename F,
0333 #endif
0334         typename Parser,
0335         typename GlobalState,
0336         typename ErrorHandler,
0337         typename SkipParser
0338 #if !BOOST_PARSER_USE_CONCEPTS
0339         ,
0340         typename Enable =
0341             std::enable_if_t<detail::transform_replacement_for<F, V, Parser>>
0342 #endif
0343         >
0344 #if BOOST_PARSER_USE_CONCEPTS
0345     requires detail::transform_replacement_for<F, V, Parser>
0346 #endif
0347     struct transform_replace_view
0348         : detail::stl_interfaces::view_interface<transform_replace_view<
0349               V,
0350               F,
0351               Parser,
0352               GlobalState,
0353               ErrorHandler,
0354               SkipParser>>
0355     {
0356     private:
0357         using attr_t = detail::range_attr_t<V, Parser>;
0358         using replacement_range = std::invoke_result_t<F &, attr_t>;
0359 
0360     public:
0361         constexpr transform_replace_view() = default;
0362         constexpr transform_replace_view(
0363             V base,
0364             parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0365             parser_interface<SkipParser> const & skip,
0366             F f,
0367             trace trace_mode = trace::off) :
0368             base_(std::move(base)),
0369             f_(std::move(f)),
0370             parser_(parser),
0371             skip_(skip),
0372             trace_mode_(trace_mode)
0373         {}
0374         constexpr transform_replace_view(
0375             V base,
0376             parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0377             F f,
0378             trace trace_mode = trace::off) :
0379             base_(std::move(base)),
0380             f_(std::move(f)),
0381             parser_(parser),
0382             skip_(),
0383             trace_mode_(trace_mode)
0384         {}
0385 
0386         constexpr V base() const &
0387 #if BOOST_PARSER_USE_CONCEPTS
0388             requires std::copy_constructible<V>
0389 #endif
0390         {
0391             return base_;
0392         }
0393         constexpr V base() && { return std::move(base_); }
0394 
0395         constexpr F const & f() const { return *f_.f_; }
0396 
0397         constexpr auto begin() { return iterator<false>{this}; }
0398         constexpr auto end() { return sentinel<false>{}; }
0399 
0400         constexpr auto begin() const
0401 #if BOOST_PARSER_USE_CONCEPTS
0402             requires std::ranges::range<const V>
0403 #endif
0404         {
0405             return iterator<true>{this};
0406         }
0407         constexpr auto end() const
0408 #if BOOST_PARSER_USE_CONCEPTS
0409             requires std::ranges::range<const V>
0410 #endif
0411         {
0412             return sentinel<true>{};
0413         }
0414 
0415         template<bool Const>
0416         struct sentinel
0417         {};
0418 
0419         template<bool Const>
0420         struct iterator
0421             : detail::stl_interfaces::proxy_iterator_interface<
0422                   iterator<Const>,
0423                   std::forward_iterator_tag,
0424                   BOOST_PARSER_SUBRANGE<detail::either_iterator<
0425                       detail::maybe_const<Const, V>,
0426                       detail::maybe_const<Const, replacement_range>>>>
0427         {
0428             using I = detail::iterator_t<detail::maybe_const<Const, V>>;
0429             using S = detail::sentinel_t<detail::maybe_const<Const, V>>;
0430 
0431             using ref_t_iter = detail::either_iterator<
0432                 detail::maybe_const<Const, V>,
0433                 detail::maybe_const<Const, replacement_range>>;
0434             using reference_type = BOOST_PARSER_SUBRANGE<ref_t_iter>;
0435 
0436             constexpr iterator() = default;
0437             constexpr iterator(
0438                 detail::maybe_const<Const, transform_replace_view> * parent) :
0439                 parent_(parent),
0440                 r_(parent_->base_.begin(), parent_->base_.end()),
0441                 curr_(r_.begin(), r_.begin()),
0442                 next_it_(r_.begin()),
0443                 in_match_(true)
0444             {
0445                 ++*this;
0446             }
0447 
0448             constexpr iterator & operator++()
0449             {
0450                 if (in_match_) {
0451                     r_ = BOOST_PARSER_SUBRANGE<I, S>(next_it_, r_.end());
0452                     auto new_match_and_attr = detail::attr_search_repack_shim(
0453                         r_,
0454                         parent_->parser_,
0455                         parent_->skip_,
0456                         parent_->trace_mode_);
0457                     auto const new_match =
0458                         parser::get(new_match_and_attr, llong<0>{});
0459                     parent_->f_(
0460                         parser::get(std::move(new_match_and_attr), llong<1>{}));
0461                     if (new_match.begin() == curr_.end()) {
0462                         curr_ = new_match;
0463                     } else {
0464                         curr_ =
0465                             BOOST_PARSER_SUBRANGE(next_it_, new_match.begin());
0466                         in_match_ = false;
0467                     }
0468                     next_it_ = new_match.end();
0469                 } else {
0470                     if (!curr_.empty()) {
0471                         curr_ = BOOST_PARSER_SUBRANGE(curr_.end(), next_it_);
0472                         in_match_ = true;
0473                     }
0474                     if (curr_.empty())
0475                         r_ = BOOST_PARSER_SUBRANGE<I, S>(next_it_, r_.end());
0476                 }
0477                 return *this;
0478             }
0479 
0480             constexpr reference_type operator*() const
0481             {
0482                 if (in_match_) {
0483                     return reference_type(
0484                         ref_t_iter(parent_->f_.get().begin()),
0485                         ref_t_iter(parent_->f_.get().end()));
0486                 } else {
0487                     return reference_type(
0488                         ref_t_iter(curr_.begin()), ref_t_iter(curr_.end()));
0489                 }
0490             }
0491 
0492             friend constexpr bool operator==(iterator lhs, iterator rhs)
0493             {
0494                 return lhs.r_.begin() == rhs.r_.begin();
0495             }
0496             friend constexpr bool operator==(iterator it, sentinel<Const>)
0497             {
0498                 return it.r_.begin() == it.r_.end();
0499             }
0500 
0501             using base_type = detail::stl_interfaces::proxy_iterator_interface<
0502                 iterator,
0503                 std::forward_iterator_tag,
0504                 reference_type>;
0505             using base_type::operator++;
0506 
0507         private:
0508             detail::maybe_const<Const, transform_replace_view> * parent_ = {};
0509             BOOST_PARSER_SUBRANGE<I, S> r_;
0510             BOOST_PARSER_SUBRANGE<I> curr_;
0511             I next_it_ = {};
0512             bool in_match_ = {};
0513         };
0514 
0515         template<bool Const>
0516         friend struct iterator;
0517 
0518     private:
0519         V base_;
0520         F f_;
0521         parser_interface<Parser, GlobalState, ErrorHandler> parser_;
0522         parser_interface<SkipParser> skip_;
0523         trace trace_mode_;
0524     };
0525 
0526     // deduction guides
0527     template<
0528         typename V,
0529         typename F,
0530         typename Parser,
0531         typename GlobalState,
0532         typename ErrorHandler,
0533         typename SkipParser>
0534     transform_replace_view(
0535         V &&,
0536         parser_interface<Parser, GlobalState, ErrorHandler>,
0537         parser_interface<SkipParser>,
0538         F &&,
0539         trace)
0540         -> transform_replace_view<
0541             detail::text::detail::all_t<V>,
0542             detail::remove_cv_ref_t<F>,
0543             Parser,
0544             GlobalState,
0545             ErrorHandler,
0546             SkipParser>;
0547 
0548     template<
0549         typename V,
0550         typename F,
0551         typename Parser,
0552         typename GlobalState,
0553         typename ErrorHandler,
0554         typename SkipParser>
0555     transform_replace_view(
0556         V &&,
0557         parser_interface<Parser, GlobalState, ErrorHandler>,
0558         parser_interface<SkipParser>,
0559         F &&)
0560         -> transform_replace_view<
0561             detail::text::detail::all_t<V>,
0562             detail::remove_cv_ref_t<F>,
0563             Parser,
0564             GlobalState,
0565             ErrorHandler,
0566             SkipParser>;
0567 
0568     template<
0569         typename V,
0570         typename F,
0571         typename Parser,
0572         typename GlobalState,
0573         typename ErrorHandler>
0574     transform_replace_view(
0575         V &&, parser_interface<Parser, GlobalState, ErrorHandler>, F &&, trace)
0576         -> transform_replace_view<
0577             detail::text::detail::all_t<V>,
0578             detail::remove_cv_ref_t<F>,
0579             Parser,
0580             GlobalState,
0581             ErrorHandler,
0582             parser_interface<eps_parser<detail::phony>>>;
0583 
0584     template<
0585         typename V,
0586         typename F,
0587         typename Parser,
0588         typename GlobalState,
0589         typename ErrorHandler>
0590     transform_replace_view(
0591         V &&, parser_interface<Parser, GlobalState, ErrorHandler>, F &&)
0592         -> transform_replace_view<
0593             detail::text::detail::all_t<V>,
0594             detail::remove_cv_ref_t<F>,
0595             Parser,
0596             GlobalState,
0597             ErrorHandler,
0598             parser_interface<eps_parser<detail::phony>>>;
0599 
0600     namespace detail {
0601         template<
0602             typename V,
0603             typename F,
0604             typename Parser,
0605             typename GlobalState,
0606             typename ErrorHandler,
0607             typename SkipParser>
0608         using transform_replace_view_expr = decltype(transform_replace_view<
0609                                                      V,
0610                                                      F,
0611                                                      Parser,
0612                                                      GlobalState,
0613                                                      ErrorHandler,
0614                                                      SkipParser>(
0615             std::declval<V>(),
0616             std::declval<
0617                 parser_interface<Parser, GlobalState, ErrorHandler> const &>(),
0618             std::declval<parser_interface<SkipParser> const &>(),
0619             std::declval<F>(),
0620             trace::on));
0621 
0622         template<
0623             typename V,
0624             typename F,
0625             typename Parser,
0626             typename GlobalState,
0627             typename ErrorHandler,
0628             typename SkipParser>
0629         constexpr bool can_transform_replace_view = is_detected_v<
0630             transform_replace_view_expr,
0631             V,
0632             F,
0633             Parser,
0634             GlobalState,
0635             ErrorHandler,
0636             SkipParser>;
0637 
0638         struct transform_replace_impl
0639         {
0640 #if BOOST_PARSER_USE_CONCEPTS
0641 
0642             template<
0643                 parsable_range R,
0644                 std::move_constructible F,
0645                 typename Parser,
0646                 typename GlobalState,
0647                 typename ErrorHandler,
0648                 typename SkipParser>
0649                 requires std::ranges::viewable_range<R> &&
0650                          std::regular_invocable<
0651                              F &,
0652                              range_attr_t<to_range_t<R>, Parser>> &&
0653                          can_transform_replace_view<
0654                              to_range_t<R>,
0655                              utf_rvalue_shim<
0656                                  to_range_t<R>,
0657                                  std::remove_cvref_t<F>,
0658                                  range_attr_t<to_range_t<R>, Parser>>,
0659                              Parser,
0660                              GlobalState,
0661                              ErrorHandler,
0662                              SkipParser>
0663             [[nodiscard]] constexpr auto operator()(
0664                 R && r,
0665                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0666                     parser,
0667                 parser_interface<SkipParser> const & skip,
0668                 F && f,
0669                 trace trace_mode = trace::off) const
0670             {
0671                 return transform_replace_view(
0672                     to_range<R>::call((R &&)r),
0673                     parser,
0674                     skip,
0675                     utf_rvalue_shim<
0676                         to_range_t<R>,
0677                         std::remove_cvref_t<F>,
0678                         range_attr_t<to_range_t<R>, Parser>>((F &&)f),
0679                     trace_mode);
0680             }
0681 
0682             template<
0683                 parsable_range R,
0684                 std::move_constructible F,
0685                 typename Parser,
0686                 typename GlobalState,
0687                 typename ErrorHandler>
0688                 requires std::ranges::viewable_range<R> &&
0689                          std::regular_invocable<
0690                              F &,
0691                              range_attr_t<to_range_t<R>, Parser>> &&
0692                          can_transform_replace_view<
0693                              to_range_t<R>,
0694                              utf_rvalue_shim<
0695                                  to_range_t<R>,
0696                                  std::remove_cvref_t<F>,
0697                                  range_attr_t<to_range_t<R>, Parser>>,
0698                              Parser,
0699                              GlobalState,
0700                              ErrorHandler,
0701                              parser_interface<eps_parser<detail::phony>>>
0702             [[nodiscard]] constexpr auto operator()(
0703                 R && r,
0704                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0705                     parser,
0706                 F && f,
0707                 trace trace_mode = trace::off) const
0708             {
0709                 return (*this)(
0710                     (R &&)r,
0711                     parser,
0712                     parser_interface<eps_parser<detail::phony>>{},
0713                     (F &&)f,
0714                     trace_mode);
0715             }
0716 
0717 #else
0718 
0719             template<
0720                 typename R,
0721                 typename Parser,
0722                 typename GlobalState,
0723                 typename ErrorHandler,
0724                 typename SkipParser,
0725                 typename F = trace,
0726                 typename Trace = trace,
0727                 typename Enable = std::enable_if_t<is_parsable_range_v<R>>>
0728             [[nodiscard]] constexpr auto operator()(
0729                 R && r,
0730                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0731                     parser,
0732                 SkipParser && skip,
0733                 F && f = F{},
0734                 Trace trace_mode = Trace{}) const
0735             {
0736                 if constexpr (
0737                     is_parser_iface<remove_cv_ref_t<SkipParser>> &&
0738                     std::is_invocable_v<
0739                         F &,
0740                         range_attr_t<to_range_t<R>, Parser>> &&
0741                     std::is_same_v<Trace, trace>) {
0742                     // (r, parser, skip, f, trace) case
0743                     return impl(
0744                         to_range<R>::call((R &&) r),
0745                         parser,
0746                         skip,
0747                         (F &&) f,
0748                         trace_mode);
0749                 } else if constexpr (
0750                     std::is_invocable_v<
0751                         SkipParser &,
0752                         range_attr_t<to_range_t<R>, Parser>> &&
0753                     std::is_same_v<remove_cv_ref_t<F>, trace> &&
0754                     std::is_same_v<Trace, trace>) {
0755                     // (r, parser, f, trace) case
0756                     return impl(
0757                         to_range<R>::call((R &&) r),
0758                         parser,
0759                         parser_interface<eps_parser<detail::phony>>{},
0760                         (SkipParser &&) skip,
0761                         f);
0762                 } else {
0763                     static_assert(
0764                         sizeof(R) == 1 && false,
0765                         "Only the signatures replace(R, parser, skip, "
0766                         "replcement trace = trace::off) and replace(R, parser, "
0767                         "f, trace = trace::off) are supported.");
0768                 }
0769             }
0770 
0771         private:
0772             template<
0773                 typename R,
0774                 typename F,
0775                 typename Parser,
0776                 typename GlobalState,
0777                 typename ErrorHandler,
0778                 typename SkipParser>
0779             [[nodiscard]] constexpr auto impl(
0780                 R && r,
0781                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0782                     parser,
0783                 parser_interface<SkipParser> const & skip,
0784                 F && f,
0785                 trace trace_mode = trace::off) const
0786             {
0787                 return transform_replace_view(
0788                     (R &&) r,
0789                     parser,
0790                     skip,
0791                     utf_rvalue_shim<
0792                         R,
0793                         remove_cv_ref_t<F>,
0794                         range_attr_t<R, Parser>>((F &&) f),
0795                     trace_mode);
0796             }
0797 
0798 #endif
0799         };
0800     }
0801 
0802     /** A range adaptor object ([range.adaptor.object]).  Given subexpressions
0803         `E` and `P`, `Q`, `R`, and 'S', each of the expressions `replace(E,
0804         P)`, `replace(E, P, Q)`. `replace(E, P, Q, R)`, and `replace(E, P, Q,
0805         R, S)` are expression-equivalent to `replace_view(E, P)`,
0806         `replace_view(E, P, Q)`, `replace_view(E, P, Q, R)`, `replace_view(E,
0807         P, Q, R, S)`, respectively. */
0808     inline constexpr detail::stl_interfaces::adaptor<
0809         detail::transform_replace_impl>
0810         transform_replace = detail::transform_replace_impl{};
0811 
0812 }
0813 
0814 #if BOOST_PARSER_USE_CONCEPTS
0815 template<
0816     typename V,
0817     typename F,
0818     typename Parser,
0819     typename GlobalState,
0820     typename ErrorHandler,
0821     typename SkipParser>
0822 constexpr bool
0823     std::ranges::enable_borrowed_range<boost::parser::transform_replace_view<
0824         V,
0825         F,
0826         Parser,
0827         GlobalState,
0828         ErrorHandler,
0829         SkipParser>> = std::ranges::enable_borrowed_range<V> &&
0830                        (std::ranges::enable_borrowed_range<F> ||
0831                         boost::parser::detail::tidy_func<F>);
0832 #endif
0833 
0834 #endif
0835 
0836 #endif