terminal.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  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/include/phoenix_core.hpp>
  15. #include <boost/spirit/include/phoenix_function.hpp>
  16. #include <boost/proto/proto.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. // incomplete type: should not be appeared unused_type in nonlazy arg.
  205. template <>
  206. struct to_nonlazy_arg<unused_type>;
  207. }
  208. template <typename Terminal>
  209. struct terminal
  210. : proto::extends<
  211. typename proto::terminal<Terminal>::type
  212. , terminal<Terminal>
  213. >
  214. {
  215. typedef terminal<Terminal> this_type;
  216. typedef Terminal terminal_type;
  217. typedef proto::extends<
  218. typename proto::terminal<Terminal>::type
  219. , terminal<Terminal>
  220. > base_type;
  221. terminal() {}
  222. terminal(Terminal const& t)
  223. : base_type(proto::terminal<Terminal>::type::make(t))
  224. {}
  225. #if defined(BOOST_MSVC)
  226. #pragma warning(push)
  227. // warning C4348: 'boost::spirit::terminal<...>::result_helper': redefinition of default parameter: parameter 3, 4
  228. #pragma warning(disable: 4348)
  229. #endif
  230. template <
  231. bool Lazy
  232. , typename A0
  233. , typename A1 = unused_type
  234. , typename A2 = unused_type
  235. >
  236. struct result_helper;
  237. #if defined(BOOST_MSVC)
  238. #pragma warning(pop)
  239. #endif
  240. template <
  241. typename A0
  242. >
  243. struct result_helper<false, A0>
  244. {
  245. typedef typename
  246. proto::terminal<
  247. terminal_ex<
  248. Terminal
  249. , typename detail::result_of::make_vector<
  250. typename detail::to_nonlazy_arg<A0>::type>::type>
  251. >::type
  252. type;
  253. };
  254. template <
  255. typename A0
  256. , typename A1
  257. >
  258. struct result_helper<false, A0, A1>
  259. {
  260. typedef typename
  261. proto::terminal<
  262. terminal_ex<
  263. Terminal
  264. , typename detail::result_of::make_vector<
  265. typename detail::to_nonlazy_arg<A0>::type
  266. , typename detail::to_nonlazy_arg<A1>::type>::type>
  267. >::type
  268. type;
  269. };
  270. template <
  271. typename A0
  272. , typename A1
  273. , typename A2
  274. >
  275. struct result_helper<false, A0, A1, A2>
  276. {
  277. typedef typename
  278. proto::terminal<
  279. terminal_ex<
  280. Terminal
  281. , typename detail::result_of::make_vector<
  282. typename detail::to_nonlazy_arg<A0>::type
  283. , typename detail::to_nonlazy_arg<A1>::type
  284. , typename detail::to_nonlazy_arg<A2>::type>::type>
  285. >::type
  286. type;
  287. };
  288. template <
  289. typename A0
  290. , typename A1
  291. , typename A2
  292. >
  293. struct result_helper<true, A0, A1, A2>
  294. {
  295. typedef typename
  296. make_lazy<this_type
  297. , typename detail::to_lazy_arg<A0>::type
  298. , typename detail::to_lazy_arg<A1>::type
  299. , typename detail::to_lazy_arg<A2>::type>::type
  300. type;
  301. };
  302. // FIXME: we need to change this to conform to the result_of protocol
  303. template <
  304. typename A0
  305. , typename A1 = unused_type
  306. , typename A2 = unused_type // Support up to 3 args
  307. >
  308. struct result
  309. {
  310. typedef typename
  311. result_helper<
  312. detail::contains_actor<A0, A1, A2>::value
  313. , A0, A1, A2
  314. >::type
  315. type;
  316. };
  317. template <typename This, typename A0>
  318. struct result<This(A0)>
  319. {
  320. typedef typename
  321. result_helper<
  322. detail::contains_actor<A0, unused_type, unused_type>::value
  323. , A0, unused_type, unused_type
  324. >::type
  325. type;
  326. };
  327. template <typename This, typename A0, typename A1>
  328. struct result<This(A0, A1)>
  329. {
  330. typedef typename
  331. result_helper<
  332. detail::contains_actor<A0, A1, unused_type>::value
  333. , A0, A1, unused_type
  334. >::type
  335. type;
  336. };
  337. template <typename This, typename A0, typename A1, typename A2>
  338. struct result<This(A0, A1, A2)>
  339. {
  340. typedef typename
  341. result_helper<
  342. detail::contains_actor<A0, A1, A2>::value
  343. , A0, A1, A2
  344. >::type
  345. type;
  346. };
  347. // Note: in the following overloads, SFINAE cannot
  348. // be done on return type because of gcc bug #24915:
  349. // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24915
  350. // Hence an additional, fake argument is used for SFINAE,
  351. // using a type which can never be a real argument type.
  352. // Non-lazy overloads. Only enabled when all
  353. // args are immediates (no Phoenix actor).
  354. template <typename A0>
  355. typename result<A0>::type
  356. operator()(A0 const& _0_
  357. , typename detail::contains_actor<A0>::is_false = 0) const
  358. {
  359. typedef typename result<A0>::type result_type;
  360. typedef typename result_type::proto_child0 child_type;
  361. return result_type::make(
  362. child_type(
  363. detail::make_vector(_0_)
  364. , this->proto_base().child0)
  365. );
  366. }
  367. template <typename A0, typename A1>
  368. typename result<A0, A1>::type
  369. operator()(A0 const& _0_, A1 const& _1_
  370. , typename detail::contains_actor<A0, A1>::is_false = 0) const
  371. {
  372. typedef typename result<A0, A1>::type result_type;
  373. typedef typename result_type::proto_child0 child_type;
  374. return result_type::make(
  375. child_type(
  376. detail::make_vector(_0_, _1_)
  377. , this->proto_base().child0)
  378. );
  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_false = 0) const
  384. {
  385. typedef typename result<A0, A1, A2>::type result_type;
  386. typedef typename result_type::proto_child0 child_type;
  387. return result_type::make(
  388. child_type(
  389. detail::make_vector(_0_, _1_, _2_)
  390. , this->proto_base().child0)
  391. );
  392. }
  393. // Lazy overloads. Enabled when at
  394. // least one arg is a Phoenix actor.
  395. template <typename A0>
  396. typename result<A0>::type
  397. operator()(A0 const& _0_
  398. , typename detail::contains_actor<A0>::is_true = 0) const
  399. {
  400. return make_lazy<this_type
  401. , typename phoenix::as_actor<A0>::type>()(*this
  402. , phoenix::as_actor<A0>::convert(_0_));
  403. }
  404. template <typename A0, typename A1>
  405. typename result<A0, A1>::type
  406. operator()(A0 const& _0_, A1 const& _1_
  407. , typename detail::contains_actor<A0, A1>::is_true = 0) const
  408. {
  409. return make_lazy<this_type
  410. , typename phoenix::as_actor<A0>::type
  411. , typename phoenix::as_actor<A1>::type>()(*this
  412. , phoenix::as_actor<A0>::convert(_0_)
  413. , phoenix::as_actor<A1>::convert(_1_));
  414. }
  415. template <typename A0, typename A1, typename A2>
  416. typename result<A0, A1, A2>::type
  417. operator()(A0 const& _0_, A1 const& _1_, A2 const& _2_
  418. , typename detail::contains_actor<A0, A1, A2>::is_true = 0) const
  419. {
  420. return make_lazy<this_type
  421. , typename phoenix::as_actor<A0>::type
  422. , typename phoenix::as_actor<A1>::type
  423. , typename phoenix::as_actor<A2>::type>()(*this
  424. , phoenix::as_actor<A0>::convert(_0_)
  425. , phoenix::as_actor<A1>::convert(_1_)
  426. , phoenix::as_actor<A2>::convert(_2_));
  427. }
  428. // silence MSVC warning C4512: assignment operator could not be generated
  429. BOOST_DELETED_FUNCTION(terminal& operator= (terminal const&))
  430. };
  431. ///////////////////////////////////////////////////////////////////////////
  432. namespace result_of
  433. {
  434. // Calculate the type of the compound terminal if generated by one of
  435. // the spirit::terminal::operator() overloads above
  436. // The terminal type itself is passed through without modification
  437. template <typename Tag>
  438. struct terminal
  439. {
  440. typedef spirit::terminal<Tag> type;
  441. };
  442. template <typename Tag, typename A0>
  443. struct terminal<Tag(A0)>
  444. {
  445. typedef typename spirit::terminal<Tag>::
  446. template result<A0>::type type;
  447. };
  448. template <typename Tag, typename A0, typename A1>
  449. struct terminal<Tag(A0, A1)>
  450. {
  451. typedef typename spirit::terminal<Tag>::
  452. template result<A0, A1>::type type;
  453. };
  454. template <typename Tag, typename A0, typename A1, typename A2>
  455. struct terminal<Tag(A0, A1, A2)>
  456. {
  457. typedef typename spirit::terminal<Tag>::
  458. template result<A0, A1, A2>::type type;
  459. };
  460. }
  461. ///////////////////////////////////////////////////////////////////////////
  462. // support for stateful tag types
  463. namespace tag
  464. {
  465. template <
  466. typename Data, typename Tag
  467. , typename DataTag1 = unused_type, typename DataTag2 = unused_type>
  468. struct stateful_tag
  469. {
  470. BOOST_SPIRIT_IS_TAG()
  471. typedef Data data_type;
  472. stateful_tag() {}
  473. stateful_tag(data_type const& data) : data_(data) {}
  474. data_type data_;
  475. // silence MSVC warning C4512: assignment operator could not be generated
  476. BOOST_DELETED_FUNCTION(stateful_tag& operator= (stateful_tag const&))
  477. };
  478. }
  479. template <
  480. typename Data, typename Tag
  481. , typename DataTag1 = unused_type, typename DataTag2 = unused_type>
  482. struct stateful_tag_type
  483. : spirit::terminal<tag::stateful_tag<Data, Tag, DataTag1, DataTag2> >
  484. {
  485. typedef tag::stateful_tag<Data, Tag, DataTag1, DataTag2> tag_type;
  486. stateful_tag_type() {}
  487. stateful_tag_type(Data const& data)
  488. : spirit::terminal<tag_type>(data)
  489. {}
  490. // silence MSVC warning C4512: assignment operator could not be generated
  491. BOOST_DELETED_FUNCTION(stateful_tag_type& operator= (stateful_tag_type const&))
  492. };
  493. namespace detail
  494. {
  495. // extract expression if this is a Tag
  496. template <typename StatefulTag>
  497. struct get_stateful_data
  498. {
  499. typedef typename StatefulTag::data_type data_type;
  500. // is invoked if given tag is != Tag
  501. template <typename Tag_>
  502. static data_type call(Tag_) { return data_type(); }
  503. // this is invoked if given tag is same as'Tag'
  504. static data_type const& call(StatefulTag const& t) { return t.data_; }
  505. };
  506. }
  507. }}
  508. namespace boost { namespace phoenix
  509. {
  510. template <typename Tag>
  511. struct is_custom_terminal<Tag, typename Tag::is_spirit_tag>
  512. : mpl::true_
  513. {};
  514. template <typename Tag>
  515. struct custom_terminal<Tag, typename Tag::is_spirit_tag>
  516. {
  517. #ifndef BOOST_PHOENIX_NO_SPECIALIZE_CUSTOM_TERMINAL
  518. typedef void _is_default_custom_terminal; // fix for #7730
  519. #endif
  520. typedef spirit::terminal<Tag> result_type;
  521. template <typename Context>
  522. result_type operator()(Tag const & t, Context const &)
  523. {
  524. return spirit::terminal<Tag>(t);
  525. }
  526. };
  527. }}
  528. // Define a spirit 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. #define BOOST_SPIRIT_TERMINAL_X(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_Y
  532. #define BOOST_SPIRIT_TERMINAL_Y(x, y) ((x, y)) BOOST_SPIRIT_TERMINAL_X
  533. #define BOOST_SPIRIT_TERMINAL_X0
  534. #define BOOST_SPIRIT_TERMINAL_Y0
  535. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  536. #define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \
  537. namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
  538. typedef boost::proto::terminal<tag::name>::type type_name; \
  539. type_name const name = {{}}; \
  540. inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \
  541. /***/
  542. #else
  543. #define BOOST_SPIRIT_TERMINAL_NAME(name, type_name) \
  544. namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
  545. typedef boost::proto::terminal<tag::name>::type type_name; \
  546. /***/
  547. #endif
  548. #define BOOST_SPIRIT_TERMINAL(name) \
  549. BOOST_SPIRIT_TERMINAL_NAME(name, name ## _type) \
  550. /***/
  551. #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A(r, _, names) \
  552. BOOST_SPIRIT_TERMINAL_NAME( \
  553. BOOST_PP_TUPLE_ELEM(2, 0, names), \
  554. BOOST_PP_TUPLE_ELEM(2, 1, names) \
  555. ) \
  556. /***/
  557. #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME(seq) \
  558. BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_A, _, \
  559. BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \
  560. /***/
  561. // Define a spirit extended terminal. This macro may be placed in any namespace.
  562. // Common placeholders are placed in the main boost::spirit namespace
  563. // (see common_terminals.hpp)
  564. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  565. #define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \
  566. namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
  567. typedef boost::spirit::terminal<tag::name> type_name; \
  568. type_name const name = type_name(); \
  569. inline void BOOST_PP_CAT(silence_unused_warnings_, name)() { (void) name; } \
  570. /***/
  571. #else
  572. #define BOOST_SPIRIT_TERMINAL_NAME_EX(name, type_name) \
  573. namespace tag { struct name { BOOST_SPIRIT_IS_TAG() }; } \
  574. typedef boost::spirit::terminal<tag::name> type_name; \
  575. /***/
  576. #endif
  577. #define BOOST_SPIRIT_TERMINAL_EX(name) \
  578. BOOST_SPIRIT_TERMINAL_NAME_EX(name, name ## _type) \
  579. /***/
  580. #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A(r, _, names) \
  581. BOOST_SPIRIT_TERMINAL_NAME_EX( \
  582. BOOST_PP_TUPLE_ELEM(2, 0, names), \
  583. BOOST_PP_TUPLE_ELEM(2, 1, names) \
  584. ) \
  585. /***/
  586. #define BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX(seq) \
  587. BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX_A, _, \
  588. BOOST_PP_CAT(BOOST_SPIRIT_TERMINAL_X seq, 0)) \
  589. /***/
  590. #endif