9
3

switch.ipp 21 KB

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