File indexing completed on 2025-11-05 09:35:52
0001
0002
0003
0004
0005
0006
0007
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
0043
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
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
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& , Context const& context
0147 , mpl::false_ )
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_ )
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& , Iterator&
0165 , Context const& , ActualAttribute&
0166 , mpl::false_ )
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_ )
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
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
0204
0205
0206
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_ )
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
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;
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&
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
0328
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
0338
0339 ;
0340 {
0341
0342
0343
0344
0345
0346
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
0362
0363 transform::post(attr, std::forward<transform_attr>(attr_));
0364 }
0365 return ok_parse;
0366 }
0367 };
0368 }}}}
0369
0370 #endif