File indexing completed on 2025-01-18 09:53:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
0012 #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
0013
0014
0015 #if defined(_MSC_VER)
0016 # pragma once
0017 #endif
0018
0019 #include <boost/config.hpp>
0020 #include <boost/version.hpp>
0021 #include <boost/ref.hpp>
0022 #include <boost/assert.hpp>
0023 #include <boost/mpl/if.hpp>
0024 #include <boost/throw_exception.hpp>
0025 #include <boost/utility/result_of.hpp>
0026 #include <boost/type_traits/is_const.hpp>
0027 #include <boost/type_traits/remove_reference.hpp>
0028 #include <boost/xpressive/detail/detail_fwd.hpp>
0029 #include <boost/xpressive/detail/core/quant_style.hpp>
0030 #include <boost/xpressive/detail/core/action.hpp>
0031 #include <boost/xpressive/detail/core/state.hpp>
0032 #include <boost/proto/core.hpp>
0033 #include <boost/proto/context.hpp>
0034 #include <boost/xpressive/match_results.hpp> // for type_info_less
0035 #include <boost/xpressive/detail/static/transforms/as_action.hpp> // for 'read_attr'
0036 #if BOOST_VERSION >= 103500
0037 # include <boost/proto/fusion.hpp>
0038 # include <boost/fusion/include/transform_view.hpp>
0039 # include <boost/fusion/include/invoke.hpp>
0040 # include <boost/fusion/include/push_front.hpp>
0041 # include <boost/fusion/include/pop_front.hpp>
0042 #endif
0043
0044 #if BOOST_MSVC
0045 #pragma warning(push)
0046 #pragma warning(disable : 4510)
0047 #pragma warning(disable : 4512)
0048 #pragma warning(disable : 4610)
0049 #endif
0050
0051 namespace boost { namespace xpressive { namespace detail
0052 {
0053
0054 #if BOOST_VERSION >= 103500
0055 struct DataMember
0056 : proto::mem_ptr<proto::_, proto::terminal<proto::_> >
0057 {};
0058
0059 template<typename Expr, long N>
0060 struct child_
0061 : remove_reference<
0062 typename proto::result_of::child_c<Expr &, N>::type
0063 >
0064 {};
0065
0066
0067
0068
0069
0070 template<typename Expr, typename Context, bool IsDataMember = proto::matches<Expr, DataMember>::value>
0071 struct mem_ptr_eval
0072 {
0073 typedef typename child_<Expr, 0>::type left_type;
0074 typedef typename child_<Expr, 1>::type right_type;
0075
0076 typedef
0077 typename proto::result_of::value<
0078 typename proto::result_of::child_c<right_type, 0>::type
0079 >::type
0080 function_type;
0081
0082 typedef
0083 fusion::transform_view<
0084 typename fusion::result_of::push_front<
0085 typename fusion::result_of::pop_front<right_type>::type const
0086 , reference_wrapper<left_type>
0087 >::type const
0088 , proto::eval_fun<Context>
0089 >
0090 evaluated_args;
0091
0092 typedef
0093 typename fusion::result_of::invoke<function_type, evaluated_args>::type
0094 result_type;
0095
0096 result_type operator()(Expr &expr, Context &ctx) const
0097 {
0098 return fusion::invoke<function_type>(
0099 proto::value(proto::child_c<0>(proto::right(expr)))
0100 , evaluated_args(
0101 fusion::push_front(fusion::pop_front(proto::right(expr)), boost::ref(proto::left(expr)))
0102 , proto::eval_fun<Context>(ctx)
0103 )
0104 );
0105 }
0106 };
0107
0108
0109
0110
0111
0112 template<typename Expr, typename Context>
0113 struct mem_ptr_eval<Expr, Context, true>
0114 {
0115 typedef typename child_<Expr, 0>::type left_type;
0116 typedef typename child_<Expr, 1>::type right_type;
0117
0118 typedef
0119 typename proto::result_of::value<right_type>::type
0120 function_type;
0121
0122 typedef typename boost::result_of<
0123 function_type(typename proto::result_of::eval<left_type, Context>::type)
0124 >::type result_type;
0125
0126 result_type operator()(Expr &expr, Context &ctx) const
0127 {
0128 return proto::value(proto::right(expr))(
0129 proto::eval(proto::left(expr), ctx)
0130 );
0131 }
0132 };
0133 #endif
0134
0135 struct attr_with_default_tag
0136 {};
0137
0138 template<typename T>
0139 struct opt;
0140
0141
0142
0143
0144 struct action_context
0145 {
0146 explicit action_context(action_args_type *action_args)
0147 : action_args_(action_args)
0148 {}
0149
0150 action_args_type const &args() const
0151 {
0152 return *this->action_args_;
0153 }
0154
0155
0156 template<typename Expr, typename Arg>
0157 struct eval_terminal
0158 : proto::default_eval<Expr, action_context const>
0159 {};
0160
0161 template<typename Expr, typename Arg>
0162 struct eval_terminal<Expr, reference_wrapper<Arg> >
0163 {
0164 typedef Arg &result_type;
0165 result_type operator()(Expr &expr, action_context const &) const
0166 {
0167 return proto::value(expr).get();
0168 }
0169 };
0170
0171 template<typename Expr, typename Arg>
0172 struct eval_terminal<Expr, opt<Arg> >
0173 {
0174 typedef Arg const &result_type;
0175 result_type operator()(Expr &expr, action_context const &) const
0176 {
0177 return proto::value(expr);
0178 }
0179 };
0180
0181 template<typename Expr, typename Type, typename Int>
0182 struct eval_terminal<Expr, action_arg<Type, Int> >
0183 {
0184 typedef typename action_arg<Type, Int>::reference result_type;
0185 result_type operator()(Expr &expr, action_context const &ctx) const
0186 {
0187 action_args_type::const_iterator where_ = ctx.args().find(&typeid(proto::value(expr)));
0188 if(where_ == ctx.args().end())
0189 {
0190 BOOST_THROW_EXCEPTION(
0191 regex_error(
0192 regex_constants::error_badarg
0193 , "An argument to an action was unspecified"
0194 )
0195 );
0196 }
0197 return proto::value(expr).cast(where_->second);
0198 }
0199 };
0200
0201
0202 template<typename Expr, typename Tag = typename Expr::proto_tag>
0203 struct eval
0204 : proto::default_eval<Expr, action_context const>
0205 {};
0206
0207 template<typename Expr>
0208 struct eval<Expr, proto::tag::terminal>
0209 : eval_terminal<Expr, typename proto::result_of::value<Expr>::type>
0210 {};
0211
0212
0213 template<typename Expr>
0214 struct eval<Expr, attr_with_default_tag>
0215 {
0216 typedef
0217 typename proto::result_of::value<
0218 typename proto::result_of::left<
0219 typename proto::result_of::child<
0220 Expr
0221 >::type
0222 >::type
0223 >::type
0224 temp_type;
0225
0226 typedef typename temp_type::type result_type;
0227
0228 result_type operator ()(Expr const &expr, action_context const &ctx) const
0229 {
0230 return proto::value(proto::left(proto::child(expr))).t_
0231 ? *proto::value(proto::left(proto::child(expr))).t_
0232 : proto::eval(proto::right(proto::child(expr)), ctx);
0233 }
0234 };
0235
0236 #if BOOST_VERSION >= 103500
0237 template<typename Expr>
0238 struct eval<Expr, proto::tag::mem_ptr>
0239 : mem_ptr_eval<Expr, action_context const>
0240 {};
0241 #endif
0242
0243 private:
0244 action_args_type *action_args_;
0245 };
0246
0247
0248
0249
0250 template<typename Actor>
0251 struct action
0252 : actionable
0253 {
0254 action(Actor const &actor)
0255 : actionable()
0256 , actor_(actor)
0257 {
0258 }
0259
0260 virtual void execute(action_args_type *action_args) const
0261 {
0262 action_context const ctx(action_args);
0263 proto::eval(this->actor_, ctx);
0264 }
0265
0266 private:
0267 Actor actor_;
0268 };
0269
0270
0271
0272
0273 struct subreg_transform : proto::transform<subreg_transform>
0274 {
0275 template<typename Expr, typename State, typename Data>
0276 struct impl : proto::transform_impl<Expr, State, Data>
0277 {
0278 typedef typename impl::state state_type;
0279
0280 typedef
0281 typename proto::terminal<sub_match<typename state_type::iterator> >::type
0282 result_type;
0283
0284 result_type operator ()(
0285 typename impl::expr_param
0286 , typename impl::state_param state
0287 , typename impl::data_param data
0288 ) const
0289 {
0290 return result_type::make(state.sub_matches_[ data ]);
0291 }
0292 };
0293 };
0294
0295
0296
0297
0298 struct mark_transform : proto::transform<mark_transform>
0299 {
0300 template<typename Expr, typename State, typename Data>
0301 struct impl : proto::transform_impl<Expr, State, Data>
0302 {
0303 typedef typename impl::state state_type;
0304 typedef
0305 typename proto::terminal<sub_match<typename state_type::iterator> >::type
0306 result_type;
0307
0308 result_type operator ()(
0309 typename impl::expr_param expr
0310 , typename impl::state_param state
0311 , typename impl::data_param
0312 ) const
0313 {
0314 return result_type::make(state.sub_matches_[ proto::value(expr).mark_number_ ]);
0315 }
0316 };
0317 };
0318
0319
0320
0321
0322 template<typename T>
0323 struct opt
0324 {
0325 typedef T type;
0326 typedef T const &reference;
0327
0328 opt(T const *t)
0329 : t_(t)
0330 {}
0331
0332 operator reference() const
0333 {
0334 BOOST_XPR_ENSURE_(0 != this->t_, regex_constants::error_badattr, "Use of uninitialized regex attribute");
0335 return *this->t_;
0336 }
0337
0338 T const *t_;
0339 };
0340
0341
0342
0343
0344 struct attr_transform : proto::transform<attr_transform>
0345 {
0346 template<typename Expr, typename State, typename Data>
0347 struct impl : proto::transform_impl<Expr, State, Data>
0348 {
0349 typedef typename impl::expr expr_type;
0350
0351 typedef
0352 typename expr_type::proto_child0::matcher_type::value_type::second_type
0353 attr_type;
0354
0355 typedef
0356 typename proto::terminal<opt<attr_type> >::type
0357 result_type;
0358
0359 result_type operator ()(
0360 typename impl::expr_param
0361 , typename impl::state_param state
0362 , typename impl::data_param
0363 ) const
0364 {
0365 int slot = typename expr_type::proto_child0::nbr_type();
0366 attr_type const *attr = static_cast<attr_type const *>(state.attr_context_.attr_slots_[slot-1]);
0367 return result_type::make(opt<attr_type>(attr));
0368 }
0369 };
0370 };
0371
0372
0373
0374
0375 template<typename Grammar, typename Callable = proto::callable>
0376 struct attr_with_default_transform : proto::transform<attr_with_default_transform<Grammar, Callable> >
0377 {
0378 template<typename Expr, typename State, typename Data>
0379 struct impl : proto::transform_impl<Expr, State, Data>
0380 {
0381 typedef
0382 typename proto::unary_expr<
0383 attr_with_default_tag
0384 , typename Grammar::template impl<Expr, State, Data>::result_type
0385 >::type
0386 result_type;
0387
0388 result_type operator ()(
0389 typename impl::expr_param expr
0390 , typename impl::state_param state
0391 , typename impl::data_param data
0392 ) const
0393 {
0394 result_type that = {
0395 typename Grammar::template impl<Expr, State, Data>()(expr, state, data)
0396 };
0397 return that;
0398 }
0399 };
0400 };
0401
0402
0403
0404
0405 struct by_ref_transform : proto::transform<by_ref_transform>
0406 {
0407 template<typename Expr, typename State, typename Data>
0408 struct impl : proto::transform_impl<Expr, State, Data>
0409 {
0410 typedef
0411 typename proto::result_of::value<typename impl::expr_param>::type
0412 reference;
0413
0414 typedef
0415 typename proto::terminal<reference>::type
0416 result_type;
0417
0418 result_type operator ()(
0419 typename impl::expr_param expr
0420 , typename impl::state_param
0421 , typename impl::data_param
0422 ) const
0423 {
0424 return result_type::make(proto::value(expr));
0425 }
0426 };
0427 };
0428
0429
0430
0431
0432 struct BindActionArgs
0433 : proto::or_<
0434 proto::when<proto::terminal<any_matcher>, subreg_transform>
0435 , proto::when<proto::terminal<mark_placeholder>, mark_transform>
0436 , proto::when<proto::terminal<read_attr<proto::_, proto::_> >, attr_transform>
0437 , proto::when<proto::terminal<proto::_>, by_ref_transform>
0438 , proto::when<
0439 proto::bitwise_or<proto::terminal<read_attr<proto::_, proto::_> >, BindActionArgs>
0440 , attr_with_default_transform<proto::bitwise_or<attr_transform, BindActionArgs> >
0441 >
0442 , proto::otherwise<proto::nary_expr<proto::_, proto::vararg<BindActionArgs> > >
0443 >
0444 {};
0445
0446
0447
0448
0449 template<typename Actor>
0450 struct action_matcher
0451 : quant_style<quant_none, 0, false>
0452 {
0453 int sub_;
0454 Actor actor_;
0455
0456 action_matcher(Actor const &actor, int sub)
0457 : sub_(sub)
0458 , actor_(actor)
0459 {
0460 }
0461
0462 template<typename BidiIter, typename Next>
0463 bool match(match_state<BidiIter> &state, Next const &next) const
0464 {
0465
0466 typedef
0467 typename boost::result_of<BindActionArgs(
0468 Actor const &
0469 , match_state<BidiIter> &
0470 , int const &
0471 )>::type
0472 action_type;
0473
0474 action<action_type> actor(BindActionArgs()(this->actor_, state, this->sub_));
0475
0476
0477 actionable const **action_list_tail = state.action_list_tail_;
0478 *state.action_list_tail_ = &actor;
0479 state.action_list_tail_ = &actor.next;
0480
0481
0482 if(next.match(state))
0483 {
0484 return true;
0485 }
0486
0487 BOOST_ASSERT(0 == actor.next);
0488
0489 *action_list_tail = 0;
0490 state.action_list_tail_ = action_list_tail;
0491 return false;
0492 }
0493 };
0494
0495 }}}
0496
0497 #if BOOST_MSVC
0498 #pragma warning(pop)
0499 #endif
0500
0501 #endif