terminal.hpp 23 KB

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