Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:02:36

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