switch.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*=============================================================================
  2. Copyright (c) 2003 Hartmut Kaiser
  3. http://spirit.sourceforge.net/
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. =============================================================================*/
  7. #ifndef BOOST_SPIRIT_SWITCH_HPP
  8. #define BOOST_SPIRIT_SWITCH_HPP
  9. ///////////////////////////////////////////////////////////////////////////////
  10. //
  11. // The default_p parser generator template uses the following magic number
  12. // as the corresponding case label value inside the generated switch()
  13. // statements. If this number conflicts with your code, please pick a
  14. // different one.
  15. //
  16. ///////////////////////////////////////////////////////////////////////////////
  17. #if !defined(BOOST_SPIRIT_DEFAULTCASE_MAGIC)
  18. #define BOOST_SPIRIT_DEFAULTCASE_MAGIC 0x15F97A7
  19. #endif
  20. ///////////////////////////////////////////////////////////////////////////////
  21. //
  22. // Spirit predefined maximum number of possible case_p/default_p case branch
  23. // parsers.
  24. //
  25. ///////////////////////////////////////////////////////////////////////////////
  26. #if !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
  27. #define BOOST_SPIRIT_SWITCH_CASE_LIMIT 3
  28. #endif // !defined(BOOST_SPIRIT_SWITCH_CASE_LIMIT)
  29. ///////////////////////////////////////////////////////////////////////////////
  30. #include <boost/static_assert.hpp>
  31. ///////////////////////////////////////////////////////////////////////////////
  32. //
  33. // Ensure BOOST_SPIRIT_SELECT_LIMIT > 0
  34. //
  35. ///////////////////////////////////////////////////////////////////////////////
  36. BOOST_STATIC_ASSERT(BOOST_SPIRIT_SWITCH_CASE_LIMIT > 0);
  37. #include <boost/spirit/home/classic/namespace.hpp>
  38. #include <boost/spirit/home/classic/core/config.hpp>
  39. #include <boost/type_traits/is_same.hpp>
  40. #include <boost/spirit/home/classic/core/parser.hpp>
  41. #include <boost/spirit/home/classic/core/composite/epsilon.hpp>
  42. #include <boost/spirit/home/classic/dynamic/impl/switch.ipp>
  43. ///////////////////////////////////////////////////////////////////////////////
  44. namespace boost { namespace spirit {
  45. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  46. ///////////////////////////////////////////////////////////////////////////////
  47. //
  48. // The switch_parser allows to build switch like parsing constructs, which
  49. // will have much better perfomance as comparable straight solutions.
  50. //
  51. // Input stream driven syntax:
  52. //
  53. // switch_p
  54. // [
  55. // case_p<'a'>
  56. // (...parser to use, if the next character is 'a'...),
  57. // case_p<'b'>
  58. // (...parser to use, if the next character is 'b'...),
  59. // default_p
  60. // (...parser to use, if nothing was matched before...)
  61. // ]
  62. //
  63. // General syntax:
  64. //
  65. // switch_p(...lazy expression returning the switch condition value...)
  66. // [
  67. // case_p<1>
  68. // (...parser to use, if the switch condition value is 1...),
  69. // case_p<2>
  70. // (...parser to use, if the switch condition value is 2...),
  71. // default_p
  72. // (...parser to use, if nothing was matched before...)
  73. // ]
  74. //
  75. // The maximum number of possible case_p branches is defined by the p constant
  76. // BOOST_SPIRIT_SWITCH_CASE_LIMIT (this value defaults to 3 if not otherwise
  77. // defined).
  78. //
  79. ///////////////////////////////////////////////////////////////////////////////
  80. template <typename CaseT, typename CondT = impl::get_next_token_cond>
  81. struct switch_parser
  82. : public unary<CaseT, parser<switch_parser<CaseT, CondT> > >
  83. {
  84. typedef switch_parser<CaseT, CondT> self_t;
  85. typedef unary_parser_category parser_category_t;
  86. typedef unary<CaseT, parser<self_t> > base_t;
  87. switch_parser(CaseT const &case_)
  88. : base_t(case_), cond(CondT())
  89. {}
  90. switch_parser(CaseT const &case_, CondT const &cond_)
  91. : base_t(case_), cond(cond_)
  92. {}
  93. template <typename ScannerT>
  94. struct result
  95. {
  96. typedef typename match_result<ScannerT, nil_t>::type type;
  97. };
  98. template <typename ScannerT>
  99. typename parser_result<self_t, ScannerT>::type
  100. parse(ScannerT const& scan) const
  101. {
  102. return this->subject().parse(scan,
  103. impl::make_cond_functor<CondT>::do_(cond));
  104. }
  105. CondT cond;
  106. };
  107. ///////////////////////////////////////////////////////////////////////////////
  108. template <typename CondT>
  109. struct switch_cond_parser
  110. {
  111. switch_cond_parser(CondT const &cond_)
  112. : cond(cond_)
  113. {}
  114. template <typename ParserT>
  115. switch_parser<ParserT, CondT>
  116. operator[](parser<ParserT> const &p) const
  117. {
  118. return switch_parser<ParserT, CondT>(p.derived(), cond);
  119. }
  120. CondT const &cond;
  121. };
  122. ///////////////////////////////////////////////////////////////////////////////
  123. template <int N, typename ParserT, bool IsDefault>
  124. struct case_parser
  125. : public unary<ParserT, parser<case_parser<N, ParserT, IsDefault> > >
  126. {
  127. typedef case_parser<N, ParserT, IsDefault> self_t;
  128. typedef unary_parser_category parser_category_t;
  129. typedef unary<ParserT, parser<self_t> > base_t;
  130. typedef typename base_t::subject_t self_subject_t;
  131. BOOST_STATIC_CONSTANT(int, value = N);
  132. BOOST_STATIC_CONSTANT(bool, is_default = IsDefault);
  133. BOOST_STATIC_CONSTANT(bool, is_simple = true);
  134. BOOST_STATIC_CONSTANT(bool, is_epsilon = (
  135. is_default && boost::is_same<self_subject_t, epsilon_parser>::value
  136. ));
  137. case_parser(parser<ParserT> const &p)
  138. : base_t(p.derived())
  139. {}
  140. template <typename ScannerT>
  141. struct result
  142. {
  143. typedef typename match_result<ScannerT, nil_t>::type type;
  144. };
  145. template <typename ScannerT, typename CondT>
  146. typename parser_result<self_t, ScannerT>::type
  147. parse(ScannerT const& scan, CondT const &cond) const
  148. {
  149. typedef impl::default_case<self_t> default_t;
  150. if (!scan.at_end()) {
  151. typedef impl::default_delegate_parse<
  152. value, is_default, default_t::value> default_parse_t;
  153. typename ScannerT::iterator_t const save(scan.first);
  154. return default_parse_t::parse(cond(scan), *this,
  155. *this, scan, save);
  156. }
  157. return default_t::is_epsilon ? scan.empty_match() : scan.no_match();
  158. }
  159. template <int N1, typename ParserT1, bool IsDefault1>
  160. impl::compound_case_parser<
  161. self_t, case_parser<N1, ParserT1, IsDefault1>, IsDefault1
  162. >
  163. operator, (case_parser<N1, ParserT1, IsDefault1> const &p) const
  164. {
  165. // If the following compile time assertion fires, you've probably used
  166. // more than one default_p case inside the switch_p parser construct.
  167. BOOST_STATIC_ASSERT(!is_default || !IsDefault1);
  168. typedef case_parser<N1, ParserT1, IsDefault1> right_t;
  169. return impl::compound_case_parser<self_t, right_t, IsDefault1>(*this, p);
  170. }
  171. };
  172. ///////////////////////////////////////////////////////////////////////////////
  173. struct switch_parser_gen {
  174. // This generates a switch parser, which is driven by the condition value
  175. // returned by the lazy parameter expression 'cond'. This may be a parser,
  176. // which result is used or a phoenix actor, which will be dereferenced to
  177. // obtain the switch condition value.
  178. template <typename CondT>
  179. switch_cond_parser<CondT>
  180. operator()(CondT const &cond) const
  181. {
  182. return switch_cond_parser<CondT>(cond);
  183. }
  184. // This generates a switch parser, which is driven by the next character/token
  185. // found in the input stream.
  186. template <typename CaseT>
  187. switch_parser<CaseT>
  188. operator[](parser<CaseT> const &p) const
  189. {
  190. return switch_parser<CaseT>(p.derived());
  191. }
  192. };
  193. switch_parser_gen const switch_p = switch_parser_gen();
  194. ///////////////////////////////////////////////////////////////////////////////
  195. template <int N, typename ParserT>
  196. inline case_parser<N, ParserT, false>
  197. case_p(parser<ParserT> const &p)
  198. {
  199. return case_parser<N, ParserT, false>(p);
  200. }
  201. ///////////////////////////////////////////////////////////////////////////////
  202. struct default_parser_gen
  203. : public case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
  204. {
  205. default_parser_gen()
  206. : case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, epsilon_parser, true>
  207. (epsilon_p)
  208. {}
  209. template <typename ParserT>
  210. case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>
  211. operator()(parser<ParserT> const &p) const
  212. {
  213. return case_parser<BOOST_SPIRIT_DEFAULTCASE_MAGIC, ParserT, true>(p);
  214. }
  215. };
  216. default_parser_gen const default_p = default_parser_gen();
  217. ///////////////////////////////////////////////////////////////////////////////
  218. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  219. }} // namespace BOOST_SPIRIT_CLASSIC_NS
  220. #endif // BOOST_SPIRIT_SWITCH_HPP