action_matcher.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // action_matcher.hpp
  3. //
  4. // Copyright 2008 Eric Niebler.
  5. // Copyright 2008 David Jenkins.
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See
  8. // accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
  11. #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
  12. // MS compatible compilers support #pragma once
  13. #if defined(_MSC_VER)
  14. # pragma once
  15. #endif
  16. #include <boost/config.hpp>
  17. #include <boost/version.hpp>
  18. #include <boost/ref.hpp>
  19. #include <boost/assert.hpp>
  20. #include <boost/mpl/if.hpp>
  21. #include <boost/throw_exception.hpp>
  22. #include <boost/utility/result_of.hpp>
  23. #include <boost/type_traits/is_const.hpp>
  24. #include <boost/type_traits/remove_reference.hpp>
  25. #include <boost/xpressive/detail/detail_fwd.hpp>
  26. #include <boost/xpressive/detail/core/quant_style.hpp>
  27. #include <boost/xpressive/detail/core/action.hpp>
  28. #include <boost/xpressive/detail/core/state.hpp>
  29. #include <boost/proto/core.hpp>
  30. #include <boost/proto/context.hpp>
  31. #include <boost/xpressive/match_results.hpp> // for type_info_less
  32. #include <boost/xpressive/detail/static/transforms/as_action.hpp> // for 'read_attr'
  33. #if BOOST_VERSION >= 103500
  34. # include <boost/proto/fusion.hpp>
  35. # include <boost/fusion/include/transform_view.hpp>
  36. # include <boost/fusion/include/invoke.hpp>
  37. # include <boost/fusion/include/push_front.hpp>
  38. # include <boost/fusion/include/pop_front.hpp>
  39. #endif
  40. #if BOOST_MSVC
  41. #pragma warning(push)
  42. #pragma warning(disable : 4510) // default constructor could not be generated
  43. #pragma warning(disable : 4512) // assignment operator could not be generated
  44. #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required
  45. #endif
  46. namespace boost { namespace xpressive { namespace detail
  47. {
  48. #if BOOST_VERSION >= 103500
  49. struct DataMember
  50. : proto::mem_ptr<proto::_, proto::terminal<proto::_> >
  51. {};
  52. template<typename Expr, long N>
  53. struct child_
  54. : remove_reference<
  55. typename proto::result_of::child_c<Expr &, N>::type
  56. >
  57. {};
  58. ///////////////////////////////////////////////////////////////////////////////
  59. // mem_ptr_eval
  60. // Rewrites expressions of the form x->*foo(a) into foo(x, a) and then
  61. // evaluates them.
  62. template<typename Expr, typename Context, bool IsDataMember = proto::matches<Expr, DataMember>::value>
  63. struct mem_ptr_eval
  64. {
  65. typedef typename child_<Expr, 0>::type left_type;
  66. typedef typename child_<Expr, 1>::type right_type;
  67. typedef
  68. typename proto::result_of::value<
  69. typename proto::result_of::child_c<right_type, 0>::type
  70. >::type
  71. function_type;
  72. typedef
  73. fusion::transform_view<
  74. typename fusion::result_of::push_front<
  75. typename fusion::result_of::pop_front<right_type>::type const
  76. , reference_wrapper<left_type>
  77. >::type const
  78. , proto::eval_fun<Context>
  79. >
  80. evaluated_args;
  81. typedef
  82. typename fusion::result_of::invoke<function_type, evaluated_args>::type
  83. result_type;
  84. result_type operator()(Expr &expr, Context &ctx) const
  85. {
  86. return fusion::invoke<function_type>(
  87. proto::value(proto::child_c<0>(proto::right(expr)))
  88. , evaluated_args(
  89. fusion::push_front(fusion::pop_front(proto::right(expr)), boost::ref(proto::left(expr)))
  90. , proto::eval_fun<Context>(ctx)
  91. )
  92. );
  93. }
  94. };
  95. ///////////////////////////////////////////////////////////////////////////////
  96. // mem_ptr_eval
  97. // Rewrites expressions of the form x->*foo into foo(x) and then
  98. // evaluates them.
  99. template<typename Expr, typename Context>
  100. struct mem_ptr_eval<Expr, Context, true>
  101. {
  102. typedef typename child_<Expr, 0>::type left_type;
  103. typedef typename child_<Expr, 1>::type right_type;
  104. typedef
  105. typename proto::result_of::value<right_type>::type
  106. function_type;
  107. typedef typename boost::result_of<
  108. function_type(typename proto::result_of::eval<left_type, Context>::type)
  109. >::type result_type;
  110. result_type operator()(Expr &expr, Context &ctx) const
  111. {
  112. return proto::value(proto::right(expr))(
  113. proto::eval(proto::left(expr), ctx)
  114. );
  115. }
  116. };
  117. #endif
  118. struct attr_with_default_tag
  119. {};
  120. template<typename T>
  121. struct opt;
  122. ///////////////////////////////////////////////////////////////////////////////
  123. // action_context
  124. //
  125. struct action_context
  126. {
  127. explicit action_context(action_args_type *action_args)
  128. : action_args_(action_args)
  129. {}
  130. action_args_type const &args() const
  131. {
  132. return *this->action_args_;
  133. }
  134. // eval_terminal
  135. template<typename Expr, typename Arg>
  136. struct eval_terminal
  137. : proto::default_eval<Expr, action_context const>
  138. {};
  139. template<typename Expr, typename Arg>
  140. struct eval_terminal<Expr, reference_wrapper<Arg> >
  141. {
  142. typedef Arg &result_type;
  143. result_type operator()(Expr &expr, action_context const &) const
  144. {
  145. return proto::value(expr).get();
  146. }
  147. };
  148. template<typename Expr, typename Arg>
  149. struct eval_terminal<Expr, opt<Arg> >
  150. {
  151. typedef Arg const &result_type;
  152. result_type operator()(Expr &expr, action_context const &) const
  153. {
  154. return proto::value(expr);
  155. }
  156. };
  157. template<typename Expr, typename Type, typename Int>
  158. struct eval_terminal<Expr, action_arg<Type, Int> >
  159. {
  160. typedef typename action_arg<Type, Int>::reference result_type;
  161. result_type operator()(Expr &expr, action_context const &ctx) const
  162. {
  163. action_args_type::const_iterator where_ = ctx.args().find(&typeid(proto::value(expr)));
  164. if(where_ == ctx.args().end())
  165. {
  166. BOOST_THROW_EXCEPTION(
  167. regex_error(
  168. regex_constants::error_badarg
  169. , "An argument to an action was unspecified"
  170. )
  171. );
  172. }
  173. return proto::value(expr).cast(where_->second);
  174. }
  175. };
  176. // eval
  177. template<typename Expr, typename Tag = typename Expr::proto_tag>
  178. struct eval
  179. : proto::default_eval<Expr, action_context const>
  180. {};
  181. template<typename Expr>
  182. struct eval<Expr, proto::tag::terminal>
  183. : eval_terminal<Expr, typename proto::result_of::value<Expr>::type>
  184. {};
  185. // Evaluate attributes like a1|42
  186. template<typename Expr>
  187. struct eval<Expr, attr_with_default_tag>
  188. {
  189. typedef
  190. typename proto::result_of::value<
  191. typename proto::result_of::left<
  192. typename proto::result_of::child<
  193. Expr
  194. >::type
  195. >::type
  196. >::type
  197. temp_type;
  198. typedef typename temp_type::type result_type;
  199. result_type operator ()(Expr const &expr, action_context const &ctx) const
  200. {
  201. return proto::value(proto::left(proto::child(expr))).t_
  202. ? *proto::value(proto::left(proto::child(expr))).t_
  203. : proto::eval(proto::right(proto::child(expr)), ctx);
  204. }
  205. };
  206. #if BOOST_VERSION >= 103500
  207. template<typename Expr>
  208. struct eval<Expr, proto::tag::mem_ptr>
  209. : mem_ptr_eval<Expr, action_context const>
  210. {};
  211. #endif
  212. private:
  213. action_args_type *action_args_;
  214. };
  215. ///////////////////////////////////////////////////////////////////////////////
  216. // action
  217. //
  218. template<typename Actor>
  219. struct action
  220. : actionable
  221. {
  222. action(Actor const &actor)
  223. : actionable()
  224. , actor_(actor)
  225. {
  226. }
  227. virtual void execute(action_args_type *action_args) const
  228. {
  229. action_context const ctx(action_args);
  230. proto::eval(this->actor_, ctx);
  231. }
  232. private:
  233. Actor actor_;
  234. };
  235. ///////////////////////////////////////////////////////////////////////////////
  236. // subreg_transform
  237. //
  238. struct subreg_transform : proto::transform<subreg_transform>
  239. {
  240. template<typename Expr, typename State, typename Data>
  241. struct impl : proto::transform_impl<Expr, State, Data>
  242. {
  243. typedef typename impl::state state_type;
  244. typedef
  245. typename proto::terminal<sub_match<typename state_type::iterator> >::type
  246. result_type;
  247. result_type operator ()(
  248. typename impl::expr_param
  249. , typename impl::state_param state
  250. , typename impl::data_param data
  251. ) const
  252. {
  253. return result_type::make(state.sub_matches_[ data ]);
  254. }
  255. };
  256. };
  257. ///////////////////////////////////////////////////////////////////////////////
  258. // mark_transform
  259. //
  260. struct mark_transform : proto::transform<mark_transform>
  261. {
  262. template<typename Expr, typename State, typename Data>
  263. struct impl : proto::transform_impl<Expr, State, Data>
  264. {
  265. typedef typename impl::state state_type;
  266. typedef
  267. typename proto::terminal<sub_match<typename state_type::iterator> >::type
  268. result_type;
  269. result_type operator ()(
  270. typename impl::expr_param expr
  271. , typename impl::state_param state
  272. , typename impl::data_param
  273. ) const
  274. {
  275. return result_type::make(state.sub_matches_[ proto::value(expr).mark_number_ ]);
  276. }
  277. };
  278. };
  279. ///////////////////////////////////////////////////////////////////////////////
  280. // opt
  281. //
  282. template<typename T>
  283. struct opt
  284. {
  285. typedef T type;
  286. typedef T const &reference;
  287. opt(T const *t)
  288. : t_(t)
  289. {}
  290. operator reference() const
  291. {
  292. BOOST_XPR_ENSURE_(0 != this->t_, regex_constants::error_badattr, "Use of uninitialized regex attribute");
  293. return *this->t_;
  294. }
  295. T const *t_;
  296. };
  297. ///////////////////////////////////////////////////////////////////////////////
  298. // attr_transform
  299. //
  300. struct attr_transform : proto::transform<attr_transform>
  301. {
  302. template<typename Expr, typename State, typename Data>
  303. struct impl : proto::transform_impl<Expr, State, Data>
  304. {
  305. typedef typename impl::expr expr_type;
  306. typedef
  307. typename expr_type::proto_child0::matcher_type::value_type::second_type
  308. attr_type;
  309. typedef
  310. typename proto::terminal<opt<attr_type> >::type
  311. result_type;
  312. result_type operator ()(
  313. typename impl::expr_param
  314. , typename impl::state_param state
  315. , typename impl::data_param
  316. ) const
  317. {
  318. int slot = typename expr_type::proto_child0::nbr_type();
  319. attr_type const *attr = static_cast<attr_type const *>(state.attr_context_.attr_slots_[slot-1]);
  320. return result_type::make(opt<attr_type>(attr));
  321. }
  322. };
  323. };
  324. ///////////////////////////////////////////////////////////////////////////////
  325. // attr_with_default_transform
  326. //
  327. template<typename Grammar, typename Callable = proto::callable>
  328. struct attr_with_default_transform : proto::transform<attr_with_default_transform<Grammar, Callable> >
  329. {
  330. template<typename Expr, typename State, typename Data>
  331. struct impl : proto::transform_impl<Expr, State, Data>
  332. {
  333. typedef
  334. typename proto::unary_expr<
  335. attr_with_default_tag
  336. , typename Grammar::template impl<Expr, State, Data>::result_type
  337. >::type
  338. result_type;
  339. result_type operator ()(
  340. typename impl::expr_param expr
  341. , typename impl::state_param state
  342. , typename impl::data_param data
  343. ) const
  344. {
  345. result_type that = {
  346. typename Grammar::template impl<Expr, State, Data>()(expr, state, data)
  347. };
  348. return that;
  349. }
  350. };
  351. };
  352. ///////////////////////////////////////////////////////////////////////////////
  353. // by_ref_transform
  354. //
  355. struct by_ref_transform : proto::transform<by_ref_transform>
  356. {
  357. template<typename Expr, typename State, typename Data>
  358. struct impl : proto::transform_impl<Expr, State, Data>
  359. {
  360. typedef
  361. typename proto::result_of::value<typename impl::expr_param>::type
  362. reference;
  363. typedef
  364. typename proto::terminal<reference>::type
  365. result_type;
  366. result_type operator ()(
  367. typename impl::expr_param expr
  368. , typename impl::state_param
  369. , typename impl::data_param
  370. ) const
  371. {
  372. return result_type::make(proto::value(expr));
  373. }
  374. };
  375. };
  376. ///////////////////////////////////////////////////////////////////////////////
  377. // BindActionArgs
  378. //
  379. struct BindActionArgs
  380. : proto::or_<
  381. proto::when<proto::terminal<any_matcher>, subreg_transform>
  382. , proto::when<proto::terminal<mark_placeholder>, mark_transform>
  383. , proto::when<proto::terminal<read_attr<proto::_, proto::_> >, attr_transform>
  384. , proto::when<proto::terminal<proto::_>, by_ref_transform>
  385. , proto::when<
  386. proto::bitwise_or<proto::terminal<read_attr<proto::_, proto::_> >, BindActionArgs>
  387. , attr_with_default_transform<proto::bitwise_or<attr_transform, BindActionArgs> >
  388. >
  389. , proto::otherwise<proto::nary_expr<proto::_, proto::vararg<BindActionArgs> > >
  390. >
  391. {};
  392. ///////////////////////////////////////////////////////////////////////////////
  393. // action_matcher
  394. //
  395. template<typename Actor>
  396. struct action_matcher
  397. : quant_style<quant_none, 0, false>
  398. {
  399. int sub_;
  400. Actor actor_;
  401. action_matcher(Actor const &actor, int sub)
  402. : sub_(sub)
  403. , actor_(actor)
  404. {
  405. }
  406. template<typename BidiIter, typename Next>
  407. bool match(match_state<BidiIter> &state, Next const &next) const
  408. {
  409. // Bind the arguments
  410. typedef
  411. typename boost::result_of<BindActionArgs(
  412. Actor const &
  413. , match_state<BidiIter> &
  414. , int const &
  415. )>::type
  416. action_type;
  417. action<action_type> actor(BindActionArgs()(this->actor_, state, this->sub_));
  418. // Put the action in the action list
  419. actionable const **action_list_tail = state.action_list_tail_;
  420. *state.action_list_tail_ = &actor;
  421. state.action_list_tail_ = &actor.next;
  422. // Match the rest of the pattern
  423. if(next.match(state))
  424. {
  425. return true;
  426. }
  427. BOOST_ASSERT(0 == actor.next);
  428. // remove action from list
  429. *action_list_tail = 0;
  430. state.action_list_tail_ = action_list_tail;
  431. return false;
  432. }
  433. };
  434. }}}
  435. #if BOOST_MSVC
  436. #pragma warning(pop)
  437. #endif
  438. #endif