terminal.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  4. Copyright (c) 2011 Thomas Heller
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. ==============================================================================*/
  8. #if !defined(BOOST_SPIRIT_TERMINAL_NOVEMBER_04_2008_0906AM)
  9. #define BOOST_SPIRIT_TERMINAL_NOVEMBER_04_2008_0906AM
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/spirit/include/phoenix_core.hpp>
  14. #include <boost/spirit/include/phoenix_function.hpp>
  15. #include <boost/proto/proto.hpp>
  16. #include <boost/fusion/include/void.hpp>
  17. #include <boost/spirit/home/support/meta_compiler.hpp>
  18. #include <boost/spirit/home/support/detail/make_vector.hpp>
  19. #include <boost/spirit/home/support/unused.hpp>
  20. #include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
  21. #include <boost/preprocessor/tuple/elem.hpp>
  22. #include <boost/spirit/home/support/terminal_expression.hpp>
  23. namespace boost { namespace spirit
  24. {
  25. template <typename Terminal, typename Args>
  26. struct terminal_ex
  27. {
  28. typedef Terminal terminal_type;
  29. typedef Args args_type;
  30. terminal_ex(Args const& args_)
  31. : args(args_) {}
  32. terminal_ex(Args const& args_, Terminal const& term_)
  33. : args(args_), term(term_) {}
  34. Args args; // Args is guaranteed to be a fusion::vectorN so you
  35. // can use that template for detection and specialization
  36. Terminal term;
  37. };
  38. template <typename Terminal, typename Actor, int Arity>
  39. struct lazy_terminal
  40. {
  41. typedef Terminal terminal_type;
  42. typedef Actor actor_type;
  43. static int const arity = Arity;
  44. lazy_terminal(Actor const& actor_)
  45. : actor(actor_) {}
  46. lazy_terminal(Actor const& actor_, Terminal const& term_)
  47. : actor(actor_), term(term_) {}
  48. Actor actor;
  49. Terminal term;
  50. };
  51. template <typename Domain, typename Terminal, int Arity, typename Enable = void>
  52. struct use_lazy_terminal : mpl::false_ {};
  53. template <typename Domain, typename Terminal, int Arity, typename Enable = void>
  54. struct use_lazy_directive : mpl::false_ {};
  55. template <typename Terminal>
  56. struct terminal;
  57. template <typename Domain, typename Terminal>
  58. struct use_terminal<Domain, terminal<Terminal> >
  59. : use_terminal<Domain, Terminal> {};
  60. template <typename Domain, typename Terminal, int Arity, typename Actor>
  61. struct use_terminal<Domain, lazy_terminal<Terminal, Actor, Arity> >
  62. : use_lazy_terminal<Domain, Terminal, Arity> {};
  63. template <typename Domain, typename Terminal, int Arity, typename Actor>
  64. struct use_directive<Domain, lazy_terminal<Terminal, Actor, Arity> >
  65. : use_lazy_directive<Domain, Terminal, Arity> {};
  66. template <
  67. typename F
  68. , typename A0 = unused_type
  69. , typename A1 = unused_type
  70. , typename A2 = unused_type
  71. , typename Unused = unused_type
  72. >
  73. struct make_lazy;
  74. template <typename F, typename A0>
  75. struct make_lazy<F, A0>
  76. {
  77. typedef typename
  78. proto::terminal<
  79. lazy_terminal<
  80. typename F::terminal_type
  81. , typename phoenix::detail::expression::function_eval<F, A0>::type
  82. , 1 // arity
  83. >
  84. >::type
  85. result_type;
  86. typedef result_type type;
  87. result_type
  88. operator()(F f, A0 const& _0_) const
  89. {
  90. typedef typename result_type::proto_child0 child_type;
  91. return result_type::make(child_type(
  92. phoenix::detail::expression::function_eval<F, A0>::make(f, _0_)
  93. , f.proto_base().child0
  94. ));
  95. }
  96. };
  97. template <typename F, typename A0, typename A1>
  98. struct make_lazy<F, A0, A1>
  99. {
  100. typedef typename
  101. proto::terminal<
  102. lazy_terminal<
  103. typename F::terminal_type
  104. , typename phoenix::detail::expression::function_eval<F, A0, A1>::type
  105. , 2 // arity
  106. >
  107. >::type
  108. result_type;
  109. typedef result_type type;
  110. result_type
  111. operator()(F f, A0 const& _0_, A1 const& _1_) const
  112. {
  113. typedef typename result_type::proto_child0 child_type;
  114. return result_type::make(child_type(
  115. phoenix::detail::expression::function_eval<F, A0, A1>::make(f, _0_, _1_)
  116. , f.proto_base().child0
  117. ));
  118. }
  119. };
  120. template <typename F, typename A0, typename A1, typename A2>
  121. struct make_lazy<F, A0, A1, A2>
  122. {
  123. typedef typename
  124. proto::terminal<
  125. lazy_terminal<
  126. typename F::terminal_type
  127. , typename phoenix::detail::expression::function_eval<F, A0, A1, A2>::type
  128. , 3 // arity
  129. >
  130. >::type
  131. result_type;
  132. typedef result_type type;
  133. result_type
  134. operator()(F f, A0 const& _0_, A1 const& _1_, A2 const& _2_) const
  135. {
  136. typedef typename result_type::proto_child0 child_type;
  137. return result_type::make(child_type(
  138. phoenix::detail::expression::function_eval<F, A0, A1, A2>::make(f, _0_, _1_, _2_)
  139. , f.proto_base().child0
  140. ));
  141. }
  142. };
  143. namespace detail
  144. {
  145. // Helper struct for SFINAE purposes
  146. template <bool C> struct bool_;
  147. template <>
  148. struct bool_<true> : mpl::bool_<true>
  149. {
  150. typedef bool_<true>* is_true;
  151. };
  152. template <>
  153. struct bool_<false> : mpl::bool_<false>
  154. {
  155. typedef bool_<false>* is_false;
  156. };
  157. // Metafunction to detect if at least one arg is a Phoenix actor
  158. template <
  159. typename A0
  160. , typename A1 = unused_type
  161. , typename A2 = unused_type
  162. >
  163. struct contains_actor
  164. : bool_<
  165. phoenix::is_actor<A0>::value
  166. || phoenix::is_actor<A1>::value
  167. || phoenix::is_actor<A2>::value
  168. >
  169. {};
  170. // to_lazy_arg: convert a terminal arg type to the type make_lazy needs
  171. template <typename A>
  172. struct to_lazy_arg
  173. : phoenix::as_actor<A> // wrap A in a Phoenix actor if not already one
  174. {};
  175. template <typename A>
  176. struct to_lazy_arg<const A>
  177. : to_lazy_arg<A>
  178. {};
  179. template <typename A>
  180. struct to_lazy_arg<A &>
  181. : to_lazy_arg<A>
  182. {};
  183. template <>
  184. struct to_lazy_arg<unused_type>
  185. {
  186. // unused arg: make_lazy wants unused_type
  187. typedef unused_type type;
  188. };
  189. // to_nonlazy_arg: convert a terminal arg type to the type make_vector needs
  190. template <typename A>
  191. struct to_nonlazy_arg
  192. {
  193. // identity
  194. typedef A type;
  195. };
  196. template <typename A>
  197. struct to_nonlazy_arg<const A>
  198. : to_nonlazy_arg<A>
  199. {};
  200. template <typename A>
  201. struct to_nonlazy_arg<A &>
  202. : to_nonlazy_arg<A>
  203. {};
  204. template <>
  205. struct to_nonlazy_arg<unused_type>
  206. {
  207. // unused arg: make_vector wants fusion::void_
  208. typedef fusion::void_ type;
  209. };
  210. }
  211. template <typename Terminal>
  212. struct terminal
  213. : proto::extends<
  214. typename proto::terminal<Terminal>::type
  215. , terminal<Terminal>
  216. >
  217. {
  218. typedef terminal<Terminal> this_type;
  219. typedef Terminal terminal_type;
  220. typedef proto::extends<
  221. typename proto::terminal<Terminal>::type
  222. , terminal<Terminal>
  223. > base_type;
  224. terminal() {}
  225. terminal(Terminal const& t)
  226. : base_type(proto::terminal<Terminal>::type::make(t))
  227. {}
  228. template <
  229. bool Lazy
  230. , typename A0
  231. , typename A1
  232. , typename A2
  233. >
  234. struct result_helper;
  235. template <
  236. typename A0
  237. , typename A1
  238. , typename A2
  239. >
  240. struct result_helper<false, A0, A1, A2>
  241. {
  242. typedef typename
  243. proto::terminal<
  244. terminal_ex<
  245. Terminal
  246. , typename detail::result_of::make_vector<
  247. typename detail::to_nonlazy_arg<A0>::type
  248. , typename detail::to_nonlazy_arg<A1>::type
  249. , typename detail::to_nonlazy_arg<A2>::type>::type>
  250. >::type
  251. type;
  252. };
  253. template <
  254. typename A0
  255. , typename A1
  256. , typename A2
  257. >
  258. struct result_helper<true, A0, A1, A2>
  259. {
  260. typedef typename
  261. make_lazy<this_type
  262. , typename detail::to_lazy_arg<A0>::type
  263. , typename detail::to_lazy_arg<A1>::type
  264. , typename detail::to_lazy_arg<A2>::type>::type
  265. type;
  266. };
  267. // FIXME: we need to change this to conform to the result_of protocol
  268. template <
  269. typename A0
  270. , typename A1 = unused_type
  271. , typename A2 = unused_type // Support up to 3 args
  272. >
  273. struct result
  274. {
  275. typedef typename
  276. result_helper<
  277. detail::contains_actor<A0, A1, A2>::value
  278. , A0, A1, A2
  279. >::type
  280. type;
  281. };
  282. template <typename This, typename A0>
  283. struct result<This(A0)>
  284. {
  285. typedef typename
  286. result_helper<
  287. detail::contains_actor<A0, unused_type, unused_type>::value
  288. , A0, unused_type, unused_type
  289. >::type
  290. type;
  291. };
  292. template <typename This, typename A0, typename A1>
  293. struct result<This(A0, A1)>
  294. {
  295. typedef typename
  296. result_helper<
  297. detail::contains_actor<A0, A1, unused_type>::value
  298. , A0, A1, unused_type
  299. >::type
  300. type;
  301. };
  302. template <typename This, typename A0, typename A1, typename A2>
  303. struct result<This(A0, A1, A2)>
  304. {
  305. typedef typename
  306. result_helper<
  307. detail::contains_actor<A0, A1, A2>::value
  308. , A0, A1, A2
  309. >::type
  310. type;
  311. };
  312. // Note: in the following overloads, SFINAE cannot
  313. // be done on return type because of gcc bug #24915:
  314. // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24915
  315. // Hence an additional, fake argument is used for SFINAE,
  316. // using a type which can never be a real argument type.
  317. // Non-lazy overloads. Only enabled when all
  318. // args are immediates (no Phoenix actor).
  319. template <typename A0>
  320. typename result<A0>::type
  321. operator()(A0 const& _0_
  322. , typename detail::contains_actor<A0>::is_false = 0) const
  323. {
  324. typedef typename result<A0>::type result_type;
  325. typedef typename result_type::proto_child0 child_type;
  326. return result_type::make(
  327. child_type(
  328. detail::make_vector(_0_)
  329. , this->proto_base().child0)
  330. );
  331. }
  332. template <typename A0, typename A1>
  333. typename result<A0, A1>::type
  334. operator()(A0 const& _0_, A1 const& _1_
  335. , typename detail::contains_actor<A0, A1>::is_false = 0) const
  336. {
  337. typedef typename result<A0, A1>::type result_type;
  338. typedef typename result_type::proto_child0 child_type;
  339. return result_type::make(
  340. child_type(
  341. detail::make_vector(_0_, _1_)
  342. , this->proto_base().child0)
  343. );
  344. }
  345. template <typename A0, typename A1, typename A2>
  346. typename result<A0, A1, A2>::type
  347. operator()(A0 const& _0_, A1 const& _1_, A2 const& _2_
  348. , typename detail::contains_actor<A0, A1, A2>::is_false = 0) const
  349. {
  350. typedef typename result<A0, A1, A2>::type result_type;
  351. typedef typename result_type::proto_child0 child_type;
  352. return result_type::make(
  353. child_type(
  354. detail::make_vector(_0_, _1_, _2_)
  355. , this->proto_base().child0)
  356. );
  357. }
  358. // Lazy overloads. Enabled when at
  359. // least one arg is a Phoenix actor.
  360. template <typename A0>
  361. typename result<A0>::type
  362. operator()(A0 const& _0_
  363. , typename detail::contains_actor<A0>::is_true = 0) const
  364. {
  365. return make_lazy<this_type
  366. , typename phoenix::as_actor<A0>::type>()(*this
  367. , phoenix::as_actor<A0>::convert(_0_));
  368. }
  369. template <typename A0, typename A1>
  370. typename result<A0, A1>::type
  371. operator()(A0 const& _0_, A1 const& _1_
  372. , typename detail::contains_actor<A0, A1>::is_true = 0) const
  373. {
  374. return make_lazy<this_type
  375. , typename phoenix::as_actor<A0>::type
  376. , typename phoenix::as_actor<A1>::type>()(*this
  377. , phoenix::as_actor<A0>::convert(_0_)
  378. , phoenix::as_actor<A1>::convert(_1_));
  379. }
  380. template <typename A0, typename A1, typename A2>
  381. typename result<A0, A1, A2>::type
  382. operator()(A0 const& _0_, A1 const& _1_, A2 const& _2_
  383. , typename detail::contains_actor<A0, A1, A2>::is_true = 0) const
  384. {
  385. return make_lazy<this_type
  386. , typename phoenix::as_actor<A0>::type
  387. , typename phoenix::as_actor<A1>::type
  388. , typename phoenix::as_actor<A2>::type>()(*this
  389. , phoenix::as_actor<A0>::convert(_0_)
  390. , phoenix::as_actor<A1>::convert(_1_)
  391. , phoenix::as_actor<A2>::convert(_2_));
  392. }
  393. private:
  394. // silence MSVC warning C4512: assignment operator could not be generated
  395. terminal& operator= (terminal const&);
  396. };
  397. ///////////////////////////////////////////////////////////////////////////
  398. namespace result_of
  399. {
  400. // Calculate the type of the compound terminal if generated by one of
  401. // the spirit::terminal::operator() overloads above
  402. // The terminal type itself is passed through without modification
  403. template <typename Tag>
  404. struct terminal
  405. {
  406. typedef spirit::terminal<Tag> type;
  407. };
  408. template <typename Tag, typename A0>
  409. struct terminal<Tag(A0)>
  410. {
  411. typedef typename spirit::terminal<Tag>::
  412. template result<A0>::type type;
  413. };
  414. template <typename Tag, typename A0, typename A1>
  415. struct terminal<Tag(A0, A1)>
  416. {
  417. typedef typename spirit::terminal<Tag>::
  418. template result<A0, A1>::type type;
  419. };
  420. template <typename Tag, typename A0, typename A1, typename A2>
  421. struct terminal<Tag(A0, A1, A2)>
  422. {
  423. typedef typename spirit::terminal<Tag>::
  424. template result<A0, A1, A2>::type type;
  425. };
  426. }
  427. ///////////////////////////////////////////////////////////////////////////
  428. // support for stateful tag types
  429. namespace tag
  430. {
  431. template <
  432. typename Data, typename Tag
  433. , typename DataTag1 = unused_type, typename DataTag2 = unused_type>
  434. struct stateful_tag
  435. {
  436. BOOST_SPIRIT_IS_TAG()
  437. typedef Data data_type;
  438. stateful_tag() {}
  439. stateful_tag(data_type const& data) : data_(data) {}
  440. data_type data_;
  441. private:
  442. // silence MSVC warning C4512: assignment operator could not be generated
  443. stateful_tag& operator= (stateful_tag const&);
  444. };
  445. }
  446. template <
  447. typename Data, typename Tag
  448. , typename DataTag1 = unused_type, typename DataTag2 = unused_type>
  449. struct stateful_tag_type
  450. : spirit::terminal<tag::stateful_tag<Data, Tag, DataTag1, DataTag2> >
  451. {
  452. typedef tag::stateful_tag<Data, Tag, DataTag1, DataTag2> tag_type;
  453. stateful_tag_type() {}
  454. stateful_tag_type(Data const& data)
  455. : spirit::terminal<tag_type>(data)
  456. {}
  457. private:
  458. // silence MSVC warning C4512: assignment operator could not be generated
  459. stateful_tag_type& operator= (stateful_tag_type const&);
  460. };
  461. namespace detail
  462. {
  463. // extract expression if this is a Tag
  464. template <typename StatefulTag>
  465. struct get_stateful_data
  466. {
  467. typedef typename StatefulTag::data_type data_type;
  468. // is invoked if given tag is != Tag
  469. template <typename Tag_>
  470. static data_type call(Tag_) { return data_type(); }
  471. // this is invoked if given tag is same as'Tag'
  472. static data_type const& call(StatefulTag const& t) { return t.data_; }
  473. };
  474. }
  475. }}
  476. #ifdef BOOST_SPIRIT_USE_PHOENIX_V3
  477. namespace boost { namespace phoenix
  478. {
  479. template <typename Tag>
  480. struct is_custom_terminal<Tag, typename Tag::is_spirit_tag>
  481. : mpl::true_
  482. {};
  483. template <typename Tag>
  484. struct custom_terminal<Tag, typename Tag::is_spirit_tag>
  485. {
  486. typedef spirit::terminal<Tag> result_type;
  487. template <typename Context>
  488. result_type operator()(Tag const & t, Context const &)
  489. {
  490. return spirit::terminal<Tag>(t);
  491. }
  492. };
  493. }}
  494. #endif
  495. // Define a spirit terminal. This macro may be placed in any namespace.
  496. // Common placeholders are placed in the main boost::spirit namespace
  497. // (see common_terminals.hpp)
  498. #define BOOST_SPIRIT_TERMINAL_X(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_Y
  499. #define BOOST_SPIRIT_TERMINAL_Y(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_X
  500. #define BOOST_SPIRIT_TERMINAL_X0
  501. #define BOOST_SPIRIT_TERMINAL_Y0
  502. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  503. #define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \
  504. namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
  505. typedef boost::proto::terminal<tag::name>::type type_name; \
  506. type_name const name = {{}}; \
  507. inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \
  508. /***/
  509. #else
  510. #define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \
  511. namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
  512. typedef boost::proto::terminal<tag::name>::type type_name; \
  513. /***/
  514. #endif
  515. #define BOOST_SPIRIT_TERMINAL(name) \
  516. BOOST_SPIRIT_TERMINAL_NAME(name, name ## _type) \
  517. /***/
  518. #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A(r, _, names) \
  519. BOOST_SPIRIT_TERMINAL_NAME( \
  520. BOOST_PP_TUPLE_ELEM(2, 0, names), \
  521. BOOST_PP_TUPLE_ELEM(2, 1, names) \
  522. ) \
  523. /***/
  524. #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME(seq) \
  525. BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A, _, \
  526. BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \
  527. /***/
  528. // Define a spirit extended terminal. This macro may be placed in any namespace.
  529. // Common placeholders are placed in the main boost::spirit namespace
  530. // (see common_terminals.hpp)
  531. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  532. #define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \
  533. namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
  534. typedef boost::spirit::terminal<tag::name> type_name; \
  535. type_name const name = type_name(); \
  536. inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \
  537. /***/
  538. #else
  539. #define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \
  540. namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
  541. typedef boost::spirit::terminal<tag::name> type_name; \
  542. /***/
  543. #endif
  544. #define BOOST_SPIRIT_TERMINAL_EX(name) \
  545. BOOST_SPIRIT_TERMINAL_NAME_EX(name, name ## _type) \
  546. /***/
  547. #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A(r, _, names) \
  548. BOOST_SPIRIT_TERMINAL_NAME_EX( \
  549. BOOST_PP_TUPLE_ELEM(2, 0, names), \
  550. BOOST_PP_TUPLE_ELEM(2, 1, names) \
  551. ) \
  552. /***/
  553. #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX(seq) \
  554. BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A, _, \
  555. BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \
  556. /***/
  557. #endif