refactoring.hpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*=============================================================================
  2. Copyright (c) 2002-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_REFACTORING_HPP
  8. #define BOOST_SPIRIT_REFACTORING_HPP
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include <boost/static_assert.hpp>
  11. #include <boost/spirit/home/classic/namespace.hpp>
  12. #include <boost/spirit/home/classic/meta/as_parser.hpp>
  13. #include <boost/spirit/home/classic/core/parser.hpp>
  14. #include <boost/spirit/home/classic/core/composite/composite.hpp>
  15. #include <boost/spirit/home/classic/meta/impl/refactoring.ipp>
  16. ///////////////////////////////////////////////////////////////////////////////
  17. namespace boost { namespace spirit {
  18. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  19. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  20. #pragma warning(push)
  21. #pragma warning(disable:4512) //assignment operator could not be generated
  22. #endif
  23. ///////////////////////////////////////////////////////////////////////////////
  24. //
  25. // refactor_unary_parser class
  26. //
  27. // This helper template allows to attach an unary operation to a newly
  28. // constructed parser, which combines the subject of the left operand of
  29. // the original given parser (BinaryT) with the right operand of the
  30. // original binary parser through the original binary operation and
  31. // rewraps the resulting parser with the original unary operator.
  32. //
  33. // For instance given the parser:
  34. // *some_parser - another_parser
  35. //
  36. // will be refactored to:
  37. // *(some_parser - another_parser)
  38. //
  39. // If the parser to refactor is not a unary parser, no refactoring is done
  40. // at all.
  41. //
  42. // The original parser should be a binary_parser_category parser,
  43. // else the compilation will fail
  44. //
  45. ///////////////////////////////////////////////////////////////////////////////
  46. template <typename NestedT = non_nested_refactoring>
  47. class refactor_unary_gen;
  48. template <typename BinaryT, typename NestedT = non_nested_refactoring>
  49. class refactor_unary_parser :
  50. public parser<refactor_unary_parser<BinaryT, NestedT> > {
  51. public:
  52. // the parser to refactor has to be at least a binary_parser_category
  53. // parser
  54. BOOST_STATIC_ASSERT((
  55. boost::is_convertible<typename BinaryT::parser_category_t,
  56. binary_parser_category>::value
  57. ));
  58. refactor_unary_parser(BinaryT const& binary_, NestedT const& nested_)
  59. : binary(binary_), nested(nested_) {}
  60. typedef refactor_unary_parser<BinaryT, NestedT> self_t;
  61. typedef refactor_unary_gen<NestedT> parser_generator_t;
  62. typedef typename BinaryT::left_t::parser_category_t parser_category_t;
  63. template <typename ScannerT>
  64. typename parser_result<self_t, ScannerT>::type
  65. parse(ScannerT const& scan) const
  66. {
  67. return impl::refactor_unary_type<NestedT>::
  68. parse(*this, scan, binary, nested);
  69. }
  70. private:
  71. typename as_parser<BinaryT>::type::embed_t binary;
  72. typename NestedT::embed_t nested;
  73. };
  74. //////////////////////////////////
  75. template <typename NestedT>
  76. class refactor_unary_gen {
  77. public:
  78. typedef refactor_unary_gen<NestedT> embed_t;
  79. refactor_unary_gen(NestedT const& nested_ = non_nested_refactoring())
  80. : nested(nested_) {}
  81. template <typename ParserT>
  82. refactor_unary_parser<ParserT, NestedT>
  83. operator[](parser<ParserT> const& subject) const
  84. {
  85. return refactor_unary_parser<ParserT, NestedT>
  86. (subject.derived(), nested);
  87. }
  88. private:
  89. typename NestedT::embed_t nested;
  90. };
  91. const refactor_unary_gen<> refactor_unary_d = refactor_unary_gen<>();
  92. ///////////////////////////////////////////////////////////////////////////////
  93. //
  94. // refactor_action_parser class
  95. //
  96. // This helper template allows to attach an action taken from the left
  97. // operand of the given binary parser to a newly constructed parser,
  98. // which combines the subject of the left operand of the original binary
  99. // parser with the right operand of the original binary parser by means of
  100. // the original binary operator parser.
  101. //
  102. // For instance the parser:
  103. // some_parser[some_attached_functor] - another_parser
  104. //
  105. // will be refactored to:
  106. // (some_parser - another_parser)[some_attached_functor]
  107. //
  108. // If the left operand to refactor is not an action parser, no refactoring
  109. // is done at all.
  110. //
  111. // The original parser should be a binary_parser_category parser,
  112. // else the compilation will fail
  113. //
  114. ///////////////////////////////////////////////////////////////////////////////
  115. template <typename NestedT = non_nested_refactoring>
  116. class refactor_action_gen;
  117. template <typename BinaryT, typename NestedT = non_nested_refactoring>
  118. class refactor_action_parser :
  119. public parser<refactor_action_parser<BinaryT, NestedT> > {
  120. public:
  121. // the parser to refactor has to be at least a binary_parser_category
  122. // parser
  123. BOOST_STATIC_ASSERT((
  124. boost::is_convertible<typename BinaryT::parser_category_t,
  125. binary_parser_category>::value
  126. ));
  127. refactor_action_parser(BinaryT const& binary_, NestedT const& nested_)
  128. : binary(binary_), nested(nested_) {}
  129. typedef refactor_action_parser<BinaryT, NestedT> self_t;
  130. typedef refactor_action_gen<NestedT> parser_generator_t;
  131. typedef typename BinaryT::left_t::parser_category_t parser_category_t;
  132. template <typename ScannerT>
  133. typename parser_result<self_t, ScannerT>::type
  134. parse(ScannerT const& scan) const
  135. {
  136. return impl::refactor_action_type<NestedT>::
  137. parse(*this, scan, binary, nested);
  138. }
  139. private:
  140. typename as_parser<BinaryT>::type::embed_t binary;
  141. typename NestedT::embed_t nested;
  142. };
  143. //////////////////////////////////
  144. template <typename NestedT>
  145. class refactor_action_gen {
  146. public:
  147. typedef refactor_action_gen<NestedT> embed_t;
  148. refactor_action_gen(NestedT const& nested_ = non_nested_refactoring())
  149. : nested(nested_) {}
  150. template <typename ParserT>
  151. refactor_action_parser<ParserT, NestedT>
  152. operator[](parser<ParserT> const& subject) const
  153. {
  154. return refactor_action_parser<ParserT, NestedT>
  155. (subject.derived(), nested);
  156. }
  157. private:
  158. typename NestedT::embed_t nested;
  159. };
  160. const refactor_action_gen<> refactor_action_d = refactor_action_gen<>();
  161. ///////////////////////////////////////////////////////////////////////////////
  162. //
  163. // attach_action_parser class
  164. //
  165. // This helper template allows to attach an action given separately
  166. // to all parsers, out of which the given parser is constructed and
  167. // reconstructs a new parser having the same structure.
  168. //
  169. // For instance the parser:
  170. // (some_parser >> another_parser)[some_attached_functor]
  171. //
  172. // will be refactored to:
  173. // some_parser[some_attached_functor]
  174. // >> another_parser[some_attached_functor]
  175. //
  176. // The original parser should be a action_parser_category parser,
  177. // else the compilation will fail.
  178. //
  179. // If the parser, to which the action is attached is not an binary parser,
  180. // no refactoring is done at all.
  181. //
  182. ///////////////////////////////////////////////////////////////////////////////
  183. template <typename NestedT = non_nested_refactoring>
  184. class attach_action_gen;
  185. template <typename ActionT, typename NestedT = non_nested_refactoring>
  186. class attach_action_parser :
  187. public parser<attach_action_parser<ActionT, NestedT> > {
  188. public:
  189. // the parser to refactor has to be at least a action_parser_category
  190. // parser
  191. BOOST_STATIC_ASSERT((
  192. boost::is_convertible<typename ActionT::parser_category_t,
  193. action_parser_category>::value
  194. ));
  195. attach_action_parser(ActionT const& actor_, NestedT const& nested_)
  196. : actor(actor_), nested(nested_) {}
  197. typedef attach_action_parser<ActionT, NestedT> self_t;
  198. typedef attach_action_gen<NestedT> parser_generator_t;
  199. typedef typename ActionT::parser_category_t parser_category_t;
  200. template <typename ScannerT>
  201. typename parser_result<self_t, ScannerT>::type
  202. parse(ScannerT const& scan) const
  203. {
  204. return impl::attach_action_type<NestedT>::
  205. parse(*this, scan, actor, nested);
  206. }
  207. private:
  208. typename as_parser<ActionT>::type::embed_t actor;
  209. typename NestedT::embed_t nested;
  210. };
  211. //////////////////////////////////
  212. template <typename NestedT>
  213. class attach_action_gen {
  214. public:
  215. typedef attach_action_gen<NestedT> embed_t;
  216. attach_action_gen(NestedT const& nested_ = non_nested_refactoring())
  217. : nested(nested_) {}
  218. template <typename ParserT, typename ActionT>
  219. attach_action_parser<action<ParserT, ActionT>, NestedT>
  220. operator[](action<ParserT, ActionT> const& actor) const
  221. {
  222. return attach_action_parser<action<ParserT, ActionT>, NestedT>
  223. (actor, nested);
  224. }
  225. private:
  226. typename NestedT::embed_t nested;
  227. };
  228. const attach_action_gen<> attach_action_d = attach_action_gen<>();
  229. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  230. #pragma warning(pop)
  231. #endif
  232. ///////////////////////////////////////////////////////////////////////////////
  233. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  234. }} // namespace BOOST_SPIRIT_CLASSIC_NS
  235. #endif // BOOST_SPIRIT_REFACTORING_HPP