Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:09:35

0001 /*=============================================================================
0002     Copyright (c) 2001-2014 Joel de Guzman
0003     Copyright (c) 2013 Agustin Berge
0004     Copyright (c) 2024 Nana Sakisaka
0005 
0006     Distributed under the Boost Software License, Version 1.0. (See accompanying
0007     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 =============================================================================*/
0009 #if !defined(BOOST_SPIRIT_X3_SKIP_JANUARY_26_2008_0422PM)
0010 #define BOOST_SPIRIT_X3_SKIP_JANUARY_26_2008_0422PM
0011 
0012 #include <boost/spirit/home/x3/support/context.hpp>
0013 #include <boost/spirit/home/x3/support/unused.hpp>
0014 #include <boost/spirit/home/x3/support/expectation.hpp>
0015 #include <boost/spirit/home/x3/core/skip_over.hpp>
0016 #include <boost/spirit/home/x3/core/parser.hpp>
0017 #include <boost/utility/enable_if.hpp>
0018 
0019 namespace boost { namespace spirit { namespace x3
0020 {
0021     template <typename Subject>
0022     struct reskip_directive : unary_parser<Subject, reskip_directive<Subject>>
0023     {
0024         typedef unary_parser<Subject, reskip_directive<Subject>> base_type;
0025         static bool const is_pass_through_unary = true;
0026         static bool const handles_container = Subject::handles_container;
0027 
0028         constexpr reskip_directive(Subject const& subject)
0029           : base_type(subject) {}
0030 
0031         template <typename Iterator, typename Context
0032           , typename RContext, typename Attribute>
0033         typename disable_if<has_skipper<Context>, bool>::type
0034         parse(Iterator& first, Iterator const& last
0035           , Context& context, RContext& rcontext, Attribute& attr) const
0036         {
0037             auto const& skipper =
0038                 detail::get_unused_skipper(x3::get<skipper_tag>(context));
0039 
0040             auto const local_ctx = make_context<skipper_tag>(skipper, context);
0041             bool const r = this->subject.parse(first, last, local_ctx, rcontext, attr);
0042 
0043         #if !BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0044             if (has_expectation_failure(local_ctx))
0045             {
0046                 set_expectation_failure(get_expectation_failure(local_ctx), context);
0047             }
0048         #endif
0049 
0050             return r;
0051         }
0052         template <typename Iterator, typename Context
0053           , typename RContext, typename Attribute>
0054         typename enable_if<has_skipper<Context>, bool>::type
0055         parse(Iterator& first, Iterator const& last
0056           , Context const& context, RContext& rcontext, Attribute& attr) const
0057         {
0058             return this->subject.parse(first, last, context, rcontext, attr);
0059         }
0060     };
0061 
0062     template <typename Subject, typename Skipper>
0063     struct skip_directive : unary_parser<Subject, skip_directive<Subject, Skipper>>
0064     {
0065         typedef unary_parser<Subject, skip_directive<Subject, Skipper>> base_type;
0066         static bool const is_pass_through_unary = true;
0067         static bool const handles_container = Subject::handles_container;
0068 
0069         constexpr skip_directive(Subject const& subject, Skipper const& skipper)
0070           : base_type(subject)
0071           , skipper(skipper)
0072         {}
0073 
0074         template <typename Iterator, typename RContext, typename Attribute>
0075         bool parse(Iterator& first, Iterator const& last
0076           , unused_type const&, RContext& rcontext, Attribute& attr) const
0077         {
0078             // It is perfectly fine to omit the expectation_failure context
0079             // even in non-throwing mode if and only if the skipper itself
0080             // is expectation-less.
0081             //
0082             // For example:
0083             //   skip(a > b) [lit('foo')]
0084             //   skip(c >> d)[lit('foo')]
0085             //     `a > b`  should require non-`unused_type` context, but
0086             //     `c >> d` should NOT require non-`unused_type` context
0087             //
0088             // However, it's impossible right now to detect whether
0089             // `this->subject` actually is expectation-less, so we just
0090             // call the parse function to see what will happen. If the
0091             // subject turns out to lack the expectation context,
0092             // static_assert will be engaged in other locations.
0093             //
0094             // Anyways, we don't need to repack the expectation context
0095             // into our brand new skipper context, in contrast to the
0096             // repacking process done in `x3::skip_over`.
0097             return this->subject.parse(first, last,
0098                 make_context<skipper_tag>(skipper), rcontext, attr);
0099         }
0100 
0101         template <typename Iterator, typename Context, typename RContext, typename Attribute>
0102         bool parse(Iterator& first, Iterator const& last
0103           , Context const& context, RContext& rcontext, Attribute& attr) const
0104         {
0105         #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0106             return this->subject.parse(first, last, make_context<skipper_tag>(skipper, context), rcontext, attr);
0107 
0108         #else
0109             static_assert(
0110                 !std::is_same_v<expectation_failure_t<Context>, unused_type>,
0111                 "Context type was not specified for x3::expectation_failure_tag. "
0112                 "You probably forgot: `x3::with<x3::expectation_failure_tag>(failure)[p]`. "
0113                 "Note that you must also bind the context to your skipper.");
0114 
0115             // This logic is heavily related to the instantiation chain;
0116             // see `x3::skip_over` for details.
0117             auto const local_ctx = make_context<skipper_tag>(skipper, context);
0118             bool const r = this->subject.parse(first, last, local_ctx, rcontext, attr);
0119 
0120             if (has_expectation_failure(local_ctx))
0121             {
0122                 set_expectation_failure(get_expectation_failure(local_ctx), context);
0123             }
0124             return r;
0125         #endif
0126         }
0127 
0128         Skipper const skipper;
0129     };
0130 
0131     struct reskip_gen
0132     {
0133         template <typename Skipper>
0134         struct skip_gen
0135         {
0136             constexpr skip_gen(Skipper const& skipper)
0137               : skipper_(skipper) {}
0138 
0139             template <typename Subject>
0140             constexpr skip_directive<typename extension::as_parser<Subject>::value_type, Skipper>
0141             operator[](Subject const& subject) const
0142             {
0143                 return { as_parser(subject), skipper_ };
0144             }
0145 
0146             Skipper skipper_;
0147         };
0148 
0149         template <typename Skipper>
0150         constexpr skip_gen<Skipper> const operator()(Skipper const& skipper) const
0151         {
0152             return { skipper };
0153         }
0154 
0155         template <typename Subject>
0156         constexpr reskip_directive<typename extension::as_parser<Subject>::value_type>
0157         operator[](Subject const& subject) const
0158         {
0159             return { as_parser(subject) };
0160         }
0161     };
0162 
0163     constexpr auto skip = reskip_gen{};
0164 }}}
0165 
0166 #endif