transform_replace.hpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. #ifndef BOOST_PARSER_TRANSFORM_REPLACE_HPP
  2. #define BOOST_PARSER_TRANSFORM_REPLACE_HPP
  3. #include <boost/parser/replace.hpp>
  4. #if (!defined(_MSC_VER) || BOOST_PARSER_USE_CONCEPTS) && \
  5. (!defined(BOOST_PARSER_GCC) || 12 <= __GNUC__ || \
  6. !BOOST_PARSER_USE_CONCEPTS)
  7. namespace boost::parser {
  8. namespace detail {
  9. template<typename F>
  10. constexpr bool tidy_func = std::is_trivially_copyable_v<F> &&
  11. sizeof(F) <= sizeof(void *) * 2;
  12. template<typename I, typename S, typename Parser>
  13. using attr_type = decltype(std::declval<Parser const &>().call(
  14. std::declval<I &>(),
  15. std::declval<S>(),
  16. std::declval<
  17. parse_context<false, false, I, S, default_error_handler>>(),
  18. ws,
  19. detail::default_flags(),
  20. std::declval<bool &>()));
  21. template<typename R, typename Parser>
  22. using range_attr_t = attr_type<iterator_t<R>, sentinel_t<R>, Parser>;
  23. #if BOOST_PARSER_USE_CONCEPTS
  24. template<typename F, typename V, typename Parser>
  25. concept transform_replacement_for =
  26. std::regular_invocable<F &, range_attr_t<V, Parser>> &&
  27. detail::replacement_for<
  28. std::invoke_result_t<F &, range_attr_t<V, Parser>>,
  29. V> &&
  30. (detail::range_utf_format_v<V> ==
  31. detail::range_utf_format_v<
  32. std::invoke_result_t<F &, range_attr_t<V, Parser>>>);
  33. #else
  34. template<typename F, typename V, typename Parser>
  35. using transform_replacement_for_expr = decltype(std::declval<F &>()(
  36. std::declval<range_attr_t<V, Parser>>()));
  37. template<
  38. typename F,
  39. typename V,
  40. typename Parser,
  41. bool = is_detected_v<transform_replacement_for_expr, F, V, Parser>>
  42. constexpr bool transform_replacement_for = false;
  43. template<typename F, typename V, typename Parser>
  44. constexpr bool transform_replacement_for<F, V, Parser, true> =
  45. replacement_for<transform_replacement_for_expr<F, V, Parser>, V> &&
  46. (detail::range_utf_format_v<V> ==
  47. detail::range_utf_format_v<
  48. transform_replacement_for_expr<F, V, Parser>>);
  49. #endif
  50. template<
  51. typename R,
  52. typename Result,
  53. text::format OtherFormat = range_utf_format_v<remove_cv_ref_t<R>>,
  54. text::format Format = range_utf_format_v<remove_cv_ref_t<Result>>>
  55. struct utf_wrap
  56. {
  57. template<typename R_ = R>
  58. static auto call(R_ && r)
  59. {
  60. return (R_ &&) r | as_utf<OtherFormat>;
  61. }
  62. };
  63. template<typename R, typename Result, text::format Format>
  64. struct utf_wrap<R, Result, Format, Format>
  65. {
  66. template<typename R_ = R>
  67. static R_ && call(R_ && r)
  68. {
  69. return (R_ &&) r;
  70. }
  71. };
  72. template<typename R, typename Result>
  73. struct utf_wrap<R, Result, no_format, no_format>
  74. {
  75. template<typename R_ = R>
  76. static R_ && call(R_ && r)
  77. {
  78. return (R_ &&) r;
  79. }
  80. };
  81. template<typename R, typename Result, text::format Format>
  82. struct utf_wrap<R, Result, no_format, Format>
  83. {
  84. // Looks like you tried to use transform_replace() to replace
  85. // subranges of chars with subranges of some UTF-N (for N=8, 16,
  86. // or 32). Transcoding from char (unkown encoding) is not
  87. // supported. Check the return type of your transform function.
  88. };
  89. template<typename R, typename Result, text::format Format>
  90. struct utf_wrap<R, Result, Format, no_format>
  91. {
  92. // Looks like you tried to use transform_replace() to replace
  93. // subranges of some UTF-N (for N=8, 16, or 32) with subranges of
  94. // chars. Transcoding to char (unkown encoding) is not supported.
  95. // Check the return type of your transform function.
  96. };
  97. template<typename T>
  98. struct regular_ref_wrapper
  99. {
  100. regular_ref_wrapper() = default;
  101. regular_ref_wrapper(T & ref) : ptr_(&ref) {}
  102. T & get() const { return *ptr_; }
  103. T * ptr_;
  104. };
  105. // This type catches results of calling F, to accommodate when F
  106. // returns an rvalue or a type that needs to be transcoded to a
  107. // different UTF.
  108. template<typename R, typename F, typename Attr>
  109. struct utf_rvalue_shim
  110. {
  111. using result_type = std::invoke_result_t<F &, Attr>;
  112. using maybe_wrapped_result_type =
  113. decltype(utf_wrap<R, result_type>::call(
  114. std::declval<result_type>()));
  115. static constexpr bool final_type_is_reference =
  116. std::is_lvalue_reference_v<maybe_wrapped_result_type>;
  117. using final_type = std::conditional_t<
  118. final_type_is_reference,
  119. regular_ref_wrapper<
  120. std::remove_reference_t<maybe_wrapped_result_type>>,
  121. remove_cv_ref_t<maybe_wrapped_result_type>>;
  122. template<typename F_ = F>
  123. utf_rvalue_shim(F_ && f) : f_((F_ &&) f)
  124. {}
  125. // These two only have return values for testing and metaprogramming
  126. // purposes.
  127. template<
  128. bool B = final_type_is_reference,
  129. typename Enable = std::enable_if_t<B>>
  130. decltype(auto) operator()(Attr && attr) const
  131. {
  132. result_ = final_type(
  133. utf_wrap<R, result_type>::call((*f_)((Attr &&) attr)));
  134. return result_->get();
  135. }
  136. template<
  137. bool B = final_type_is_reference,
  138. typename Enable = std::enable_if_t<B>>
  139. decltype(auto) operator()(Attr && attr)
  140. {
  141. result_ = final_type(
  142. utf_wrap<R, result_type>::call((*f_)((Attr &&) attr)));
  143. return result_->get();
  144. }
  145. template<
  146. bool B = final_type_is_reference,
  147. typename Enable = std::enable_if_t<!B>>
  148. final_type & operator()(Attr && attr) const
  149. {
  150. result_ = utf_wrap<R, result_type>::call((*f_)((Attr &&) attr));
  151. return *result_;
  152. }
  153. template<
  154. bool B = final_type_is_reference,
  155. typename Enable = std::enable_if_t<!B>>
  156. final_type & operator()(Attr && attr)
  157. {
  158. result_ = utf_wrap<R, result_type>::call((*f_)((Attr &&) attr));
  159. return *result_;
  160. }
  161. template<
  162. bool B = final_type_is_reference,
  163. typename Enable = std::enable_if_t<B>>
  164. decltype(auto) get() const
  165. {
  166. return result_->get();
  167. }
  168. template<
  169. bool B = final_type_is_reference,
  170. typename Enable = std::enable_if_t<B>>
  171. decltype(auto) get()
  172. {
  173. return result_->get();
  174. }
  175. template<
  176. bool B = final_type_is_reference,
  177. typename Enable = std::enable_if_t<!B>>
  178. final_type & get() const
  179. {
  180. return *result_;
  181. }
  182. template<
  183. bool B = final_type_is_reference,
  184. typename Enable = std::enable_if_t<!B>>
  185. final_type & get()
  186. {
  187. return *result_;
  188. }
  189. std::optional<F> f_;
  190. mutable std::optional<final_type> result_;
  191. };
  192. template<
  193. typename R,
  194. typename Parser,
  195. typename GlobalState,
  196. typename ErrorHandler,
  197. typename SkipParser>
  198. auto attr_search_impl(
  199. R && r,
  200. parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
  201. parser_interface<SkipParser> const & skip,
  202. trace trace_mode)
  203. {
  204. auto first = text::detail::begin(r);
  205. auto const last = text::detail::end(r);
  206. auto match_first = first;
  207. auto match_last = first;
  208. auto before = [&match_first](auto & ctx) {
  209. match_first = _where(ctx).begin();
  210. };
  211. auto after = [&match_last](auto & ctx) {
  212. match_last = _where(ctx).begin();
  213. };
  214. auto const search_parser =
  215. omit[*(char_ - parser)] >>
  216. -lexeme[eps[before] >> parser::skip[parser] >> eps[after]];
  217. using parse_result_outer = decltype(parser::prefix_parse(
  218. first, last, search_parser, trace_mode));
  219. static_assert(
  220. !std::is_same_v<parse_result_outer, bool>,
  221. "If you're seeing this error, you passed a parser to "
  222. "transform_replace() that has no attribute. Please fix.");
  223. using parse_result =
  224. remove_cv_ref_t<decltype(**std::declval<parse_result_outer>())>;
  225. using return_tuple = tuple<
  226. decltype(BOOST_PARSER_SUBRANGE(first, first)),
  227. parse_result>;
  228. if (first == last) {
  229. return return_tuple(
  230. BOOST_PARSER_SUBRANGE(first, first), parse_result{});
  231. }
  232. if constexpr (std::is_same_v<SkipParser, eps_parser<phony>>) {
  233. auto result = parser::prefix_parse(
  234. first, last, search_parser, trace_mode);
  235. if (*result) {
  236. return return_tuple(
  237. BOOST_PARSER_SUBRANGE(match_first, match_last),
  238. std::move(**result));
  239. }
  240. } else {
  241. auto result = parser::prefix_parse(
  242. first, last, search_parser, skip, trace_mode);
  243. if (*result) {
  244. return return_tuple(
  245. BOOST_PARSER_SUBRANGE(match_first, match_last),
  246. std::move(**result));
  247. }
  248. }
  249. return return_tuple(
  250. BOOST_PARSER_SUBRANGE(first, first), parse_result{});
  251. }
  252. template<
  253. typename R,
  254. typename Parser,
  255. typename GlobalState,
  256. typename ErrorHandler,
  257. typename SkipParser>
  258. auto attr_search_repack_shim(
  259. R && r,
  260. parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
  261. parser_interface<SkipParser> const & skip,
  262. trace trace_mode)
  263. {
  264. using value_type = range_value_t<decltype(r)>;
  265. if constexpr (std::is_same_v<value_type, char>) {
  266. return detail::attr_search_impl(
  267. (R &&) r, parser, skip, trace_mode);
  268. } else {
  269. auto r_unpacked = detail::text::unpack_iterator_and_sentinel(
  270. text::detail::begin(r), text::detail::end(r));
  271. auto result = detail::attr_search_impl(
  272. r | as_utf32, parser, skip, trace_mode);
  273. auto subrng = parser::get(result, llong<0>{});
  274. auto & attr = parser::get(result, llong<1>{});
  275. return tuple<
  276. decltype(BOOST_PARSER_SUBRANGE(
  277. r_unpacked.repack(subrng.begin().base()),
  278. r_unpacked.repack(subrng.end().base()))),
  279. remove_cv_ref_t<decltype(attr)>>(
  280. BOOST_PARSER_SUBRANGE(
  281. r_unpacked.repack(subrng.begin().base()),
  282. r_unpacked.repack(subrng.end().base())),
  283. std::move(attr));
  284. }
  285. }
  286. }
  287. /** Produces a range of subranges of a given range `base`. Each subrange
  288. is either a subrange of `base` that does not match the given parser
  289. `parser`, or is `f(*boost::parser::parse(match, parser))`, where `f`
  290. is the given invocable and `match` is the matching subrange.
  291. In addition to the template parameter constraints, `F` must be
  292. invocable with the attribute type of `Parser`; `V` and the range type
  293. produced by `F`, "`Rf`" must be ranges of `char`, or must have the
  294. same UTF format; and `V` and `Rf` must meet the same compatibility
  295. requirements as described in `std::ranges::join_view`. */
  296. template<
  297. #if BOOST_PARSER_USE_CONCEPTS
  298. std::ranges::viewable_range V,
  299. std::move_constructible F,
  300. #else
  301. typename V,
  302. typename F,
  303. #endif
  304. typename Parser,
  305. typename GlobalState,
  306. typename ErrorHandler,
  307. typename SkipParser
  308. #if !BOOST_PARSER_USE_CONCEPTS
  309. ,
  310. typename Enable =
  311. std::enable_if_t<detail::transform_replacement_for<F, V, Parser>>
  312. #endif
  313. >
  314. #if BOOST_PARSER_USE_CONCEPTS
  315. requires detail::transform_replacement_for<F, V, Parser>
  316. #endif
  317. struct transform_replace_view
  318. : detail::stl_interfaces::view_interface<transform_replace_view<
  319. V,
  320. F,
  321. Parser,
  322. GlobalState,
  323. ErrorHandler,
  324. SkipParser>>
  325. {
  326. private:
  327. using attr_t = detail::range_attr_t<V, Parser>;
  328. using replacement_range = std::invoke_result_t<F &, attr_t>;
  329. public:
  330. constexpr transform_replace_view() = default;
  331. constexpr transform_replace_view(
  332. V base,
  333. parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
  334. parser_interface<SkipParser> const & skip,
  335. F f,
  336. trace trace_mode = trace::off) :
  337. base_(std::move(base)),
  338. f_(std::move(f)),
  339. parser_(parser),
  340. skip_(skip),
  341. trace_mode_(trace_mode)
  342. {}
  343. constexpr transform_replace_view(
  344. V base,
  345. parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
  346. F f,
  347. trace trace_mode = trace::off) :
  348. base_(std::move(base)),
  349. f_(std::move(f)),
  350. parser_(parser),
  351. skip_(),
  352. trace_mode_(trace_mode)
  353. {}
  354. constexpr V base() const &
  355. #if BOOST_PARSER_USE_CONCEPTS
  356. requires std::copy_constructible<V>
  357. #endif
  358. {
  359. return base_;
  360. }
  361. constexpr V base() && { return std::move(base_); }
  362. constexpr F const & f() const { return *f_.f_; }
  363. constexpr auto begin() { return iterator<false>{this}; }
  364. constexpr auto end() { return sentinel<false>{}; }
  365. constexpr auto begin() const
  366. #if BOOST_PARSER_USE_CONCEPTS
  367. requires std::ranges::range<const V>
  368. #endif
  369. {
  370. return iterator<true>{this};
  371. }
  372. constexpr auto end() const
  373. #if BOOST_PARSER_USE_CONCEPTS
  374. requires std::ranges::range<const V>
  375. #endif
  376. {
  377. return sentinel<true>{};
  378. }
  379. template<bool Const>
  380. struct sentinel
  381. {};
  382. template<bool Const>
  383. struct iterator
  384. : detail::stl_interfaces::proxy_iterator_interface<
  385. iterator<Const>,
  386. std::forward_iterator_tag,
  387. BOOST_PARSER_SUBRANGE<detail::either_iterator<
  388. detail::maybe_const<Const, V>,
  389. detail::maybe_const<Const, replacement_range>>>>
  390. {
  391. using I = detail::iterator_t<detail::maybe_const<Const, V>>;
  392. using S = detail::sentinel_t<detail::maybe_const<Const, V>>;
  393. using ref_t_iter = detail::either_iterator<
  394. detail::maybe_const<Const, V>,
  395. detail::maybe_const<Const, replacement_range>>;
  396. using reference_type = BOOST_PARSER_SUBRANGE<ref_t_iter>;
  397. constexpr iterator() = default;
  398. constexpr iterator(
  399. detail::maybe_const<Const, transform_replace_view> * parent) :
  400. parent_(parent),
  401. r_(parent_->base_.begin(), parent_->base_.end()),
  402. curr_(r_.begin(), r_.begin()),
  403. next_it_(r_.begin()),
  404. in_match_(true)
  405. {
  406. ++*this;
  407. }
  408. constexpr iterator & operator++()
  409. {
  410. if (in_match_) {
  411. r_ = BOOST_PARSER_SUBRANGE<I, S>(next_it_, r_.end());
  412. auto new_match_and_attr = detail::attr_search_repack_shim(
  413. r_,
  414. parent_->parser_,
  415. parent_->skip_,
  416. parent_->trace_mode_);
  417. auto const new_match =
  418. parser::get(new_match_and_attr, llong<0>{});
  419. parent_->f_(
  420. parser::get(std::move(new_match_and_attr), llong<1>{}));
  421. if (new_match.begin() == curr_.end()) {
  422. curr_ = new_match;
  423. } else {
  424. curr_ =
  425. BOOST_PARSER_SUBRANGE(next_it_, new_match.begin());
  426. in_match_ = false;
  427. }
  428. next_it_ = new_match.end();
  429. } else {
  430. if (!curr_.empty()) {
  431. curr_ = BOOST_PARSER_SUBRANGE(curr_.end(), next_it_);
  432. in_match_ = true;
  433. }
  434. if (curr_.empty())
  435. r_ = BOOST_PARSER_SUBRANGE<I, S>(next_it_, r_.end());
  436. }
  437. return *this;
  438. }
  439. constexpr reference_type operator*() const
  440. {
  441. if (in_match_) {
  442. return reference_type(
  443. ref_t_iter(parent_->f_.get().begin()),
  444. ref_t_iter(parent_->f_.get().end()));
  445. } else {
  446. return reference_type(
  447. ref_t_iter(curr_.begin()), ref_t_iter(curr_.end()));
  448. }
  449. }
  450. friend constexpr bool operator==(iterator lhs, iterator rhs)
  451. {
  452. return lhs.r_.begin() == rhs.r_.begin();
  453. }
  454. friend constexpr bool operator==(iterator it, sentinel<Const>)
  455. {
  456. return it.r_.begin() == it.r_.end();
  457. }
  458. using base_type = detail::stl_interfaces::proxy_iterator_interface<
  459. iterator,
  460. std::forward_iterator_tag,
  461. reference_type>;
  462. using base_type::operator++;
  463. private:
  464. detail::maybe_const<Const, transform_replace_view> * parent_ = {};
  465. BOOST_PARSER_SUBRANGE<I, S> r_;
  466. BOOST_PARSER_SUBRANGE<I> curr_;
  467. I next_it_ = {};
  468. bool in_match_ = {};
  469. };
  470. template<bool Const>
  471. friend struct iterator;
  472. private:
  473. V base_;
  474. F f_;
  475. parser_interface<Parser, GlobalState, ErrorHandler> parser_;
  476. parser_interface<SkipParser> skip_;
  477. trace trace_mode_;
  478. };
  479. // deduction guides
  480. template<
  481. typename V,
  482. typename F,
  483. typename Parser,
  484. typename GlobalState,
  485. typename ErrorHandler,
  486. typename SkipParser>
  487. transform_replace_view(
  488. V &&,
  489. parser_interface<Parser, GlobalState, ErrorHandler>,
  490. parser_interface<SkipParser>,
  491. F &&,
  492. trace)
  493. -> transform_replace_view<
  494. detail::text::detail::all_t<V>,
  495. detail::remove_cv_ref_t<F>,
  496. Parser,
  497. GlobalState,
  498. ErrorHandler,
  499. SkipParser>;
  500. template<
  501. typename V,
  502. typename F,
  503. typename Parser,
  504. typename GlobalState,
  505. typename ErrorHandler,
  506. typename SkipParser>
  507. transform_replace_view(
  508. V &&,
  509. parser_interface<Parser, GlobalState, ErrorHandler>,
  510. parser_interface<SkipParser>,
  511. F &&)
  512. -> transform_replace_view<
  513. detail::text::detail::all_t<V>,
  514. detail::remove_cv_ref_t<F>,
  515. Parser,
  516. GlobalState,
  517. ErrorHandler,
  518. SkipParser>;
  519. template<
  520. typename V,
  521. typename F,
  522. typename Parser,
  523. typename GlobalState,
  524. typename ErrorHandler>
  525. transform_replace_view(
  526. V &&, parser_interface<Parser, GlobalState, ErrorHandler>, F &&, trace)
  527. -> transform_replace_view<
  528. detail::text::detail::all_t<V>,
  529. detail::remove_cv_ref_t<F>,
  530. Parser,
  531. GlobalState,
  532. ErrorHandler,
  533. parser_interface<eps_parser<detail::phony>>>;
  534. template<
  535. typename V,
  536. typename F,
  537. typename Parser,
  538. typename GlobalState,
  539. typename ErrorHandler>
  540. transform_replace_view(
  541. V &&, parser_interface<Parser, GlobalState, ErrorHandler>, F &&)
  542. -> transform_replace_view<
  543. detail::text::detail::all_t<V>,
  544. detail::remove_cv_ref_t<F>,
  545. Parser,
  546. GlobalState,
  547. ErrorHandler,
  548. parser_interface<eps_parser<detail::phony>>>;
  549. namespace detail {
  550. template<
  551. typename V,
  552. typename F,
  553. typename Parser,
  554. typename GlobalState,
  555. typename ErrorHandler,
  556. typename SkipParser>
  557. using transform_replace_view_expr = decltype(transform_replace_view<
  558. V,
  559. F,
  560. Parser,
  561. GlobalState,
  562. ErrorHandler,
  563. SkipParser>(
  564. std::declval<V>(),
  565. std::declval<
  566. parser_interface<Parser, GlobalState, ErrorHandler> const &>(),
  567. std::declval<parser_interface<SkipParser> const &>(),
  568. std::declval<F>(),
  569. trace::on));
  570. template<
  571. typename V,
  572. typename F,
  573. typename Parser,
  574. typename GlobalState,
  575. typename ErrorHandler,
  576. typename SkipParser>
  577. constexpr bool can_transform_replace_view = is_detected_v<
  578. transform_replace_view_expr,
  579. V,
  580. F,
  581. Parser,
  582. GlobalState,
  583. ErrorHandler,
  584. SkipParser>;
  585. struct transform_replace_impl
  586. {
  587. #if BOOST_PARSER_USE_CONCEPTS
  588. template<
  589. parsable_range R,
  590. std::move_constructible F,
  591. typename Parser,
  592. typename GlobalState,
  593. typename ErrorHandler,
  594. typename SkipParser>
  595. requires std::ranges::viewable_range<R> &&
  596. std::regular_invocable<
  597. F &,
  598. range_attr_t<to_range_t<R>, Parser>> &&
  599. can_transform_replace_view<
  600. to_range_t<R>,
  601. utf_rvalue_shim<
  602. to_range_t<R>,
  603. std::remove_cvref_t<F>,
  604. range_attr_t<to_range_t<R>, Parser>>,
  605. Parser,
  606. GlobalState,
  607. ErrorHandler,
  608. SkipParser>
  609. [[nodiscard]] constexpr auto operator()(
  610. R && r,
  611. parser_interface<Parser, GlobalState, ErrorHandler> const &
  612. parser,
  613. parser_interface<SkipParser> const & skip,
  614. F && f,
  615. trace trace_mode = trace::off) const
  616. {
  617. return transform_replace_view(
  618. to_range<R>::call((R &&)r),
  619. parser,
  620. skip,
  621. utf_rvalue_shim<
  622. to_range_t<R>,
  623. std::remove_cvref_t<F>,
  624. range_attr_t<to_range_t<R>, Parser>>((F &&)f),
  625. trace_mode);
  626. }
  627. template<
  628. parsable_range R,
  629. std::move_constructible F,
  630. typename Parser,
  631. typename GlobalState,
  632. typename ErrorHandler>
  633. requires std::ranges::viewable_range<R> &&
  634. std::regular_invocable<
  635. F &,
  636. range_attr_t<to_range_t<R>, Parser>> &&
  637. can_transform_replace_view<
  638. to_range_t<R>,
  639. utf_rvalue_shim<
  640. to_range_t<R>,
  641. std::remove_cvref_t<F>,
  642. range_attr_t<to_range_t<R>, Parser>>,
  643. Parser,
  644. GlobalState,
  645. ErrorHandler,
  646. parser_interface<eps_parser<detail::phony>>>
  647. [[nodiscard]] constexpr auto operator()(
  648. R && r,
  649. parser_interface<Parser, GlobalState, ErrorHandler> const &
  650. parser,
  651. F && f,
  652. trace trace_mode = trace::off) const
  653. {
  654. return (*this)(
  655. (R &&)r,
  656. parser,
  657. parser_interface<eps_parser<detail::phony>>{},
  658. (F &&)f,
  659. trace_mode);
  660. }
  661. #else
  662. template<
  663. typename R,
  664. typename Parser,
  665. typename GlobalState,
  666. typename ErrorHandler,
  667. typename SkipParser,
  668. typename F = trace,
  669. typename Trace = trace,
  670. typename Enable = std::enable_if_t<is_parsable_range_v<R>>>
  671. [[nodiscard]] constexpr auto operator()(
  672. R && r,
  673. parser_interface<Parser, GlobalState, ErrorHandler> const &
  674. parser,
  675. SkipParser && skip,
  676. F && f = F{},
  677. Trace trace_mode = Trace{}) const
  678. {
  679. if constexpr (
  680. is_parser_iface<remove_cv_ref_t<SkipParser>> &&
  681. std::is_invocable_v<
  682. F &,
  683. range_attr_t<to_range_t<R>, Parser>> &&
  684. std::is_same_v<Trace, trace>) {
  685. // (r, parser, skip, f, trace) case
  686. return impl(
  687. to_range<R>::call((R &&) r),
  688. parser,
  689. skip,
  690. (F &&) f,
  691. trace_mode);
  692. } else if constexpr (
  693. std::is_invocable_v<
  694. SkipParser &,
  695. range_attr_t<to_range_t<R>, Parser>> &&
  696. std::is_same_v<remove_cv_ref_t<F>, trace> &&
  697. std::is_same_v<Trace, trace>) {
  698. // (r, parser, f, trace) case
  699. return impl(
  700. to_range<R>::call((R &&) r),
  701. parser,
  702. parser_interface<eps_parser<detail::phony>>{},
  703. (SkipParser &&) skip,
  704. f);
  705. } else {
  706. static_assert(
  707. sizeof(R) == 1 && false,
  708. "Only the signatures replace(R, parser, skip, "
  709. "replcement trace = trace::off) and replace(R, parser, "
  710. "f, trace = trace::off) are supported.");
  711. }
  712. }
  713. private:
  714. template<
  715. typename R,
  716. typename F,
  717. typename Parser,
  718. typename GlobalState,
  719. typename ErrorHandler,
  720. typename SkipParser>
  721. [[nodiscard]] constexpr auto impl(
  722. R && r,
  723. parser_interface<Parser, GlobalState, ErrorHandler> const &
  724. parser,
  725. parser_interface<SkipParser> const & skip,
  726. F && f,
  727. trace trace_mode = trace::off) const
  728. {
  729. return transform_replace_view(
  730. (R &&) r,
  731. parser,
  732. skip,
  733. utf_rvalue_shim<
  734. R,
  735. remove_cv_ref_t<F>,
  736. range_attr_t<R, Parser>>((F &&) f),
  737. trace_mode);
  738. }
  739. #endif
  740. };
  741. }
  742. /** A range adaptor object ([range.adaptor.object]). Given subexpressions
  743. `E` and `P`, `Q`, `R`, and 'S', each of the expressions `replace(E,
  744. P)`, `replace(E, P, Q)`. `replace(E, P, Q, R)`, and `replace(E, P, Q,
  745. R, S)` are expression-equivalent to `replace_view(E, P)`,
  746. `replace_view(E, P, Q)`, `replace_view(E, P, Q, R)`, `replace_view(E,
  747. P, Q, R, S)`, respectively. */
  748. inline constexpr detail::stl_interfaces::adaptor<
  749. detail::transform_replace_impl>
  750. transform_replace = detail::transform_replace_impl{};
  751. }
  752. #if BOOST_PARSER_USE_CONCEPTS
  753. template<
  754. typename V,
  755. typename F,
  756. typename Parser,
  757. typename GlobalState,
  758. typename ErrorHandler,
  759. typename SkipParser>
  760. constexpr bool
  761. std::ranges::enable_borrowed_range<boost::parser::transform_replace_view<
  762. V,
  763. F,
  764. Parser,
  765. GlobalState,
  766. ErrorHandler,
  767. SkipParser>> = std::ranges::enable_borrowed_range<V> &&
  768. (std::ranges::enable_borrowed_range<F> ||
  769. boost::parser::detail::tidy_func<F>);
  770. #endif
  771. #endif
  772. #endif