File indexing completed on 2025-09-17 08:40:35
0001 #ifndef BOOST_PARSER_SPLIT_HPP
0002 #define BOOST_PARSER_SPLIT_HPP
0003
0004 #include <boost/parser/search.hpp>
0005
0006
0007 namespace boost::parser {
0008
0009
0010
0011
0012 template<
0013 #if BOOST_PARSER_USE_CONCEPTS
0014 std::ranges::viewable_range V,
0015 #else
0016 typename V,
0017 #endif
0018 typename Parser,
0019 typename GlobalState,
0020 typename ErrorHandler,
0021 typename SkipParser>
0022 struct split_view
0023 : detail::stl_interfaces::view_interface<
0024 split_view<V, Parser, GlobalState, ErrorHandler, SkipParser>>
0025 {
0026 constexpr split_view() = default;
0027 constexpr split_view(
0028 V base,
0029 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0030 parser_interface<SkipParser> const & skip,
0031 trace trace_mode = trace::off) :
0032 base_(std::move(base)),
0033 parser_(parser),
0034 skip_(skip),
0035 trace_mode_(trace_mode)
0036 {}
0037 constexpr split_view(
0038 V base,
0039 parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0040 trace trace_mode = trace::off) :
0041 base_(std::move(base)),
0042 parser_(parser),
0043 skip_(),
0044 trace_mode_(trace_mode)
0045 {}
0046
0047 constexpr V base() const &
0048 #if BOOST_PARSER_USE_CONCEPTS
0049 requires std::copy_constructible<V>
0050 #endif
0051 {
0052 return base_;
0053 }
0054 constexpr V base() && { return std::move(base_); }
0055
0056 constexpr auto begin() { return iterator<false>{this}; }
0057 constexpr auto end() { return sentinel<false>{}; }
0058
0059 constexpr auto begin() const
0060 #if BOOST_PARSER_USE_CONCEPTS
0061 requires std::ranges::range<const V>
0062 #endif
0063 {
0064 return iterator<true>{this};
0065 }
0066 constexpr auto end() const
0067 #if BOOST_PARSER_USE_CONCEPTS
0068 requires std::ranges::range<const V>
0069 #endif
0070 {
0071 return sentinel<true>{};
0072 }
0073
0074 template<bool Const>
0075 struct sentinel
0076 {};
0077
0078 template<bool Const>
0079 struct iterator
0080 : detail::stl_interfaces::proxy_iterator_interface<
0081 iterator<Const>,
0082 std::forward_iterator_tag,
0083 BOOST_PARSER_SUBRANGE<
0084 detail::iterator_t<detail::maybe_const<Const, V>>>>
0085 {
0086 using I = detail::iterator_t<detail::maybe_const<Const, V>>;
0087 using S = detail::sentinel_t<detail::maybe_const<Const, V>>;
0088
0089 constexpr iterator() = default;
0090 constexpr iterator(
0091 detail::maybe_const<Const, split_view> * parent) :
0092 parent_(parent),
0093 r_(parent_->base_.begin(), parent_->base_.end()),
0094 curr_(r_.begin(), r_.begin()),
0095 next_it_(r_.begin()),
0096 next_follows_match_(false)
0097 {
0098 ++*this;
0099 }
0100
0101 constexpr iterator & operator++()
0102 {
0103 if (next_it_ == r_.end() && next_follows_match_) {
0104 curr_ = BOOST_PARSER_SUBRANGE(next_it_, next_it_);
0105 next_follows_match_ = false;
0106 return *this;
0107 }
0108 r_ = BOOST_PARSER_SUBRANGE<I, S>(next_it_, r_.end());
0109 auto const curr_match = parser::search(
0110 r_, parent_->parser_, parent_->skip_, parent_->trace_mode_);
0111 curr_ = BOOST_PARSER_SUBRANGE(next_it_, curr_match.begin());
0112 next_it_ = curr_match.end();
0113 next_follows_match_ = !curr_match.empty();
0114 return *this;
0115 }
0116
0117 constexpr BOOST_PARSER_SUBRANGE<I> operator*() const
0118 {
0119 return curr_;
0120 }
0121
0122 friend constexpr bool operator==(iterator lhs, iterator rhs)
0123 {
0124 return lhs.r_.begin() == rhs.r_.begin();
0125 }
0126 friend constexpr bool operator==(iterator it, sentinel<Const>)
0127 {
0128 return it.r_.begin() == it.r_.end();
0129 }
0130
0131 using base_type = detail::stl_interfaces::proxy_iterator_interface<
0132 iterator,
0133 std::forward_iterator_tag,
0134 BOOST_PARSER_SUBRANGE<I>>;
0135 using base_type::operator++;
0136
0137 private:
0138 detail::maybe_const<Const, split_view> * parent_;
0139 BOOST_PARSER_SUBRANGE<I, S> r_;
0140 BOOST_PARSER_SUBRANGE<I> curr_;
0141 I next_it_;
0142 bool next_follows_match_;
0143 };
0144
0145 template<bool Const>
0146 friend struct iterator;
0147
0148 private:
0149 V base_;
0150 parser_interface<Parser, GlobalState, ErrorHandler> parser_;
0151 parser_interface<SkipParser> skip_;
0152 trace trace_mode_;
0153 };
0154
0155
0156 template<
0157 typename V,
0158 typename Parser,
0159 typename GlobalState,
0160 typename ErrorHandler,
0161 typename SkipParser>
0162 split_view(
0163 V &&,
0164 parser_interface<Parser, GlobalState, ErrorHandler>,
0165 parser_interface<SkipParser>,
0166 trace)
0167 -> split_view<
0168 detail::text::detail::all_t<V>,
0169 Parser,
0170 GlobalState,
0171 ErrorHandler,
0172 SkipParser>;
0173
0174 template<
0175 typename V,
0176 typename Parser,
0177 typename GlobalState,
0178 typename ErrorHandler,
0179 typename SkipParser>
0180 split_view(
0181 V &&,
0182 parser_interface<Parser, GlobalState, ErrorHandler>,
0183 parser_interface<SkipParser>)
0184 -> split_view<
0185 detail::text::detail::all_t<V>,
0186 Parser,
0187 GlobalState,
0188 ErrorHandler,
0189 SkipParser>;
0190
0191 template<
0192 typename V,
0193 typename Parser,
0194 typename GlobalState,
0195 typename ErrorHandler>
0196 split_view(
0197 V &&, parser_interface<Parser, GlobalState, ErrorHandler>, trace)
0198 -> split_view<
0199 detail::text::detail::all_t<V>,
0200 Parser,
0201 GlobalState,
0202 ErrorHandler,
0203 parser_interface<eps_parser<detail::phony>>>;
0204
0205 template<
0206 typename V,
0207 typename Parser,
0208 typename GlobalState,
0209 typename ErrorHandler>
0210 split_view(V &&, parser_interface<Parser, GlobalState, ErrorHandler>)
0211 -> split_view<
0212 detail::text::detail::all_t<V>,
0213 Parser,
0214 GlobalState,
0215 ErrorHandler,
0216 parser_interface<eps_parser<detail::phony>>>;
0217
0218 namespace detail {
0219 template<
0220 typename V,
0221 typename Parser,
0222 typename GlobalState,
0223 typename ErrorHandler,
0224 typename SkipParser>
0225 using split_view_expr = decltype(split_view<
0226 V,
0227 Parser,
0228 GlobalState,
0229 ErrorHandler,
0230 SkipParser>(
0231 std::declval<V>(),
0232 std::declval<
0233 parser_interface<Parser, GlobalState, ErrorHandler> const &>(),
0234 std::declval<parser_interface<SkipParser> const &>(),
0235 trace::on));
0236
0237 template<
0238 typename V,
0239 typename Parser,
0240 typename GlobalState,
0241 typename ErrorHandler,
0242 typename SkipParser>
0243 constexpr bool can_split_view = is_detected_v<
0244 split_view_expr,
0245 V,
0246 Parser,
0247 GlobalState,
0248 ErrorHandler,
0249 SkipParser>;
0250
0251 struct split_impl
0252 {
0253 #if BOOST_PARSER_USE_CONCEPTS
0254
0255 template<
0256 parsable_range R,
0257 typename Parser,
0258 typename GlobalState,
0259 typename ErrorHandler,
0260 typename SkipParser>
0261 requires(std::ranges::viewable_range<R>) && can_split_view<
0262 to_range_t<R>,
0263 Parser,
0264 GlobalState,
0265 ErrorHandler,
0266 SkipParser>
0267 [[nodiscard]] constexpr auto operator()(
0268 R && r,
0269 parser_interface<Parser, GlobalState, ErrorHandler> const &
0270 parser,
0271 parser_interface<SkipParser> const & skip,
0272 trace trace_mode = trace::off) const
0273 {
0274 return split_view(
0275 to_range<R>::call((R &&)r), parser, skip, trace_mode);
0276 }
0277
0278 template<
0279 parsable_range R,
0280 typename Parser,
0281 typename GlobalState,
0282 typename ErrorHandler>
0283 requires(std::ranges::viewable_range<R>) &&
0284 can_split_view<
0285 to_range_t<R>,
0286 Parser,
0287 GlobalState,
0288 ErrorHandler,
0289 parser_interface<eps_parser<detail::phony>>>
0290 [[nodiscard]] constexpr auto operator()(
0291 R && r,
0292 parser_interface<Parser, GlobalState, ErrorHandler> const &
0293 parser,
0294 trace trace_mode = trace::off) const
0295 {
0296 return (*this)(
0297 (R &&)r,
0298 parser,
0299 parser_interface<eps_parser<detail::phony>>{},
0300 trace_mode);
0301 }
0302
0303 #else
0304
0305 template<
0306 typename R,
0307 typename Parser,
0308 typename GlobalState,
0309 typename ErrorHandler,
0310 typename SkipParser =
0311 parser_interface<eps_parser<detail::phony>>,
0312 typename Trace = trace,
0313 typename Enable = std::enable_if_t<is_parsable_range_v<R>>>
0314 [[nodiscard]] constexpr auto operator()(
0315 R && r,
0316 parser_interface<Parser, GlobalState, ErrorHandler> const &
0317 parser,
0318 SkipParser const & skip = SkipParser{},
0319 Trace trace_mode = Trace{}) const
0320 {
0321 if constexpr (
0322 std::
0323 is_same_v<detail::remove_cv_ref_t<SkipParser>, trace> &&
0324 std::is_same_v<Trace, trace>) {
0325
0326 return impl(
0327 (R &&) r,
0328 parser,
0329 parser_interface<eps_parser<detail::phony>>{},
0330 skip);
0331 } else if constexpr (
0332 detail::is_parser_iface<SkipParser> &&
0333 std::is_same_v<Trace, trace>) {
0334
0335 return impl((R &&) r, parser, skip, trace_mode);
0336 } else {
0337 static_assert(
0338 sizeof(R) == 1 && false,
0339 "Only the signatures split(R, parser, skip, trace "
0340 "= trace::off) and split(R, parser, trace = "
0341 "trace::off) are supported.");
0342 }
0343 }
0344
0345 private:
0346 template<
0347 typename R,
0348 typename Parser,
0349 typename GlobalState,
0350 typename ErrorHandler,
0351 typename SkipParser>
0352 [[nodiscard]] constexpr auto impl(
0353 R && r,
0354 parser_interface<Parser, GlobalState, ErrorHandler> const &
0355 parser,
0356 parser_interface<SkipParser> const & skip,
0357 trace trace_mode = trace::off) const
0358 {
0359 return split_view(
0360 to_range<R>::call((R &&) r), parser, skip, trace_mode);
0361 }
0362
0363 #endif
0364 };
0365 }
0366
0367
0368
0369
0370
0371
0372 inline constexpr detail::stl_interfaces::adaptor<detail::split_impl>
0373 split = detail::split_impl{};
0374
0375 }
0376
0377 #if BOOST_PARSER_USE_CONCEPTS
0378 template<
0379 typename V,
0380 typename Parser,
0381 typename GlobalState,
0382 typename ErrorHandler,
0383 typename SkipParser>
0384 constexpr bool std::ranges::enable_borrowed_range<
0385 boost::parser::
0386 split_view<V, Parser, GlobalState, ErrorHandler, SkipParser>> =
0387 std::ranges::enable_borrowed_range<V>;
0388 #endif
0389
0390 #endif