Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:40:35

0001 #ifndef BOOST_PARSER_SEARCH_HPP
0002 #define BOOST_PARSER_SEARCH_HPP
0003 
0004 #include <boost/parser/parser.hpp>
0005 #include <boost/parser/transcode_view.hpp>
0006 
0007 #include <cstring>
0008 
0009 
0010 namespace boost::parser {
0011 
0012     namespace detail {
0013         template<bool Const, typename T>
0014         using maybe_const = std::conditional_t<Const, const T, T>;
0015 
0016         inline constexpr text::format no_format = text::format::none;
0017 
0018         template<text::format Format = text::format::utf8>
0019         constexpr auto as_utf =
0020             text::detail::as_utf_impl<text::utf8_view, text::format::utf8>{};
0021         template<>
0022         constexpr auto as_utf<text::format::utf16> =
0023             text::detail::as_utf_impl<text::utf16_view, text::format::utf16>{};
0024         template<>
0025         constexpr auto as_utf<text::format::utf32> =
0026             text::detail::as_utf_impl<text::utf32_view, text::format::utf32>{};
0027 
0028         template<
0029             typename R_,
0030             bool ToCommonRange = false,
0031             text::format OtherRangeFormat = no_format,
0032             bool = std::is_same_v<sentinel_t<remove_cv_ref_t<R_>>,
0033                                   null_sentinel_t> ||
0034                    text::detail::is_bounded_array_v<remove_cv_ref_t<R_>>>
0035         struct to_range
0036         {
0037             template<typename R>
0038             static constexpr auto call(R && r)
0039             {
0040                 static_assert(std::is_same_v<R, R_>);
0041                 using T = remove_cv_ref_t<R>;
0042                 if constexpr (std::is_same_v<sentinel_t<T>, null_sentinel_t>) {
0043                     auto plus_strlen = [](auto * ptr) {
0044                         while (*ptr) {
0045                             ++ptr;
0046                         }
0047                         return ptr;
0048                     };
0049                     auto const first = r.begin();
0050                     if constexpr (OtherRangeFormat == no_format) {
0051                         if constexpr (ToCommonRange) {
0052                             return BOOST_PARSER_SUBRANGE(
0053                                 first, plus_strlen(first));
0054                         } else {
0055                             return (R &&) r;
0056                         }
0057                     } else {
0058                         if constexpr (ToCommonRange) {
0059                             return BOOST_PARSER_SUBRANGE(
0060                                 first, plus_strlen(first)) |
0061                                    as_utf<OtherRangeFormat>;
0062                         } else {
0063                             return (R &&) r | as_utf<OtherRangeFormat>;
0064                         }
0065                     }
0066                 } else if constexpr (text::detail::is_bounded_array_v<T>) {
0067                     auto const first = std::begin(r);
0068                     auto last = std::end(r);
0069                     constexpr auto n = std::extent_v<T>;
0070                     if (n && !r[n - 1])
0071                         --last;
0072                     if constexpr (OtherRangeFormat == no_format) {
0073                         return BOOST_PARSER_SUBRANGE(first, last);
0074                     } else {
0075                         return BOOST_PARSER_SUBRANGE(first, last) |
0076                                as_utf<OtherRangeFormat>;
0077                     }
0078                 } else {
0079                     return (R &&) r | as_utf<OtherRangeFormat>;
0080                 }
0081             }
0082         };
0083 
0084         template<typename R_, bool ToCommonRange>
0085         struct to_range<R_, ToCommonRange, no_format, false>
0086         {
0087             template<typename R>
0088             static constexpr R && call(R && r)
0089             {
0090                 return (R &&) r;
0091             }
0092         };
0093 
0094         template<typename R>
0095         using to_range_t = decltype(to_range<R>::call(std::declval<R>()));
0096 
0097         struct phony
0098         {};
0099 
0100         template<
0101             typename R,
0102             typename Parser,
0103             typename GlobalState,
0104             typename ErrorHandler,
0105             typename SkipParser>
0106         auto search_impl(
0107             R && r,
0108             parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0109             parser_interface<SkipParser> const & skip,
0110             trace trace_mode)
0111         {
0112             auto first = text::detail::begin(r);
0113             auto const last = text::detail::end(r);
0114 
0115             if (first == last)
0116                 return BOOST_PARSER_SUBRANGE(first, first);
0117 
0118             auto const search_parser = omit[*(char_ - parser)] >> -raw[parser];
0119             if constexpr (std::is_same_v<SkipParser, eps_parser<phony>>) {
0120                 auto result = parser::prefix_parse(
0121                     first, last, search_parser, trace_mode);
0122                 if (*result)
0123                     return **result;
0124             } else {
0125                 auto result = parser::prefix_parse(
0126                     first, last, search_parser, skip, trace_mode);
0127                 if (*result)
0128                     return **result;
0129             }
0130 
0131             return BOOST_PARSER_SUBRANGE(first, first);
0132         }
0133 
0134         template<
0135             typename R,
0136             typename Parser,
0137             typename GlobalState,
0138             typename ErrorHandler,
0139             typename SkipParser>
0140 #if BOOST_PARSER_USE_CONCEPTS
0141         std::ranges::borrowed_subrange_t<R>
0142 #else
0143         auto
0144 #endif
0145         search_repack_shim(
0146             R && r,
0147             parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0148             parser_interface<SkipParser> const & skip,
0149             trace trace_mode)
0150         {
0151             using value_type = range_value_t<decltype(r)>;
0152             if constexpr (std::is_same_v<value_type, char>) {
0153                 return detail::search_impl((R &&) r, parser, skip, trace_mode);
0154             } else {
0155                 auto r_unpacked = detail::text::unpack_iterator_and_sentinel(
0156                     text::detail::begin(r), text::detail::end(r));
0157                 auto result =
0158                     detail::search_impl(r | as_utf32, parser, skip, trace_mode);
0159                 return BOOST_PARSER_SUBRANGE(
0160                     r_unpacked.repack(text::detail::begin(result).base()),
0161                     r_unpacked.repack(text::detail::end(result).base()));
0162             }
0163         }
0164 
0165         template<typename T>
0166         constexpr bool is_parser_iface = false;
0167         template<typename T>
0168         constexpr bool is_parser_iface<parser_interface<T>> = true;
0169     }
0170 
0171     /** Returns a subrange to the first match for parser `parser` in `r`,
0172         using skip-parser `skip`.  This function has a similar interface and
0173         semantics to `std::ranges::search()`.  Returns `std::ranges::dangling`
0174         in C++20 and later if `r` is a non-borrowable rvalue. */
0175     template<
0176 #if BOOST_PARSER_USE_CONCEPTS
0177         parsable_range R,
0178 #else
0179         typename R,
0180 #endif
0181         typename Parser,
0182         typename GlobalState,
0183         typename ErrorHandler,
0184         typename SkipParser
0185 #if !BOOST_PARSER_USE_CONCEPTS
0186         ,
0187         typename Enable = std::enable_if_t<detail::is_parsable_range_v<R>>
0188 #endif
0189         >
0190     auto search(
0191         R && r,
0192         parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0193         parser_interface<SkipParser> const & skip,
0194         trace trace_mode = trace::off)
0195     {
0196         return detail::search_repack_shim(
0197             detail::to_range<R>::call((R &&) r), parser, skip, trace_mode);
0198     }
0199 
0200     /** Returns a subrange to the first match for parser `parser` in `[first,
0201         last)`, using skip-parser `skip`.  This function has a similar
0202         interface and semantics to `std::ranges::search()`. */
0203     template<
0204 #if BOOST_PARSER_USE_CONCEPTS
0205         parsable_iter I,
0206         std::sentinel_for<I> S,
0207 #else
0208         typename I,
0209         typename S,
0210 #endif
0211         typename Parser,
0212         typename SkipParser,
0213         typename GlobalState,
0214 #if BOOST_PARSER_USE_CONCEPTS
0215         error_handler<I, S, GlobalState> ErrorHandler
0216 #else
0217         typename ErrorHandler,
0218         typename Enable = std::enable_if_t<
0219             detail::is_parsable_iter_v<I> &&
0220             detail::is_equality_comparable_with_v<I, S>>
0221 #endif
0222         >
0223     auto search(
0224         I first,
0225         S last,
0226         parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0227         parser_interface<SkipParser> const & skip,
0228         trace trace_mode = trace::off)
0229     {
0230         return parser::search(
0231             BOOST_PARSER_SUBRANGE(first, last), parser, skip, trace_mode);
0232     }
0233 
0234     /** Returns a subrange to the first match for parser `parser` in `r`.
0235         This function has a similar interface and semantics to
0236         `std::ranges::search()`.  Returns `std::ranges::dangling` in C++20 and
0237         later if `r` is a non-borrowable rvalue. */
0238     template<
0239 #if BOOST_PARSER_USE_CONCEPTS
0240         parsable_range R,
0241 #else
0242         typename R,
0243 #endif
0244         typename Parser,
0245         typename GlobalState,
0246         typename ErrorHandler
0247 #if !BOOST_PARSER_USE_CONCEPTS
0248         ,
0249         typename Enable = std::enable_if_t<detail::is_parsable_range_v<R>>
0250 #endif
0251         >
0252     auto search(
0253         R && r,
0254         parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0255         trace trace_mode = trace::off)
0256     {
0257         return parser::search(
0258             (R &&) r,
0259             parser,
0260             parser_interface<eps_parser<detail::phony>>{},
0261             trace_mode);
0262     }
0263 
0264     /** Returns a subrange to the first match for parser `parser` in `[first,
0265         last)`.  This function has a similar interface and semantics to
0266         `std::ranges::search()`. */
0267     template<
0268 #if BOOST_PARSER_USE_CONCEPTS
0269         parsable_iter I,
0270         std::sentinel_for<I> S,
0271 #else
0272         typename I,
0273         typename S,
0274 #endif
0275         typename Parser,
0276         typename GlobalState,
0277 #if BOOST_PARSER_USE_CONCEPTS
0278         error_handler<I, S, GlobalState> ErrorHandler
0279 #else
0280         typename ErrorHandler,
0281         typename Enable = std::enable_if_t<
0282             detail::is_parsable_iter_v<I> &&
0283             detail::is_equality_comparable_with_v<I, S>>
0284 #endif
0285         >
0286     auto search(
0287         I first,
0288         S last,
0289         parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0290         trace trace_mode = trace::off)
0291     {
0292         return parser::search(
0293             BOOST_PARSER_SUBRANGE(first, last),
0294             parser,
0295             parser_interface<eps_parser<detail::phony>>{},
0296             trace_mode);
0297     }
0298 
0299     /** Produces a sequence of subranges of the underlying sequence of type
0300         `V`.  Each subrange is a nonoverlapping match of the given parser,
0301         using a skip-parser if provided. */
0302     template<
0303 #if BOOST_PARSER_USE_CONCEPTS
0304         std::ranges::viewable_range V,
0305 #else
0306         typename V,
0307 #endif
0308         typename Parser,
0309         typename GlobalState,
0310         typename ErrorHandler,
0311         typename SkipParser>
0312     struct search_all_view
0313         : detail::stl_interfaces::view_interface<
0314               search_all_view<V, Parser, GlobalState, ErrorHandler, SkipParser>>
0315     {
0316         constexpr search_all_view() = default;
0317         constexpr search_all_view(
0318             V base,
0319             parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0320             parser_interface<SkipParser> const & skip,
0321             trace trace_mode = trace::off) :
0322             base_(std::move(base)),
0323             parser_(parser),
0324             skip_(skip),
0325             trace_mode_(trace_mode)
0326         {}
0327         constexpr search_all_view(
0328             V base,
0329             parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0330             trace trace_mode = trace::off) :
0331             base_(std::move(base)),
0332             parser_(parser),
0333             skip_(),
0334             trace_mode_(trace_mode)
0335         {}
0336 
0337         constexpr V base() const &
0338 #if BOOST_PARSER_USE_CONCEPTS
0339             requires std::copy_constructible<V>
0340 #endif
0341         {
0342             return base_;
0343         }
0344         constexpr V base() && { return std::move(base_); }
0345 
0346         constexpr auto begin() { return iterator<false>{this}; }
0347         constexpr auto end() { return sentinel<false>{}; }
0348 
0349         constexpr auto begin() const
0350 #if BOOST_PARSER_USE_CONCEPTS
0351             requires std::ranges::range<const V>
0352 #endif
0353         {
0354             return iterator<true>{this};
0355         }
0356         constexpr auto end() const
0357 #if BOOST_PARSER_USE_CONCEPTS
0358             requires std::ranges::range<const V>
0359 #endif
0360         {
0361             return sentinel<true>{};
0362         }
0363 
0364         template<bool Const>
0365         struct sentinel
0366         {};
0367 
0368         template<bool Const>
0369         struct iterator
0370             : detail::stl_interfaces::proxy_iterator_interface<
0371                   iterator<Const>,
0372                   std::forward_iterator_tag,
0373                   BOOST_PARSER_SUBRANGE<
0374                       detail::iterator_t<detail::maybe_const<Const, V>>>>
0375         {
0376             using I = detail::iterator_t<detail::maybe_const<Const, V>>;
0377             using S = detail::sentinel_t<detail::maybe_const<Const, V>>;
0378 
0379             constexpr iterator() = default;
0380             constexpr iterator(
0381                 detail::maybe_const<Const, search_all_view> * parent) :
0382                 parent_(parent),
0383                 r_(parent_->base_.begin(), parent_->base_.end()),
0384                 curr_(r_.begin(), r_.begin()),
0385                 next_it_(r_.begin())
0386             {
0387                 ++*this;
0388             }
0389 
0390             constexpr iterator & operator++()
0391             {
0392                 r_ = BOOST_PARSER_SUBRANGE<I, S>(next_it_, r_.end());
0393                 curr_ = parser::search(
0394                     r_, parent_->parser_, parent_->skip_, parent_->trace_mode_);
0395                 next_it_ = curr_.end();
0396                 if (curr_.begin() == curr_.end())
0397                     r_ = BOOST_PARSER_SUBRANGE<I, S>(next_it_, r_.end());
0398                 return *this;
0399             }
0400 
0401             constexpr BOOST_PARSER_SUBRANGE<I> operator*() const
0402             {
0403                 return curr_;
0404             }
0405 
0406             friend constexpr bool operator==(iterator lhs, iterator rhs)
0407             {
0408                 return lhs.r_.begin() == rhs.r_.begin();
0409             }
0410             friend constexpr bool operator==(iterator it, sentinel<Const>)
0411             {
0412                 return it.r_.begin() == it.r_.end();
0413             }
0414 
0415             using base_type = detail::stl_interfaces::proxy_iterator_interface<
0416                 iterator,
0417                 std::forward_iterator_tag,
0418                 BOOST_PARSER_SUBRANGE<I>>;
0419             using base_type::operator++;
0420 
0421         private:
0422             detail::maybe_const<Const, search_all_view> * parent_;
0423             BOOST_PARSER_SUBRANGE<I, S> r_;
0424             BOOST_PARSER_SUBRANGE<I> curr_;
0425             I next_it_;
0426         };
0427 
0428         template<bool Const>
0429         friend struct iterator;
0430 
0431     private:
0432         V base_;
0433         parser_interface<Parser, GlobalState, ErrorHandler> parser_;
0434         parser_interface<SkipParser> skip_;
0435         trace trace_mode_;
0436     };
0437 
0438     // deduction guides
0439     template<
0440         typename V,
0441         typename Parser,
0442         typename GlobalState,
0443         typename ErrorHandler,
0444         typename SkipParser>
0445     search_all_view(
0446         V &&,
0447         parser_interface<Parser, GlobalState, ErrorHandler>,
0448         parser_interface<SkipParser>,
0449         trace)
0450         -> search_all_view<
0451             detail::text::detail::all_t<V>,
0452             Parser,
0453             GlobalState,
0454             ErrorHandler,
0455             SkipParser>;
0456 
0457     template<
0458         typename V,
0459         typename Parser,
0460         typename GlobalState,
0461         typename ErrorHandler,
0462         typename SkipParser>
0463     search_all_view(
0464         V &&,
0465         parser_interface<Parser, GlobalState, ErrorHandler>,
0466         parser_interface<SkipParser>)
0467         -> search_all_view<
0468             detail::text::detail::all_t<V>,
0469             Parser,
0470             GlobalState,
0471             ErrorHandler,
0472             SkipParser>;
0473 
0474     template<
0475         typename V,
0476         typename Parser,
0477         typename GlobalState,
0478         typename ErrorHandler>
0479     search_all_view(
0480         V &&, parser_interface<Parser, GlobalState, ErrorHandler>, trace)
0481         -> search_all_view<
0482             detail::text::detail::all_t<V>,
0483             Parser,
0484             GlobalState,
0485             ErrorHandler,
0486             parser_interface<eps_parser<detail::phony>>>;
0487 
0488     template<
0489         typename V,
0490         typename Parser,
0491         typename GlobalState,
0492         typename ErrorHandler>
0493     search_all_view(V &&, parser_interface<Parser, GlobalState, ErrorHandler>)
0494         -> search_all_view<
0495             detail::text::detail::all_t<V>,
0496             Parser,
0497             GlobalState,
0498             ErrorHandler,
0499             parser_interface<eps_parser<detail::phony>>>;
0500 
0501     namespace detail {
0502         template<
0503             typename V,
0504             typename Parser,
0505             typename GlobalState,
0506             typename ErrorHandler,
0507             typename SkipParser>
0508         using search_all_view_expr = decltype(search_all_view<
0509                                               V,
0510                                               Parser,
0511                                               GlobalState,
0512                                               ErrorHandler,
0513                                               SkipParser>(
0514             std::declval<V>(),
0515             std::declval<
0516                 parser_interface<Parser, GlobalState, ErrorHandler> const &>(),
0517             std::declval<parser_interface<SkipParser> const &>(),
0518             trace::on));
0519 
0520         template<
0521             typename V,
0522             typename Parser,
0523             typename GlobalState,
0524             typename ErrorHandler,
0525             typename SkipParser>
0526         constexpr bool can_search_all_view = is_detected_v<
0527             search_all_view_expr,
0528             V,
0529             Parser,
0530             GlobalState,
0531             ErrorHandler,
0532             SkipParser>;
0533 
0534         struct search_all_impl
0535         {
0536 #if BOOST_PARSER_USE_CONCEPTS
0537 
0538             template<
0539                 parsable_range R,
0540                 typename Parser,
0541                 typename GlobalState,
0542                 typename ErrorHandler,
0543                 typename SkipParser>
0544                 requires(std::ranges::viewable_range<R>) && can_search_all_view<
0545                                                                 to_range_t<R>,
0546                                                                 Parser,
0547                                                                 GlobalState,
0548                                                                 ErrorHandler,
0549                                                                 SkipParser>
0550             [[nodiscard]] constexpr auto operator()(
0551                 R && r,
0552                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0553                     parser,
0554                 parser_interface<SkipParser> const & skip,
0555                 trace trace_mode = trace::off) const
0556             {
0557                 return search_all_view(
0558                     to_range<R>::call((R &&)r), parser, skip, trace_mode);
0559             }
0560 
0561             template<
0562                 parsable_range R,
0563                 typename Parser,
0564                 typename GlobalState,
0565                 typename ErrorHandler>
0566                 requires(std::ranges::viewable_range<R>) &&
0567                         can_search_all_view<
0568                             to_range_t<R>,
0569                             Parser,
0570                             GlobalState,
0571                             ErrorHandler,
0572                             parser_interface<eps_parser<detail::phony>>>
0573             [[nodiscard]] constexpr auto operator()(
0574                 R && r,
0575                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0576                     parser,
0577                 trace trace_mode = trace::off) const
0578             {
0579                 return (*this)(
0580                     (R &&)r,
0581                     parser,
0582                     parser_interface<eps_parser<detail::phony>>{},
0583                     trace_mode);
0584             }
0585 
0586 #else
0587 
0588             template<
0589                 typename R,
0590                 typename Parser,
0591                 typename GlobalState,
0592                 typename ErrorHandler,
0593                 typename SkipParser =
0594                     parser_interface<eps_parser<detail::phony>>,
0595                 typename Trace = trace,
0596                 typename Enable = std::enable_if_t<is_parsable_range_v<R>>>
0597             [[nodiscard]] constexpr auto operator()(
0598                 R && r,
0599                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0600                     parser,
0601                 SkipParser const & skip = SkipParser{},
0602                 Trace trace_mode = Trace{}) const
0603             {
0604                 if constexpr (
0605                     std::
0606                         is_same_v<detail::remove_cv_ref_t<SkipParser>, trace> &&
0607                     std::is_same_v<Trace, trace>) {
0608                     // (r, parser, trace) case
0609                     return impl(
0610                         (R &&) r,
0611                         parser,
0612                         parser_interface<eps_parser<detail::phony>>{},
0613                         skip);
0614                 } else if constexpr (
0615                     detail::is_parser_iface<SkipParser> &&
0616                     std::is_same_v<Trace, trace>) {
0617                     // (r, parser, skip, trace) case
0618                     return impl((R &&) r, parser, skip, trace_mode);
0619                 } else {
0620                     static_assert(
0621                         sizeof(R) == 1 && false,
0622                         "Only the signatures search_all(R, parser, skip, trace "
0623                         "= trace::off) and search_all(R, parser, trace = "
0624                         "trace::off) are supported.");
0625                 }
0626             }
0627 
0628         private:
0629             template<
0630                 typename R,
0631                 typename Parser,
0632                 typename GlobalState,
0633                 typename ErrorHandler,
0634                 typename SkipParser>
0635             [[nodiscard]] constexpr auto impl(
0636                 R && r,
0637                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0638                     parser,
0639                 parser_interface<SkipParser> const & skip,
0640                 trace trace_mode = trace::off) const
0641             {
0642                 return search_all_view(
0643                     to_range<R>::call((R &&) r), parser, skip, trace_mode);
0644             }
0645 
0646 #endif
0647         };
0648     }
0649 
0650     /** A range adaptor object ([range.adaptor.object]).  Given subexpressions
0651         `E` and `P`, `Q`, and `R`, each of the expressions `search_all(E, P)`,
0652         `search_all(E, P, Q)`, and `search_all(E, P, Q, R)` are
0653         expression-equivalent to `search_all_view(E, P)`, `search_all_view(E,
0654         P, Q)`, and `search_all_view(E, P, Q, R)`, respectively. */
0655     inline constexpr detail::stl_interfaces::adaptor<detail::search_all_impl>
0656         search_all = detail::search_all_impl{};
0657 
0658 }
0659 
0660 #if BOOST_PARSER_USE_CONCEPTS
0661 template<
0662     typename V,
0663     typename Parser,
0664     typename GlobalState,
0665     typename ErrorHandler,
0666     typename SkipParser>
0667 constexpr bool std::ranges::enable_borrowed_range<
0668     boost::parser::
0669         search_all_view<V, Parser, GlobalState, ErrorHandler, SkipParser>> =
0670     std::ranges::enable_borrowed_range<V>;
0671 #endif
0672 
0673 #endif