/src/contrib/boost/spirit/home/classic/dynamic/impl/switch.ipp

http://pythonocc.googlecode.com/ · C++ Header · 574 lines · 360 code · 94 blank · 120 comment · 10 complexity · cedf966bc7e83c3a19831ed21e948ac1 MD5 · raw file

  1. /*=============================================================================
  2. Copyright (c) 2003 Hartmut Kaiser
  3. http://spirit.sourceforge.net/
  4. Use, modification and distribution is subject to the Boost Software
  5. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #ifndef BOOST_SPIRIT_SWITCH_IPP
  9. #define BOOST_SPIRIT_SWITCH_IPP
  10. #include <boost/mpl/if.hpp>
  11. #include <boost/type_traits/is_same.hpp>
  12. #include <boost/static_assert.hpp>
  13. #include <boost/preprocessor/cat.hpp>
  14. #include <boost/preprocessor/inc.hpp>
  15. #include <boost/preprocessor/repeat.hpp>
  16. #include <boost/preprocessor/repeat_from_to.hpp>
  17. #include <boost/spirit/home/classic/core/parser.hpp>
  18. #include <boost/spirit/home/classic/core/primitives/primitives.hpp>
  19. #include <boost/spirit/home/classic/core/composite/composite.hpp>
  20. #include <boost/spirit/home/classic/meta/as_parser.hpp>
  21. #include <boost/spirit/home/classic/phoenix/actor.hpp>
  22. #include <boost/spirit/home/classic/phoenix/tuples.hpp>
  23. ///////////////////////////////////////////////////////////////////////////////
  24. namespace boost { namespace spirit {
  25. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  26. // forward declaration
  27. template <int N, typename ParserT, bool IsDefault> struct case_parser;
  28. ///////////////////////////////////////////////////////////////////////////////
  29. namespace impl {
  30. ///////////////////////////////////////////////////////////////////////////////
  31. // parse helper functions
  32. template <typename ParserT, typename ScannerT>
  33. inline typename parser_result<ParserT, ScannerT>::type
  34. delegate_parse(ParserT const &p, ScannerT const &scan,
  35. typename ScannerT::iterator_t const save)
  36. {
  37. typedef typename parser_result<ParserT, ScannerT>::type result_t;
  38. result_t result (p.subject().parse(scan));
  39. if (!result)
  40. scan.first = save;
  41. return result;
  42. }
  43. ///////////////////////////////////////////////////////////////////////////////
  44. // General default case handling (no default_p case branch given).
  45. // First try to match the current parser node (if the condition value is
  46. // matched) and, if that fails, return a no_match
  47. template <int N, bool IsDefault, bool HasDefault>
  48. struct default_delegate_parse {
  49. template <
  50. typename ParserT, typename DefaultT,
  51. typename ValueT, typename ScannerT
  52. >
  53. static typename parser_result<ParserT, ScannerT>::type
  54. parse (ValueT const &value, ParserT const &p, DefaultT const &,
  55. ScannerT const &scan, typename ScannerT::iterator_t const save)
  56. {
  57. if (value == N)
  58. return delegate_parse(p, scan, save);
  59. return scan.no_match();
  60. }
  61. };
  62. // The current case parser node is the default parser.
  63. // Ignore the given case value and try to match the given default parser.
  64. template <int N, bool HasDefault>
  65. struct default_delegate_parse<N, true, HasDefault> {
  66. template <
  67. typename ParserT, typename DefaultT,
  68. typename ValueT, typename ScannerT
  69. >
  70. static typename parser_result<ParserT, ScannerT>::type
  71. parse (ValueT const& /*value*/, ParserT const &, DefaultT const &d,
  72. ScannerT const &scan, typename ScannerT::iterator_t const save)
  73. {
  74. // Since there is a default_p case branch defined, the corresponding
  75. // parser shouldn't be the nothing_parser
  76. BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value));
  77. return delegate_parse(d, scan, save);
  78. }
  79. };
  80. // The current case parser node is not the default parser, but there is a
  81. // default_p branch given inside the switch_p parser.
  82. // First try to match the current parser node (if the condition value is
  83. // matched) and, if that fails, match the given default_p parser.
  84. template <int N>
  85. struct default_delegate_parse<N, false, true> {
  86. template <
  87. typename ParserT, typename DefaultT,
  88. typename ValueT, typename ScannerT
  89. >
  90. static typename parser_result<ParserT, ScannerT>::type
  91. parse (ValueT const &value, ParserT const &p, DefaultT const &d,
  92. ScannerT const &scan, typename ScannerT::iterator_t const save)
  93. {
  94. // Since there is a default_p case branch defined, the corresponding
  95. // parser shouldn't be the nothing_parser
  96. BOOST_STATIC_ASSERT((!boost::is_same<DefaultT, nothing_parser>::value));
  97. if (value == N)
  98. return delegate_parse(p, scan, save);
  99. return delegate_parse(d, scan, save);
  100. }
  101. };
  102. ///////////////////////////////////////////////////////////////////////////////
  103. // Look through the case parser chain to test, if there is a default case
  104. // branch defined (returned by 'value').
  105. template <typename CaseT, bool IsSimple = CaseT::is_simple>
  106. struct default_case;
  107. ////////////////////////////////////////
  108. template <typename ResultT, bool IsDefault>
  109. struct get_default_parser {
  110. template <typename ParserT>
  111. static ResultT
  112. get(parser<ParserT> const &p)
  113. {
  114. return default_case<typename ParserT::derived_t::left_t>::
  115. get(p.derived().left());
  116. }
  117. };
  118. template <typename ResultT>
  119. struct get_default_parser<ResultT, true> {
  120. template <typename ParserT>
  121. static ResultT
  122. get(parser<ParserT> const &p) { return p.derived().right(); }
  123. };
  124. ////////////////////////////////////////
  125. template <typename CaseT, bool IsSimple>
  126. struct default_case {
  127. // The 'value' constant is true, if the current case_parser or one of its
  128. // left siblings is a default_p generated case_parser.
  129. BOOST_STATIC_CONSTANT(bool, value =
  130. (CaseT::is_default || default_case<typename CaseT::left_t>::value));
  131. // The 'is_epsilon' constant is true, if the current case_parser or one of
  132. // its left siblings is a default_p generated parser with an attached
  133. // epsilon_p (this is generated by the plain default_p).
  134. BOOST_STATIC_CONSTANT(bool, is_epsilon = (
  135. (CaseT::is_default && CaseT::is_epsilon) ||
  136. default_case<typename CaseT::left_t>::is_epsilon
  137. ));
  138. // The computed 'type' represents the type of the default case branch
  139. // parser (if there is one) or nothing_parser (if there isn't any default
  140. // case branch).
  141. typedef typename boost::mpl::if_c<
  142. CaseT::is_default, typename CaseT::right_embed_t,
  143. typename default_case<typename CaseT::left_t>::type
  144. >::type type;
  145. // The get function returns the parser attached to the default case branch
  146. // (if there is one) or an instance of a nothing_parser (if there isn't
  147. // any default case branch).
  148. template <typename ParserT>
  149. static type
  150. get(parser<ParserT> const &p)
  151. { return get_default_parser<type, CaseT::is_default>::get(p); }
  152. };
  153. ////////////////////////////////////////
  154. template <typename ResultT, bool IsDefault>
  155. struct get_default_parser_simple {
  156. template <typename ParserT>
  157. static ResultT
  158. get(parser<ParserT> const &p) { return p.derived(); }
  159. };
  160. template <typename ResultT>
  161. struct get_default_parser_simple<ResultT, false> {
  162. template <typename ParserT>
  163. static nothing_parser
  164. get(parser<ParserT> const &) { return nothing_p; }
  165. };
  166. ////////////////////////////////////////
  167. // Specialization of the default_case template for the last (leftmost) element
  168. // of the case parser chain.
  169. template <typename CaseT>
  170. struct default_case<CaseT, true> {
  171. // The 'value' and 'is_epsilon' constant, the 'type' type and the function
  172. // 'get' are described above.
  173. BOOST_STATIC_CONSTANT(bool, value = CaseT::is_default);
  174. BOOST_STATIC_CONSTANT(bool, is_epsilon = (
  175. CaseT::is_default && CaseT::is_epsilon
  176. ));
  177. typedef typename boost::mpl::if_c<
  178. CaseT::is_default, CaseT, nothing_parser
  179. >::type type;
  180. template <typename ParserT>
  181. static type
  182. get(parser<ParserT> const &p)
  183. { return get_default_parser_simple<type, value>::get(p); }
  184. };
  185. ///////////////////////////////////////////////////////////////////////////////
  186. // The case_chain template calculates recursivly the depth of the left
  187. // subchain of the given case branch node.
  188. template <typename CaseT, bool IsSimple = CaseT::is_simple>
  189. struct case_chain {
  190. BOOST_STATIC_CONSTANT(int, depth = (
  191. case_chain<typename CaseT::left_t>::depth + 1
  192. ));
  193. };
  194. template <typename CaseT>
  195. struct case_chain<CaseT, true> {
  196. BOOST_STATIC_CONSTANT(int, depth = 0);
  197. };
  198. ///////////////////////////////////////////////////////////////////////////////
  199. // The chain_parser template is used to extract the type and the instance of
  200. // a left or a right parser, burried arbitrary deep inside the case parser
  201. // chain.
  202. template <int Depth, typename CaseT>
  203. struct chain_parser {
  204. typedef typename CaseT::left_t our_left_t;
  205. typedef typename chain_parser<Depth-1, our_left_t>::left_t left_t;
  206. typedef typename chain_parser<Depth-1, our_left_t>::right_t right_t;
  207. static left_t
  208. left(CaseT const &p)
  209. { return chain_parser<Depth-1, our_left_t>::left(p.left()); }
  210. static right_t
  211. right(CaseT const &p)
  212. { return chain_parser<Depth-1, our_left_t>::right(p.left()); }
  213. };
  214. template <typename CaseT>
  215. struct chain_parser<1, CaseT> {
  216. typedef typename CaseT::left_t left_t;
  217. typedef typename CaseT::right_t right_t;
  218. static left_t left(CaseT const &p) { return p.left(); }
  219. static right_t right(CaseT const &p) { return p.right(); }
  220. };
  221. template <typename CaseT>
  222. struct chain_parser<0, CaseT>; // shouldn't be instantiated
  223. ///////////////////////////////////////////////////////////////////////////////
  224. // Type computing meta function for calculating the type of the return value
  225. // of the used conditional switch expression
  226. template <typename TargetT, typename ScannerT>
  227. struct condition_result {
  228. typedef typename TargetT::template result<ScannerT>::type type;
  229. };
  230. ///////////////////////////////////////////////////////////////////////////////
  231. template <typename LeftT, typename RightT, bool IsDefault>
  232. struct compound_case_parser
  233. : public binary<LeftT, RightT,
  234. parser<compound_case_parser<LeftT, RightT, IsDefault> > >
  235. {
  236. typedef compound_case_parser<LeftT, RightT, IsDefault> self_t;
  237. typedef binary_parser_category parser_category_t;
  238. typedef binary<LeftT, RightT, parser<self_t> > base_t;
  239. BOOST_STATIC_CONSTANT(int, value = RightT::value);
  240. BOOST_STATIC_CONSTANT(bool, is_default = IsDefault);
  241. BOOST_STATIC_CONSTANT(bool, is_simple = false);
  242. BOOST_STATIC_CONSTANT(bool, is_epsilon = (
  243. is_default &&
  244. boost::is_same<typename RightT::subject_t, epsilon_parser>::value
  245. ));
  246. compound_case_parser(parser<LeftT> const &lhs, parser<RightT> const &rhs)
  247. : base_t(lhs.derived(), rhs.derived())
  248. {}
  249. template <typename ScannerT>
  250. struct result
  251. {
  252. typedef typename match_result<ScannerT, nil_t>::type type;
  253. };
  254. template <typename ScannerT, typename CondT>
  255. typename parser_result<self_t, ScannerT>::type
  256. parse(ScannerT const& scan, CondT const &cond) const;
  257. template <int N1, typename ParserT1, bool IsDefault1>
  258. compound_case_parser<
  259. self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
  260. >
  261. operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
  262. {
  263. // If the following compile time assertion fires, you've probably used
  264. // more than one default_p case inside the switch_p parser construct.
  265. BOOST_STATIC_ASSERT(!default_case<self_t>::value || !IsDefault1);
  266. // If this compile time assertion fires, you've probably want to use
  267. // more case_p/default_p case branches, than possible.
  268. BOOST_STATIC_ASSERT(
  269. case_chain<self_t>::depth < BOOST_SPIRIT_SWITCH_CASE_LIMIT
  270. );
  271. typedef case_parser<N1, ParserT1, IsDefault1> right_t;
  272. return compound_case_parser<self_t, right_t, IsDefault1>(*this, p);
  273. }
  274. };
  275. ///////////////////////////////////////////////////////////////////////////////
  276. // The parse_switch::do_ functions dispatch to the correct parser, which is
  277. // selected through the given conditional switch value.
  278. template <int Value, int Depth, bool IsDefault>
  279. struct parse_switch;
  280. ///////////////////////////////////////////////////////////////////////////////
  281. //
  282. // The following generates a couple of parse_switch template specializations
  283. // with an increasing number of handled case branches (for 1..N).
  284. //
  285. // template <int Value, bool IsDefault>
  286. // struct parse_switch<Value, N, IsDefault> {
  287. //
  288. // template <typename ParserT, typename ScannerT>
  289. // static typename parser_result<ParserT, ScannerT>::type
  290. // do_(ParserT const &p, ScannerT const &scan, long cond_value,
  291. // typename ScannerT::iterator_t const &save)
  292. // {
  293. // typedef ParserT left_t0;
  294. // typedef typename left_t0::left left_t1;
  295. // ...
  296. //
  297. // switch (cond_value) {
  298. // case left_tN::value:
  299. // return delegate_parse(chain_parser<
  300. // case_chain<ParserT>::depth, ParserT
  301. // >::left(p), scan, save);
  302. // ...
  303. // case left_t1::value:
  304. // return delegate_parse(chain_parser<
  305. // 1, left_t1
  306. // >::right(p.left()), scan, save);
  307. //
  308. // case left_t0::value:
  309. // default:
  310. // typedef default_case<ParserT> default_t;
  311. // typedef default_delegate_parse<
  312. // Value, IsDefault, default_t::value>
  313. // default_parse_t;
  314. //
  315. // return default_parse_t::parse(cond_value, p.right(),
  316. // default_t::get(p), scan, save);
  317. // }
  318. // }
  319. // };
  320. //
  321. ///////////////////////////////////////////////////////////////////////////////
  322. #define BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS(z, N, _) \
  323. typedef typename BOOST_PP_CAT(left_t, N)::left_t \
  324. BOOST_PP_CAT(left_t, BOOST_PP_INC(N)); \
  325. /**/
  326. #define BOOST_SPIRIT_PARSE_SWITCH_CASES(z, N, _) \
  327. case (long)(BOOST_PP_CAT(left_t, N)::value): \
  328. return delegate_parse(chain_parser<N, left_t1>::right(p.left()), \
  329. scan, save); \
  330. /**/
  331. #define BOOST_SPIRIT_PARSE_SWITCHES(z, N, _) \
  332. template <int Value, bool IsDefault> \
  333. struct parse_switch<Value, BOOST_PP_INC(N), IsDefault> { \
  334. \
  335. template <typename ParserT, typename ScannerT> \
  336. static typename parser_result<ParserT, ScannerT>::type \
  337. do_(ParserT const &p, ScannerT const &scan, long cond_value, \
  338. typename ScannerT::iterator_t const &save) \
  339. { \
  340. typedef ParserT left_t0; \
  341. BOOST_PP_REPEAT_FROM_TO_ ## z(0, BOOST_PP_INC(N), \
  342. BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS, _) \
  343. \
  344. switch (cond_value) { \
  345. case (long)(BOOST_PP_CAT(left_t, BOOST_PP_INC(N))::value): \
  346. return delegate_parse( \
  347. chain_parser< \
  348. case_chain<ParserT>::depth, ParserT \
  349. >::left(p), scan, save); \
  350. \
  351. BOOST_PP_REPEAT_FROM_TO_ ## z(1, BOOST_PP_INC(N), \
  352. BOOST_SPIRIT_PARSE_SWITCH_CASES, _) \
  353. \
  354. case (long)(left_t0::value): \
  355. default: \
  356. typedef default_case<ParserT> default_t; \
  357. typedef \
  358. default_delegate_parse<Value, IsDefault, default_t::value> \
  359. default_parse_t; \
  360. \
  361. return default_parse_t::parse(cond_value, p.right(), \
  362. default_t::get(p), scan, save); \
  363. } \
  364. } \
  365. }; \
  366. /**/
  367. BOOST_PP_REPEAT(BOOST_PP_DEC(BOOST_SPIRIT_SWITCH_CASE_LIMIT),
  368. BOOST_SPIRIT_PARSE_SWITCHES, _)
  369. #undef BOOST_SPIRIT_PARSE_SWITCH_TYPEDEFS
  370. #undef BOOST_SPIRIT_PARSE_SWITCH_CASES
  371. #undef BOOST_SPIRIT_PARSE_SWITCHES
  372. ///////////////////////////////////////////////////////////////////////////////
  373. template <typename LeftT, typename RightT, bool IsDefault>
  374. template <typename ScannerT, typename CondT>
  375. inline typename parser_result<
  376. compound_case_parser<LeftT, RightT, IsDefault>, ScannerT
  377. >::type
  378. compound_case_parser<LeftT, RightT, IsDefault>::
  379. parse(ScannerT const& scan, CondT const &cond) const
  380. {
  381. scan.at_end(); // allow skipper to take effect
  382. return parse_switch<value, case_chain<self_t>::depth, is_default>::
  383. do_(*this, scan, cond(scan), scan.first);
  384. }
  385. ///////////////////////////////////////////////////////////////////////////////
  386. // The switch condition is to be evaluated from a parser result value.
  387. template <typename ParserT>
  388. struct cond_functor {
  389. typedef cond_functor<ParserT> self_t;
  390. cond_functor(ParserT const &p_)
  391. : p(p_)
  392. {}
  393. template <typename ScannerT>
  394. struct result
  395. {
  396. typedef typename parser_result<ParserT, ScannerT>::type::attr_t type;
  397. };
  398. template <typename ScannerT>
  399. typename condition_result<self_t, ScannerT>::type
  400. operator()(ScannerT const &scan) const
  401. {
  402. typedef typename parser_result<ParserT, ScannerT>::type result_t;
  403. typedef typename result_t::attr_t attr_t;
  404. result_t result(p.parse(scan));
  405. return !result ? attr_t() : result.value();
  406. }
  407. typename ParserT::embed_t p;
  408. };
  409. template <typename ParserT>
  410. struct make_cond_functor {
  411. typedef as_parser<ParserT> as_parser_t;
  412. static cond_functor<typename as_parser_t::type>
  413. do_(ParserT const &cond)
  414. {
  415. return cond_functor<typename as_parser_t::type>(
  416. as_parser_t::convert(cond));
  417. }
  418. };
  419. ///////////////////////////////////////////////////////////////////////////////
  420. // The switch condition is to be evaluated from a phoenix actor
  421. template <typename ActorT>
  422. struct cond_actor {
  423. typedef cond_actor<ActorT> self_t;
  424. cond_actor(ActorT const &actor_)
  425. : actor(actor_)
  426. {}
  427. template <typename ScannerT>
  428. struct result
  429. {
  430. typedef typename phoenix::actor_result<ActorT, phoenix::tuple<> >::type
  431. type;
  432. };
  433. template <typename ScannerT>
  434. typename condition_result<self_t, ScannerT>::type
  435. operator()(ScannerT const& /*scan*/) const
  436. {
  437. return actor();
  438. }
  439. ActorT const &actor;
  440. };
  441. template <typename ActorT>
  442. struct make_cond_functor<phoenix::actor<ActorT> > {
  443. static cond_actor<phoenix::actor<ActorT> >
  444. do_(phoenix::actor<ActorT> const &actor)
  445. {
  446. return cond_actor<phoenix::actor<ActorT> >(actor);
  447. }
  448. };
  449. ///////////////////////////////////////////////////////////////////////////////
  450. // The switch condition is to be taken directly from the input stream
  451. struct get_next_token_cond {
  452. typedef get_next_token_cond self_t;
  453. template <typename ScannerT>
  454. struct result
  455. {
  456. typedef typename ScannerT::value_t type;
  457. };
  458. template <typename ScannerT>
  459. typename condition_result<self_t, ScannerT>::type
  460. operator()(ScannerT const &scan) const
  461. {
  462. typename ScannerT::value_t val(*scan);
  463. ++scan.first;
  464. return val;
  465. }
  466. };
  467. template <>
  468. struct make_cond_functor<get_next_token_cond> {
  469. static get_next_token_cond
  470. do_(get_next_token_cond const &cond)
  471. {
  472. return cond;
  473. }
  474. };
  475. ///////////////////////////////////////////////////////////////////////////////
  476. } // namespace impl
  477. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  478. }} // namespace boost::spirit
  479. #endif // BOOST_SPIRIT_SWITCH_IPP