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