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
0094
0095
0096
0097 };
0098 template<typename R, typename Result, text::format Format>
0099 struct utf_wrap<R, Result, Format, no_format>
0100 {
0101
0102
0103
0104
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
0119
0120
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
0141
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
0317
0318
0319
0320
0321
0322
0323
0324
0325
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
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
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
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
0803
0804
0805
0806
0807
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