| /*============================================================================= |
| Copyright (c) 2002-2003 Hartmut Kaiser |
| http://spirit.sourceforge.net/ |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| =============================================================================*/ |
| #ifndef BOOST_SPIRIT_REFACTORING_HPP |
| #define BOOST_SPIRIT_REFACTORING_HPP |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| #include <boost/static_assert.hpp> |
| #include <boost/spirit/home/classic/namespace.hpp> |
| #include <boost/spirit/home/classic/meta/as_parser.hpp> |
| #include <boost/spirit/home/classic/core/parser.hpp> |
| #include <boost/spirit/home/classic/core/composite/composite.hpp> |
| #include <boost/spirit/home/classic/meta/impl/refactoring.ipp> |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| namespace boost { namespace spirit { |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN |
| |
| #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) |
| #pragma warning(push) |
| #pragma warning(disable:4512) //assignment operator could not be generated |
| #endif |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // refactor_unary_parser class |
| // |
| // This helper template allows to attach an unary operation to a newly |
| // constructed parser, which combines the subject of the left operand of |
| // the original given parser (BinaryT) with the right operand of the |
| // original binary parser through the original binary operation and |
| // rewraps the resulting parser with the original unary operator. |
| // |
| // For instance given the parser: |
| // *some_parser - another_parser |
| // |
| // will be refactored to: |
| // *(some_parser - another_parser) |
| // |
| // If the parser to refactor is not a unary parser, no refactoring is done |
| // at all. |
| // |
| // The original parser should be a binary_parser_category parser, |
| // else the compilation will fail |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| template <typename NestedT = non_nested_refactoring> |
| class refactor_unary_gen; |
| |
| template <typename BinaryT, typename NestedT = non_nested_refactoring> |
| class refactor_unary_parser : |
| public parser<refactor_unary_parser<BinaryT, NestedT> > { |
| |
| public: |
| // the parser to refactor has to be at least a binary_parser_category |
| // parser |
| BOOST_STATIC_ASSERT(( |
| boost::is_convertible<typename BinaryT::parser_category_t, |
| binary_parser_category>::value |
| )); |
| |
| refactor_unary_parser(BinaryT const& binary_, NestedT const& nested_) |
| : binary(binary_), nested(nested_) {} |
| |
| typedef refactor_unary_parser<BinaryT, NestedT> self_t; |
| typedef refactor_unary_gen<NestedT> parser_generator_t; |
| typedef typename BinaryT::left_t::parser_category_t parser_category_t; |
| |
| template <typename ScannerT> |
| typename parser_result<self_t, ScannerT>::type |
| parse(ScannerT const& scan) const |
| { |
| return impl::refactor_unary_type<NestedT>:: |
| parse(*this, scan, binary, nested); |
| } |
| |
| private: |
| typename as_parser<BinaryT>::type::embed_t binary; |
| typename NestedT::embed_t nested; |
| }; |
| |
| ////////////////////////////////// |
| template <typename NestedT> |
| class refactor_unary_gen { |
| |
| public: |
| typedef refactor_unary_gen<NestedT> embed_t; |
| |
| refactor_unary_gen(NestedT const& nested_ = non_nested_refactoring()) |
| : nested(nested_) {} |
| |
| template <typename ParserT> |
| refactor_unary_parser<ParserT, NestedT> |
| operator[](parser<ParserT> const& subject) const |
| { |
| return refactor_unary_parser<ParserT, NestedT> |
| (subject.derived(), nested); |
| } |
| |
| private: |
| typename NestedT::embed_t nested; |
| }; |
| |
| const refactor_unary_gen<> refactor_unary_d = refactor_unary_gen<>(); |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // refactor_action_parser class |
| // |
| // This helper template allows to attach an action taken from the left |
| // operand of the given binary parser to a newly constructed parser, |
| // which combines the subject of the left operand of the original binary |
| // parser with the right operand of the original binary parser by means of |
| // the original binary operator parser. |
| // |
| // For instance the parser: |
| // some_parser[some_attached_functor] - another_parser |
| // |
| // will be refactored to: |
| // (some_parser - another_parser)[some_attached_functor] |
| // |
| // If the left operand to refactor is not an action parser, no refactoring |
| // is done at all. |
| // |
| // The original parser should be a binary_parser_category parser, |
| // else the compilation will fail |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| template <typename NestedT = non_nested_refactoring> |
| class refactor_action_gen; |
| |
| template <typename BinaryT, typename NestedT = non_nested_refactoring> |
| class refactor_action_parser : |
| public parser<refactor_action_parser<BinaryT, NestedT> > { |
| |
| public: |
| // the parser to refactor has to be at least a binary_parser_category |
| // parser |
| BOOST_STATIC_ASSERT(( |
| boost::is_convertible<typename BinaryT::parser_category_t, |
| binary_parser_category>::value |
| )); |
| |
| refactor_action_parser(BinaryT const& binary_, NestedT const& nested_) |
| : binary(binary_), nested(nested_) {} |
| |
| typedef refactor_action_parser<BinaryT, NestedT> self_t; |
| typedef refactor_action_gen<NestedT> parser_generator_t; |
| typedef typename BinaryT::left_t::parser_category_t parser_category_t; |
| |
| template <typename ScannerT> |
| typename parser_result<self_t, ScannerT>::type |
| parse(ScannerT const& scan) const |
| { |
| return impl::refactor_action_type<NestedT>:: |
| parse(*this, scan, binary, nested); |
| } |
| |
| private: |
| typename as_parser<BinaryT>::type::embed_t binary; |
| typename NestedT::embed_t nested; |
| }; |
| |
| ////////////////////////////////// |
| template <typename NestedT> |
| class refactor_action_gen { |
| |
| public: |
| typedef refactor_action_gen<NestedT> embed_t; |
| |
| refactor_action_gen(NestedT const& nested_ = non_nested_refactoring()) |
| : nested(nested_) {} |
| |
| template <typename ParserT> |
| refactor_action_parser<ParserT, NestedT> |
| operator[](parser<ParserT> const& subject) const |
| { |
| return refactor_action_parser<ParserT, NestedT> |
| (subject.derived(), nested); |
| } |
| |
| private: |
| typename NestedT::embed_t nested; |
| }; |
| |
| const refactor_action_gen<> refactor_action_d = refactor_action_gen<>(); |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // attach_action_parser class |
| // |
| // This helper template allows to attach an action given separately |
| // to to all parsers, out of which the given parser is constructed and |
| // reconstructs a new parser having the same structure. |
| // |
| // For instance the parser: |
| // (some_parser >> another_parser)[some_attached_functor] |
| // |
| // will be refactored to: |
| // some_parser[some_attached_functor] |
| // >> another_parser[some_attached_functor] |
| // |
| // The original parser should be a action_parser_category parser, |
| // else the compilation will fail |
| // |
| // If the parser, to which the action is attached is not an binary parser, |
| // no refactoring is done at all. |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| template <typename NestedT = non_nested_refactoring> |
| class attach_action_gen; |
| |
| template <typename ActionT, typename NestedT = non_nested_refactoring> |
| class attach_action_parser : |
| public parser<attach_action_parser<ActionT, NestedT> > { |
| |
| public: |
| // the parser to refactor has to be at least a action_parser_category |
| // parser |
| BOOST_STATIC_ASSERT(( |
| boost::is_convertible<typename ActionT::parser_category_t, |
| action_parser_category>::value |
| )); |
| |
| attach_action_parser(ActionT const& actor_, NestedT const& nested_) |
| : actor(actor_), nested(nested_) {} |
| |
| typedef attach_action_parser<ActionT, NestedT> self_t; |
| typedef attach_action_gen<NestedT> parser_generator_t; |
| typedef typename ActionT::parser_category_t parser_category_t; |
| |
| template <typename ScannerT> |
| typename parser_result<self_t, ScannerT>::type |
| parse(ScannerT const& scan) const |
| { |
| return impl::attach_action_type<NestedT>:: |
| parse(*this, scan, actor, nested); |
| } |
| |
| private: |
| typename as_parser<ActionT>::type::embed_t actor; |
| typename NestedT::embed_t nested; |
| }; |
| |
| ////////////////////////////////// |
| template <typename NestedT> |
| class attach_action_gen { |
| |
| public: |
| typedef attach_action_gen<NestedT> embed_t; |
| |
| attach_action_gen(NestedT const& nested_ = non_nested_refactoring()) |
| : nested(nested_) {} |
| |
| template <typename ParserT, typename ActionT> |
| attach_action_parser<action<ParserT, ActionT>, NestedT> |
| operator[](action<ParserT, ActionT> const& actor) const |
| { |
| return attach_action_parser<action<ParserT, ActionT>, NestedT> |
| (actor, nested); |
| } |
| |
| private: |
| typename NestedT::embed_t nested; |
| }; |
| |
| const attach_action_gen<> attach_action_d = attach_action_gen<>(); |
| |
| #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) |
| #pragma warning(pop) |
| #endif |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END |
| |
| }} // namespace BOOST_SPIRIT_CLASSIC_NS |
| |
| #endif // BOOST_SPIRIT_REFACTORING_HPP |
| |