1 /*============================================================================= 2 Copyright (c) 2001-2014 Joel de Guzman 3 Copyright (c) 2013-2014 Agustin Berge 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 #if !defined(BOOST_SPIRIT_X3_AUXILIARY_ANY_PARSER_APR_09_2014_1145PM) 9 #define BOOST_SPIRIT_X3_AUXILIARY_ANY_PARSER_APR_09_2014_1145PM 10 11 #include <boost/spirit/home/x3/core/parser.hpp> 12 #include <boost/spirit/home/x3/support/context.hpp> 13 #include <boost/spirit/home/x3/support/subcontext.hpp> 14 #include <boost/spirit/home/x3/support/unused.hpp> 15 #include <boost/spirit/home/x3/support/traits/container_traits.hpp> 16 #include <boost/spirit/home/x3/support/traits/has_attribute.hpp> 17 #include <boost/spirit/home/x3/support/traits/move_to.hpp> 18 #include <boost/spirit/home/x3/support/traits/is_parser.hpp> 19 #include <memory> 20 #include <string> 21 22 namespace boost { namespace spirit { namespace x3 23 { 24 template < 25 typename Iterator 26 , typename Attribute = unused_type 27 , typename Context = subcontext<>> 28 struct any_parser : parser<any_parser<Iterator, Attribute, Context>> 29 { 30 typedef Attribute attribute_type; 31 32 static bool const has_attribute = 33 !is_same<unused_type, attribute_type>::value; 34 static bool const handles_container = 35 traits::is_container<Attribute>::value; 36 37 public: 38 any_parser() = default; 39 40 template <typename Expr, 41 typename Enable = typename enable_if<traits::is_parser<Expr>>::type> any_parserboost::spirit::x3::any_parser42 any_parser(Expr const& expr) 43 : _content(new holder<Expr>(expr)) {} 44 any_parserboost::spirit::x3::any_parser45 any_parser(any_parser const& other) 46 : _content(other._content ? other._content->clone() : nullptr) {} 47 48 any_parser(any_parser&& other) = default; 49 operator =boost::spirit::x3::any_parser50 any_parser& operator=(any_parser const& other) 51 { 52 _content.reset(other._content ? other._content->clone() : nullptr); 53 return *this; 54 } 55 56 any_parser& operator=(any_parser&& other) = default; 57 58 template <typename Iterator_, typename Context_> parseboost::spirit::x3::any_parser59 bool parse(Iterator_& first, Iterator_ const& last 60 , Context_ const& context, unused_type, Attribute& attr) const 61 { 62 BOOST_STATIC_ASSERT_MSG( 63 (is_same<Iterator, Iterator_>::value) 64 , "Incompatible iterator used" 65 ); 66 67 BOOST_ASSERT_MSG( 68 (_content != nullptr) 69 , "Invalid use of uninitialized any_parser" 70 ); 71 72 return _content->parse(first, last, context, attr); 73 } 74 75 template <typename Iterator_, typename Context_, typename Attribute_> parseboost::spirit::x3::any_parser76 bool parse(Iterator_& first, Iterator_ const& last 77 , Context_ const& context, unused_type, Attribute_& attr_) const 78 { 79 Attribute attr; 80 if (parse(first, last, context, unused, attr)) 81 { 82 traits::move_to(attr, attr_); 83 return true; 84 } 85 return false; 86 } 87 get_infoboost::spirit::x3::any_parser88 std::string get_info() const 89 { 90 return _content ? _content->get_info() : ""; 91 } 92 93 private: 94 95 struct placeholder 96 { 97 virtual placeholder* clone() const = 0; 98 99 virtual bool parse(Iterator& first, Iterator const& last 100 , Context const& context, Attribute& attr) const = 0; 101 102 virtual std::string get_info() const = 0; 103 ~placeholderboost::spirit::x3::any_parser::placeholder104 virtual ~placeholder() {} 105 }; 106 107 template <typename Expr> 108 struct holder : placeholder 109 { 110 typedef typename extension::as_parser<Expr>::value_type parser_type; 111 holderboost::spirit::x3::any_parser::holder112 explicit holder(Expr const& p) 113 : _parser(as_parser(p)) {} 114 cloneboost::spirit::x3::any_parser::holder115 holder* clone() const override 116 { 117 return new holder(*this); 118 } 119 parseboost::spirit::x3::any_parser::holder120 bool parse(Iterator& first, Iterator const& last 121 , Context const& context, Attribute& attr) const override 122 { 123 return _parser.parse(first, last, context, unused, attr); 124 } 125 get_infoboost::spirit::x3::any_parser::holder126 std::string get_info() const override 127 { 128 return x3::what(_parser); 129 } 130 131 parser_type _parser; 132 }; 133 134 private: 135 std::unique_ptr<placeholder> _content; 136 }; 137 138 template <typename Iterator, typename Attribute, typename Context> 139 struct get_info<any_parser<Iterator, Attribute, Context>> 140 { 141 typedef std::string result_type; operator ()boost::spirit::x3::get_info142 std::string operator()( 143 any_parser<Iterator, Attribute, Context> const& p) const 144 { 145 return p.get_info(); 146 } 147 }; 148 }}} 149 150 #endif 151