| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- #ifndef BOOST_PARSER_SPLIT_HPP
- #define BOOST_PARSER_SPLIT_HPP
- #include <boost/parser/search.hpp>
- namespace boost::parser {
- /** Produces a sequence of subranges of the underlying sequence of type
- `V`. the underlying sequence is split into subranges delimited by
- matches of the given parser, possibly using a given skip-parser. */
- template<
- #if BOOST_PARSER_USE_CONCEPTS
- std::ranges::viewable_range V,
- #else
- typename V,
- #endif
- typename Parser,
- typename GlobalState,
- typename ErrorHandler,
- typename SkipParser>
- struct split_view
- : detail::stl_interfaces::view_interface<
- split_view<V, Parser, GlobalState, ErrorHandler, SkipParser>>
- {
- constexpr split_view() = default;
- constexpr split_view(
- V base,
- parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
- parser_interface<SkipParser> const & skip,
- trace trace_mode = trace::off) :
- base_(std::move(base)),
- parser_(parser),
- skip_(skip),
- trace_mode_(trace_mode)
- {}
- constexpr split_view(
- V base,
- parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
- trace trace_mode = trace::off) :
- base_(std::move(base)),
- parser_(parser),
- skip_(),
- trace_mode_(trace_mode)
- {}
- constexpr V base() const &
- #if BOOST_PARSER_USE_CONCEPTS
- requires std::copy_constructible<V>
- #endif
- {
- return base_;
- }
- constexpr V base() && { return std::move(base_); }
- constexpr auto begin() { return iterator<false>{this}; }
- constexpr auto end() { return sentinel<false>{}; }
- constexpr auto begin() const
- #if BOOST_PARSER_USE_CONCEPTS
- requires std::ranges::range<const V>
- #endif
- {
- return iterator<true>{this};
- }
- constexpr auto end() const
- #if BOOST_PARSER_USE_CONCEPTS
- requires std::ranges::range<const V>
- #endif
- {
- return sentinel<true>{};
- }
- template<bool Const>
- struct sentinel
- {};
- template<bool Const>
- struct iterator
- : detail::stl_interfaces::proxy_iterator_interface<
- iterator<Const>,
- std::forward_iterator_tag,
- BOOST_PARSER_SUBRANGE<
- detail::iterator_t<detail::maybe_const<Const, V>>>>
- {
- using I = detail::iterator_t<detail::maybe_const<Const, V>>;
- using S = detail::sentinel_t<detail::maybe_const<Const, V>>;
- constexpr iterator() = default;
- constexpr iterator(
- detail::maybe_const<Const, split_view> * parent) :
- parent_(parent),
- r_(parent_->base_.begin(), parent_->base_.end()),
- curr_(r_.begin(), r_.begin()),
- next_it_(r_.begin()),
- next_follows_match_(false)
- {
- ++*this;
- }
- constexpr iterator & operator++()
- {
- if (next_it_ == r_.end() && next_follows_match_) {
- curr_ = BOOST_PARSER_SUBRANGE(next_it_, next_it_);
- next_follows_match_ = false;
- return *this;
- }
- r_ = BOOST_PARSER_SUBRANGE<I, S>(next_it_, r_.end());
- auto const curr_match = parser::search(
- r_, parent_->parser_, parent_->skip_, parent_->trace_mode_);
- curr_ = BOOST_PARSER_SUBRANGE(next_it_, curr_match.begin());
- next_it_ = curr_match.end();
- next_follows_match_ = !curr_match.empty();
- return *this;
- }
- constexpr BOOST_PARSER_SUBRANGE<I> operator*() const
- {
- return curr_;
- }
- friend constexpr bool operator==(iterator lhs, iterator rhs)
- {
- return lhs.r_.begin() == rhs.r_.begin();
- }
- friend constexpr bool operator==(iterator it, sentinel<Const>)
- {
- return it.r_.begin() == it.r_.end();
- }
- using base_type = detail::stl_interfaces::proxy_iterator_interface<
- iterator,
- std::forward_iterator_tag,
- BOOST_PARSER_SUBRANGE<I>>;
- using base_type::operator++;
- private:
- detail::maybe_const<Const, split_view> * parent_;
- BOOST_PARSER_SUBRANGE<I, S> r_;
- BOOST_PARSER_SUBRANGE<I> curr_;
- I next_it_;
- bool next_follows_match_;
- };
- template<bool Const>
- friend struct iterator;
- private:
- V base_;
- parser_interface<Parser, GlobalState, ErrorHandler> parser_;
- parser_interface<SkipParser> skip_;
- trace trace_mode_;
- };
- // deduction guides
- template<
- typename V,
- typename Parser,
- typename GlobalState,
- typename ErrorHandler,
- typename SkipParser>
- split_view(
- V &&,
- parser_interface<Parser, GlobalState, ErrorHandler>,
- parser_interface<SkipParser>,
- trace)
- -> split_view<
- detail::text::detail::all_t<V>,
- Parser,
- GlobalState,
- ErrorHandler,
- SkipParser>;
- template<
- typename V,
- typename Parser,
- typename GlobalState,
- typename ErrorHandler,
- typename SkipParser>
- split_view(
- V &&,
- parser_interface<Parser, GlobalState, ErrorHandler>,
- parser_interface<SkipParser>)
- -> split_view<
- detail::text::detail::all_t<V>,
- Parser,
- GlobalState,
- ErrorHandler,
- SkipParser>;
- template<
- typename V,
- typename Parser,
- typename GlobalState,
- typename ErrorHandler>
- split_view(
- V &&, parser_interface<Parser, GlobalState, ErrorHandler>, trace)
- -> split_view<
- detail::text::detail::all_t<V>,
- Parser,
- GlobalState,
- ErrorHandler,
- parser_interface<eps_parser<detail::phony>>>;
- template<
- typename V,
- typename Parser,
- typename GlobalState,
- typename ErrorHandler>
- split_view(V &&, parser_interface<Parser, GlobalState, ErrorHandler>)
- -> split_view<
- detail::text::detail::all_t<V>,
- Parser,
- GlobalState,
- ErrorHandler,
- parser_interface<eps_parser<detail::phony>>>;
- namespace detail {
- template<
- typename V,
- typename Parser,
- typename GlobalState,
- typename ErrorHandler,
- typename SkipParser>
- using split_view_expr = decltype(split_view<
- V,
- Parser,
- GlobalState,
- ErrorHandler,
- SkipParser>(
- std::declval<V>(),
- std::declval<
- parser_interface<Parser, GlobalState, ErrorHandler> const &>(),
- std::declval<parser_interface<SkipParser> const &>(),
- trace::on));
- template<
- typename V,
- typename Parser,
- typename GlobalState,
- typename ErrorHandler,
- typename SkipParser>
- constexpr bool can_split_view = is_detected_v<
- split_view_expr,
- V,
- Parser,
- GlobalState,
- ErrorHandler,
- SkipParser>;
- struct split_impl
- {
- #if BOOST_PARSER_USE_CONCEPTS
- template<
- parsable_range R,
- typename Parser,
- typename GlobalState,
- typename ErrorHandler,
- typename SkipParser>
- requires(std::ranges::viewable_range<R>) && can_split_view<
- to_range_t<R>,
- Parser,
- GlobalState,
- ErrorHandler,
- SkipParser>
- [[nodiscard]] constexpr auto operator()(
- R && r,
- parser_interface<Parser, GlobalState, ErrorHandler> const &
- parser,
- parser_interface<SkipParser> const & skip,
- trace trace_mode = trace::off) const
- {
- return split_view(
- to_range<R>::call((R &&)r), parser, skip, trace_mode);
- }
- template<
- parsable_range R,
- typename Parser,
- typename GlobalState,
- typename ErrorHandler>
- requires(std::ranges::viewable_range<R>) &&
- can_split_view<
- to_range_t<R>,
- Parser,
- GlobalState,
- ErrorHandler,
- parser_interface<eps_parser<detail::phony>>>
- [[nodiscard]] constexpr auto operator()(
- R && r,
- parser_interface<Parser, GlobalState, ErrorHandler> const &
- parser,
- trace trace_mode = trace::off) const
- {
- return (*this)(
- (R &&)r,
- parser,
- parser_interface<eps_parser<detail::phony>>{},
- trace_mode);
- }
- #else
- template<
- typename R,
- typename Parser,
- typename GlobalState,
- typename ErrorHandler,
- typename SkipParser =
- parser_interface<eps_parser<detail::phony>>,
- typename Trace = trace,
- typename Enable = std::enable_if_t<is_parsable_range_v<R>>>
- [[nodiscard]] constexpr auto operator()(
- R && r,
- parser_interface<Parser, GlobalState, ErrorHandler> const &
- parser,
- SkipParser const & skip = SkipParser{},
- Trace trace_mode = Trace{}) const
- {
- if constexpr (
- std::
- is_same_v<detail::remove_cv_ref_t<SkipParser>, trace> &&
- std::is_same_v<Trace, trace>) {
- // (r, parser, trace) case
- return impl(
- (R &&) r,
- parser,
- parser_interface<eps_parser<detail::phony>>{},
- skip);
- } else if constexpr (
- detail::is_parser_iface<SkipParser> &&
- std::is_same_v<Trace, trace>) {
- // (r, parser, skip, trace) case
- return impl((R &&) r, parser, skip, trace_mode);
- } else {
- static_assert(
- sizeof(R) == 1 && false,
- "Only the signatures split(R, parser, skip, trace "
- "= trace::off) and split(R, parser, trace = "
- "trace::off) are supported.");
- }
- }
- private:
- template<
- typename R,
- typename Parser,
- typename GlobalState,
- typename ErrorHandler,
- typename SkipParser>
- [[nodiscard]] constexpr auto impl(
- R && r,
- parser_interface<Parser, GlobalState, ErrorHandler> const &
- parser,
- parser_interface<SkipParser> const & skip,
- trace trace_mode = trace::off) const
- {
- return split_view(
- to_range<R>::call((R &&) r), parser, skip, trace_mode);
- }
- #endif
- };
- }
- /** A range adaptor object ([range.adaptor.object]). Given subexpressions
- `E` and `P`, `Q`, and `R`, each of the expressions `split(E, P)`,
- `split(E, P, Q)`, and `split(E, P, Q, R)` are
- expression-equivalent to `split_view(E, P)`, `split_view(E,
- P, Q)`, and `split_view(E, P, Q, R)`, respectively. */
- inline constexpr detail::stl_interfaces::adaptor<detail::split_impl>
- split = detail::split_impl{};
- }
- #if BOOST_PARSER_USE_CONCEPTS
- template<
- typename V,
- typename Parser,
- typename GlobalState,
- typename ErrorHandler,
- typename SkipParser>
- constexpr bool std::ranges::enable_borrowed_range<
- boost::parser::
- split_view<V, Parser, GlobalState, ErrorHandler, SkipParser>> =
- std::ranges::enable_borrowed_range<V>;
- #endif
- #endif
|