split.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. #ifndef BOOST_PARSER_SPLIT_HPP
  2. #define BOOST_PARSER_SPLIT_HPP
  3. #include <boost/parser/search.hpp>
  4. namespace boost::parser {
  5. /** Produces a sequence of subranges of the underlying sequence of type
  6. `V`. the underlying sequence is split into subranges delimited by
  7. matches of the given parser, possibly using a given skip-parser. */
  8. template<
  9. #if BOOST_PARSER_USE_CONCEPTS
  10. std::ranges::viewable_range V,
  11. #else
  12. typename V,
  13. #endif
  14. typename Parser,
  15. typename GlobalState,
  16. typename ErrorHandler,
  17. typename SkipParser>
  18. struct split_view
  19. : detail::stl_interfaces::view_interface<
  20. split_view<V, Parser, GlobalState, ErrorHandler, SkipParser>>
  21. {
  22. constexpr split_view() = default;
  23. constexpr split_view(
  24. V base,
  25. parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
  26. parser_interface<SkipParser> const & skip,
  27. trace trace_mode = trace::off) :
  28. base_(std::move(base)),
  29. parser_(parser),
  30. skip_(skip),
  31. trace_mode_(trace_mode)
  32. {}
  33. constexpr split_view(
  34. V base,
  35. parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
  36. trace trace_mode = trace::off) :
  37. base_(std::move(base)),
  38. parser_(parser),
  39. skip_(),
  40. trace_mode_(trace_mode)
  41. {}
  42. constexpr V base() const &
  43. #if BOOST_PARSER_USE_CONCEPTS
  44. requires std::copy_constructible<V>
  45. #endif
  46. {
  47. return base_;
  48. }
  49. constexpr V base() && { return std::move(base_); }
  50. constexpr auto begin() { return iterator<false>{this}; }
  51. constexpr auto end() { return sentinel<false>{}; }
  52. constexpr auto begin() const
  53. #if BOOST_PARSER_USE_CONCEPTS
  54. requires std::ranges::range<const V>
  55. #endif
  56. {
  57. return iterator<true>{this};
  58. }
  59. constexpr auto end() const
  60. #if BOOST_PARSER_USE_CONCEPTS
  61. requires std::ranges::range<const V>
  62. #endif
  63. {
  64. return sentinel<true>{};
  65. }
  66. template<bool Const>
  67. struct sentinel
  68. {};
  69. template<bool Const>
  70. struct iterator
  71. : detail::stl_interfaces::proxy_iterator_interface<
  72. iterator<Const>,
  73. std::forward_iterator_tag,
  74. BOOST_PARSER_SUBRANGE<
  75. detail::iterator_t<detail::maybe_const<Const, V>>>>
  76. {
  77. using I = detail::iterator_t<detail::maybe_const<Const, V>>;
  78. using S = detail::sentinel_t<detail::maybe_const<Const, V>>;
  79. constexpr iterator() = default;
  80. constexpr iterator(
  81. detail::maybe_const<Const, split_view> * parent) :
  82. parent_(parent),
  83. r_(parent_->base_.begin(), parent_->base_.end()),
  84. curr_(r_.begin(), r_.begin()),
  85. next_it_(r_.begin()),
  86. next_follows_match_(false)
  87. {
  88. ++*this;
  89. }
  90. constexpr iterator & operator++()
  91. {
  92. if (next_it_ == r_.end() && next_follows_match_) {
  93. curr_ = BOOST_PARSER_SUBRANGE(next_it_, next_it_);
  94. next_follows_match_ = false;
  95. return *this;
  96. }
  97. r_ = BOOST_PARSER_SUBRANGE<I, S>(next_it_, r_.end());
  98. auto const curr_match = parser::search(
  99. r_, parent_->parser_, parent_->skip_, parent_->trace_mode_);
  100. curr_ = BOOST_PARSER_SUBRANGE(next_it_, curr_match.begin());
  101. next_it_ = curr_match.end();
  102. next_follows_match_ = !curr_match.empty();
  103. return *this;
  104. }
  105. constexpr BOOST_PARSER_SUBRANGE<I> operator*() const
  106. {
  107. return curr_;
  108. }
  109. friend constexpr bool operator==(iterator lhs, iterator rhs)
  110. {
  111. return lhs.r_.begin() == rhs.r_.begin();
  112. }
  113. friend constexpr bool operator==(iterator it, sentinel<Const>)
  114. {
  115. return it.r_.begin() == it.r_.end();
  116. }
  117. using base_type = detail::stl_interfaces::proxy_iterator_interface<
  118. iterator,
  119. std::forward_iterator_tag,
  120. BOOST_PARSER_SUBRANGE<I>>;
  121. using base_type::operator++;
  122. private:
  123. detail::maybe_const<Const, split_view> * parent_;
  124. BOOST_PARSER_SUBRANGE<I, S> r_;
  125. BOOST_PARSER_SUBRANGE<I> curr_;
  126. I next_it_;
  127. bool next_follows_match_;
  128. };
  129. template<bool Const>
  130. friend struct iterator;
  131. private:
  132. V base_;
  133. parser_interface<Parser, GlobalState, ErrorHandler> parser_;
  134. parser_interface<SkipParser> skip_;
  135. trace trace_mode_;
  136. };
  137. // deduction guides
  138. template<
  139. typename V,
  140. typename Parser,
  141. typename GlobalState,
  142. typename ErrorHandler,
  143. typename SkipParser>
  144. split_view(
  145. V &&,
  146. parser_interface<Parser, GlobalState, ErrorHandler>,
  147. parser_interface<SkipParser>,
  148. trace)
  149. -> split_view<
  150. detail::text::detail::all_t<V>,
  151. Parser,
  152. GlobalState,
  153. ErrorHandler,
  154. SkipParser>;
  155. template<
  156. typename V,
  157. typename Parser,
  158. typename GlobalState,
  159. typename ErrorHandler,
  160. typename SkipParser>
  161. split_view(
  162. V &&,
  163. parser_interface<Parser, GlobalState, ErrorHandler>,
  164. parser_interface<SkipParser>)
  165. -> split_view<
  166. detail::text::detail::all_t<V>,
  167. Parser,
  168. GlobalState,
  169. ErrorHandler,
  170. SkipParser>;
  171. template<
  172. typename V,
  173. typename Parser,
  174. typename GlobalState,
  175. typename ErrorHandler>
  176. split_view(
  177. V &&, parser_interface<Parser, GlobalState, ErrorHandler>, trace)
  178. -> split_view<
  179. detail::text::detail::all_t<V>,
  180. Parser,
  181. GlobalState,
  182. ErrorHandler,
  183. parser_interface<eps_parser<detail::phony>>>;
  184. template<
  185. typename V,
  186. typename Parser,
  187. typename GlobalState,
  188. typename ErrorHandler>
  189. split_view(V &&, parser_interface<Parser, GlobalState, ErrorHandler>)
  190. -> split_view<
  191. detail::text::detail::all_t<V>,
  192. Parser,
  193. GlobalState,
  194. ErrorHandler,
  195. parser_interface<eps_parser<detail::phony>>>;
  196. namespace detail {
  197. template<
  198. typename V,
  199. typename Parser,
  200. typename GlobalState,
  201. typename ErrorHandler,
  202. typename SkipParser>
  203. using split_view_expr = decltype(split_view<
  204. V,
  205. Parser,
  206. GlobalState,
  207. ErrorHandler,
  208. SkipParser>(
  209. std::declval<V>(),
  210. std::declval<
  211. parser_interface<Parser, GlobalState, ErrorHandler> const &>(),
  212. std::declval<parser_interface<SkipParser> const &>(),
  213. trace::on));
  214. template<
  215. typename V,
  216. typename Parser,
  217. typename GlobalState,
  218. typename ErrorHandler,
  219. typename SkipParser>
  220. constexpr bool can_split_view = is_detected_v<
  221. split_view_expr,
  222. V,
  223. Parser,
  224. GlobalState,
  225. ErrorHandler,
  226. SkipParser>;
  227. struct split_impl
  228. {
  229. #if BOOST_PARSER_USE_CONCEPTS
  230. template<
  231. parsable_range R,
  232. typename Parser,
  233. typename GlobalState,
  234. typename ErrorHandler,
  235. typename SkipParser>
  236. requires(std::ranges::viewable_range<R>) && can_split_view<
  237. to_range_t<R>,
  238. Parser,
  239. GlobalState,
  240. ErrorHandler,
  241. SkipParser>
  242. [[nodiscard]] constexpr auto operator()(
  243. R && r,
  244. parser_interface<Parser, GlobalState, ErrorHandler> const &
  245. parser,
  246. parser_interface<SkipParser> const & skip,
  247. trace trace_mode = trace::off) const
  248. {
  249. return split_view(
  250. to_range<R>::call((R &&)r), parser, skip, trace_mode);
  251. }
  252. template<
  253. parsable_range R,
  254. typename Parser,
  255. typename GlobalState,
  256. typename ErrorHandler>
  257. requires(std::ranges::viewable_range<R>) &&
  258. can_split_view<
  259. to_range_t<R>,
  260. Parser,
  261. GlobalState,
  262. ErrorHandler,
  263. parser_interface<eps_parser<detail::phony>>>
  264. [[nodiscard]] constexpr auto operator()(
  265. R && r,
  266. parser_interface<Parser, GlobalState, ErrorHandler> const &
  267. parser,
  268. trace trace_mode = trace::off) const
  269. {
  270. return (*this)(
  271. (R &&)r,
  272. parser,
  273. parser_interface<eps_parser<detail::phony>>{},
  274. trace_mode);
  275. }
  276. #else
  277. template<
  278. typename R,
  279. typename Parser,
  280. typename GlobalState,
  281. typename ErrorHandler,
  282. typename SkipParser =
  283. parser_interface<eps_parser<detail::phony>>,
  284. typename Trace = trace,
  285. typename Enable = std::enable_if_t<is_parsable_range_v<R>>>
  286. [[nodiscard]] constexpr auto operator()(
  287. R && r,
  288. parser_interface<Parser, GlobalState, ErrorHandler> const &
  289. parser,
  290. SkipParser const & skip = SkipParser{},
  291. Trace trace_mode = Trace{}) const
  292. {
  293. if constexpr (
  294. std::
  295. is_same_v<detail::remove_cv_ref_t<SkipParser>, trace> &&
  296. std::is_same_v<Trace, trace>) {
  297. // (r, parser, trace) case
  298. return impl(
  299. (R &&) r,
  300. parser,
  301. parser_interface<eps_parser<detail::phony>>{},
  302. skip);
  303. } else if constexpr (
  304. detail::is_parser_iface<SkipParser> &&
  305. std::is_same_v<Trace, trace>) {
  306. // (r, parser, skip, trace) case
  307. return impl((R &&) r, parser, skip, trace_mode);
  308. } else {
  309. static_assert(
  310. sizeof(R) == 1 && false,
  311. "Only the signatures split(R, parser, skip, trace "
  312. "= trace::off) and split(R, parser, trace = "
  313. "trace::off) are supported.");
  314. }
  315. }
  316. private:
  317. template<
  318. typename R,
  319. typename Parser,
  320. typename GlobalState,
  321. typename ErrorHandler,
  322. typename SkipParser>
  323. [[nodiscard]] constexpr auto impl(
  324. R && r,
  325. parser_interface<Parser, GlobalState, ErrorHandler> const &
  326. parser,
  327. parser_interface<SkipParser> const & skip,
  328. trace trace_mode = trace::off) const
  329. {
  330. return split_view(
  331. to_range<R>::call((R &&) r), parser, skip, trace_mode);
  332. }
  333. #endif
  334. };
  335. }
  336. /** A range adaptor object ([range.adaptor.object]). Given subexpressions
  337. `E` and `P`, `Q`, and `R`, each of the expressions `split(E, P)`,
  338. `split(E, P, Q)`, and `split(E, P, Q, R)` are
  339. expression-equivalent to `split_view(E, P)`, `split_view(E,
  340. P, Q)`, and `split_view(E, P, Q, R)`, respectively. */
  341. inline constexpr detail::stl_interfaces::adaptor<detail::split_impl>
  342. split = detail::split_impl{};
  343. }
  344. #if BOOST_PARSER_USE_CONCEPTS
  345. template<
  346. typename V,
  347. typename Parser,
  348. typename GlobalState,
  349. typename ErrorHandler,
  350. typename SkipParser>
  351. constexpr bool std::ranges::enable_borrowed_range<
  352. boost::parser::
  353. split_view<V, Parser, GlobalState, ErrorHandler, SkipParser>> =
  354. std::ranges::enable_borrowed_range<V>;
  355. #endif
  356. #endif