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