File indexing completed on 2025-01-31 10:02:36
0001
0002
0003
0004
0005
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
0040
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
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
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& , Context const& context
0144 , mpl::false_ )
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_ )
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& , Iterator&
0162 , Context const& , ActualAttribute&
0163 , mpl::false_ )
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_ )
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
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
0201
0202
0203
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_ )
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&
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
0305
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
0315
0316 ;
0317 {
0318
0319
0320
0321
0322
0323
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
0339
0340 transform::post(attr, std::forward<transform_attr>(attr_));
0341 }
0342 return ok_parse;
0343 }
0344 };
0345 }}}}
0346
0347 #endif