Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-05 09:35:52

0001 /*=============================================================================
0002     Copyright (c) 2001-2014 Joel de Guzman
0003     Copyright (c) 2017 wanghan02
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_DETAIL_RULE_JAN_08_2012_0326PM)
0010 #define BOOST_SPIRIT_X3_DETAIL_RULE_JAN_08_2012_0326PM
0011 
0012 #include <boost/core/ignore_unused.hpp>
0013 #include <boost/spirit/home/x3/auxiliary/guard.hpp>
0014 #include <boost/spirit/home/x3/core/parser.hpp>
0015 #include <boost/spirit/home/x3/core/skip_over.hpp>
0016 #include <boost/spirit/home/x3/support/expectation.hpp>
0017 #include <boost/spirit/home/x3/directive/expect.hpp>
0018 #include <boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp>
0019 #include <boost/utility/addressof.hpp>
0020 
0021 #if defined(BOOST_SPIRIT_X3_DEBUG)
0022 #include <boost/spirit/home/x3/nonterminal/simple_trace.hpp>
0023 #endif
0024 
0025 #include <type_traits>
0026 
0027 namespace boost { namespace spirit { namespace x3
0028 {
0029     template <typename ID>
0030     struct identity;
0031 
0032     template <typename ID, typename Attribute = unused_type, bool force_attribute = false>
0033     struct rule;
0034 
0035     struct parse_pass_context_tag;
0036 
0037     namespace detail
0038     {
0039         template <typename ID>
0040         struct rule_id {};
0041 
0042         // we use this so we can detect if the default parse_rule
0043         // is the being called.
0044         struct default_parse_rule_result
0045         {
0046             default_parse_rule_result(bool r)
0047               : r(r) {}
0048             operator bool() const { return r; }
0049             bool r;
0050         };
0051     }
0052 
0053     // default parse_rule implementation
0054     template <typename ID, typename Iterator
0055       , typename Context, typename ActualAttribute>
0056     inline detail::default_parse_rule_result
0057     parse_rule(
0058         detail::rule_id<ID>
0059       , Iterator& first, Iterator const& last
0060       , Context const& context, ActualAttribute& attr);
0061 }}}
0062 
0063 namespace boost { namespace spirit { namespace x3 { namespace detail
0064 {
0065 #if defined(BOOST_SPIRIT_X3_DEBUG)
0066     template <typename Iterator, typename Attribute>
0067     struct context_debug
0068     {
0069         context_debug(
0070             char const* rule_name
0071           , Iterator const& first, Iterator const& last
0072           , Attribute const& attr
0073           , bool const& ok_parse //was parse successful?
0074           )
0075           : ok_parse(ok_parse), rule_name(rule_name)
0076           , first(first), last(last)
0077           , attr(attr)
0078           , f(detail::get_simple_trace())
0079         {
0080             f(first, last, attr, pre_parse, rule_name);
0081         }
0082 
0083         ~context_debug()
0084         {
0085             auto status = ok_parse ? successful_parse : failed_parse ;
0086             f(first, last, attr, status, rule_name);
0087         }
0088 
0089         bool const& ok_parse;
0090         char const* rule_name;
0091         Iterator const& first;
0092         Iterator const& last;
0093         Attribute const& attr;
0094         detail::simple_trace_type& f;
0095     };
0096 #endif
0097 
0098     template <typename ID, typename Iterator, typename Context, typename Enable = void>
0099     struct has_on_error : mpl::false_ {};
0100 
0101     template <typename ID, typename Iterator, typename Context>
0102     struct has_on_error<ID, Iterator, Context,
0103             decltype(void(
0104                 std::declval<ID>().on_error(
0105                     std::declval<Iterator&>()
0106                   , std::declval<Iterator>()
0107                   , std::declval<expectation_failure<Iterator>>()
0108                   , std::declval<Context>()
0109                 )
0110             ))
0111         >
0112       : mpl::true_
0113     {};
0114 
0115     template <typename ID, typename Iterator, typename Attribute, typename Context, typename Enable = void>
0116     struct has_on_success : mpl::false_ {};
0117 
0118     template <typename ID, typename Iterator, typename Attribute, typename Context>
0119     struct has_on_success<ID, Iterator, Context, Attribute,
0120             decltype(void(
0121                 std::declval<ID>().on_success(
0122                     std::declval<Iterator&>()
0123                   , std::declval<Iterator&>()
0124                   , std::declval<Attribute&>()
0125                   , std::declval<Context>()
0126                 )
0127             ))
0128         >
0129       : mpl::true_
0130     {};
0131 
0132     template <typename ID>
0133     struct make_id
0134     {
0135         typedef identity<ID> type;
0136     };
0137 
0138     template <typename ID>
0139     struct make_id<identity<ID>>
0140     {
0141         typedef identity<ID> type;
0142     };
0143 
0144     template <typename ID, typename RHS, typename Context>
0145     Context const&
0146     make_rule_context(RHS const& /* rhs */, Context const& context
0147       , mpl::false_ /* is_default_parse_rule */)
0148     {
0149         return context;
0150     }
0151 
0152     template <typename ID, typename RHS, typename Context>
0153     auto make_rule_context(RHS const& rhs, Context const& context
0154       , mpl::true_ /* is_default_parse_rule */ )
0155     {
0156         return make_unique_context<ID>(rhs, context);
0157     }
0158 
0159     template <typename Attribute, typename ID, bool skip_definition_injection = false>
0160     struct rule_parser
0161     {
0162         template <typename Iterator, typename Context, typename ActualAttribute>
0163         static bool call_on_success(
0164             Iterator& /* before */, Iterator& /* after */
0165           , Context const& /* context */, ActualAttribute& /* attr */
0166           , mpl::false_ /* No on_success handler */ )
0167         {
0168             return true;
0169         }
0170 
0171         template <typename Iterator, typename Context, typename ActualAttribute>
0172         static bool call_on_success(
0173             Iterator& before, Iterator& after
0174           , Context const& context, ActualAttribute& attr
0175           , mpl::true_ /* Has on_success handler */)
0176         {
0177             x3::skip_over(before, after, context);
0178             bool pass = true;
0179             ID().on_success(
0180                 before
0181               , after
0182               , attr
0183               , make_context<parse_pass_context_tag>(pass, context)
0184             );
0185             return pass;
0186         }
0187 
0188         template <typename RHS, typename Iterator, typename Context
0189           , typename RContext, typename ActualAttribute>
0190         static bool parse_rhs_main(
0191             RHS const& rhs
0192           , Iterator& first, Iterator const& last
0193           , Context const& context, RContext& rcontext, ActualAttribute& attr
0194           , mpl::false_)
0195         {
0196             // see if the user has a BOOST_SPIRIT_DEFINE for this rule
0197             typedef
0198                 decltype(parse_rule(
0199                     detail::rule_id<ID>{}, first, last
0200                   , make_unique_context<ID>(rhs, context), std::declval<Attribute&>()))
0201             parse_rule_result;
0202 
0203             // If there is no BOOST_SPIRIT_DEFINE for this rule,
0204             // we'll make a context for this rule tagged by its ID
0205             // so we can extract the rule later on in the default
0206             // (generic) parse_rule function.
0207             typedef
0208                 is_same<parse_rule_result, default_parse_rule_result>
0209             is_default_parse_rule;
0210 
0211             Iterator start = first;
0212             bool r = rhs.parse(
0213                 first
0214               , last
0215               , make_rule_context<ID>(rhs, context, std::conditional_t<skip_definition_injection, mpl::false_, is_default_parse_rule>())
0216               , rcontext
0217               , attr
0218             );
0219 
0220             if (r)
0221             {
0222                 r = call_on_success(start, first, context, attr
0223                   , has_on_success<ID, Iterator, Context, ActualAttribute>());
0224             }
0225 
0226             return r;
0227         }
0228 
0229         template <typename RHS, typename Iterator, typename Context
0230           , typename RContext, typename ActualAttribute>
0231         static bool parse_rhs_main(
0232             RHS const& rhs
0233           , Iterator& first, Iterator const& last
0234           , Context const& context, RContext& rcontext, ActualAttribute& attr
0235           , mpl::true_ /* on_error is found */)
0236         {
0237             for (;;)
0238             {
0239             #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0240                 try
0241             #endif
0242                 {
0243                     if (parse_rhs_main(
0244                         rhs, first, last, context, rcontext, attr, mpl::false_()))
0245                     {
0246                         return true;
0247                     }
0248                 }
0249 
0250             #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0251                 catch (expectation_failure<Iterator> const& x) {
0252             #else
0253                 if (has_expectation_failure(context)) {
0254                     auto& x = get_expectation_failure(context);
0255             #endif
0256                     // X3 developer note: don't forget to sync this implementation with x3::guard
0257                     switch (ID().on_error(first, last, x, context))
0258                     {
0259                         case error_handler_result::fail:
0260                             clear_expectation_failure(context);
0261                             return false;
0262 
0263                         case error_handler_result::retry:
0264                             continue;
0265 
0266                         case error_handler_result::accept:
0267                             return true;
0268 
0269                         case error_handler_result::rethrow:
0270                         #if BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE
0271                             throw;
0272                         #else
0273                             return false; // TODO: design decision required
0274                         #endif
0275                     }
0276                 }
0277                 return false;
0278             }
0279         }
0280 
0281         template <typename RHS, typename Iterator
0282           , typename Context, typename RContext, typename ActualAttribute>
0283         static bool parse_rhs_main(
0284             RHS const& rhs
0285           , Iterator& first, Iterator const& last
0286           , Context const& context, RContext& rcontext, ActualAttribute& attr)
0287         {
0288             return parse_rhs_main(
0289                 rhs, first, last, context, rcontext, attr
0290               , has_on_error<ID, Iterator, Context>()
0291             );
0292         }
0293 
0294         template <typename RHS, typename Iterator
0295           , typename Context, typename RContext, typename ActualAttribute>
0296         static bool parse_rhs(
0297             RHS const& rhs
0298           , Iterator& first, Iterator const& last
0299           , Context const& context, RContext& rcontext, ActualAttribute& attr
0300           , mpl::false_)
0301         {
0302             return parse_rhs_main(rhs, first, last, context, rcontext, attr);
0303         }
0304 
0305         template <typename RHS, typename Iterator
0306           , typename Context, typename RContext, typename ActualAttribute>
0307         static bool parse_rhs(
0308             RHS const& rhs
0309           , Iterator& first, Iterator const& last
0310           , Context const& context, RContext& rcontext, ActualAttribute& /* attr */
0311           , mpl::true_)
0312         {
0313             return parse_rhs_main(rhs, first, last, context, rcontext, unused);
0314         }
0315 
0316         template <typename RHS, typename Iterator, typename Context
0317           , typename ActualAttribute, typename ExplicitAttrPropagation>
0318         static bool call_rule_definition(
0319             RHS const& rhs
0320           , char const* rule_name
0321           , Iterator& first, Iterator const& last
0322           , Context const& context, ActualAttribute& attr
0323           , ExplicitAttrPropagation)
0324         {
0325             boost::ignore_unused(rule_name);
0326 
0327             // do down-stream transformation, provides attribute for
0328             // rhs parser
0329             typedef traits::transform_attribute<
0330                 ActualAttribute, Attribute, parser_id>
0331             transform;
0332 
0333             typedef typename transform::type transform_attr;
0334             transform_attr attr_ = transform::pre(attr);
0335 
0336             bool ok_parse
0337               //Creates a place to hold the result of parse_rhs
0338               //called inside the following scope.
0339               ;
0340             {
0341              // Create a scope to cause the dbg variable below (within
0342              // the #if...#endif) to call it's DTOR before any
0343              // modifications are made to the attribute, attr_ passed
0344              // to parse_rhs (such as might be done in
0345              // transform::post when, for example,
0346              // ActualAttribute is a recursive variant).
0347 #if defined(BOOST_SPIRIT_X3_DEBUG)
0348                 context_debug<Iterator, transform_attr>
0349                 dbg(rule_name, first, last, attr_, ok_parse);
0350 #endif
0351                 ok_parse = parse_rhs(rhs, first, last, context, attr_, attr_
0352                    , mpl::bool_
0353                      < (  RHS::has_action
0354                        && !ExplicitAttrPropagation::value
0355                        )
0356                      >()
0357                   );
0358             }
0359             if (ok_parse)
0360             {
0361                 // do up-stream transformation, this integrates the results
0362                 // back into the original attribute value, if appropriate
0363                 transform::post(attr, std::forward<transform_attr>(attr_));
0364             }
0365             return ok_parse;
0366         }
0367     };
0368 }}}}
0369 
0370 #endif