]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/x3/core/parser.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / spirit / home / x3 / core / parser.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2014 Joel de Guzman
3 Copyright (c) 2013 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_PARSER_OCTOBER_16_2008_0254PM)
9 #define BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM
10
11 #include <boost/mpl/bool.hpp>
12 #include <boost/type_traits/is_base_of.hpp>
13 #include <boost/type_traits/remove_cv.hpp>
14 #include <boost/type_traits/remove_reference.hpp>
15 #include <boost/utility/declval.hpp>
16 #include <boost/utility/enable_if.hpp>
17 #include <boost/spirit/home/x3/support/unused.hpp>
18 #include <boost/spirit/home/x3/support/context.hpp>
19 #include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
20 #include <boost/spirit/home/x3/support/utility/sfinae.hpp>
21 #include <boost/core/ignore_unused.hpp>
22 #include <boost/assert.hpp>
23 #include <string>
24
25 #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
26 #include <typeinfo>
27 #endif
28
29 namespace boost { namespace spirit { namespace x3
30 {
31 template <typename Subject, typename Action>
32 struct action;
33
34 template <typename Subject, typename Handler>
35 struct guard;
36
37 struct parser_base {};
38 struct parser_id;
39
40 template <typename Derived>
41 struct parser : parser_base
42 {
43 typedef Derived derived_type;
44 static bool const handles_container = false;
45 static bool const is_pass_through_unary = false;
46 static bool const has_action = false;
47
48 Derived const& derived() const
49 {
50 return *static_cast<Derived const*>(this);
51 }
52
53 template <typename Action>
54 action<Derived, Action>
55 operator[](Action f) const
56 {
57 return action<Derived, Action>(this->derived(), f);
58 }
59
60 template <typename Handler>
61 guard<Derived, Handler>
62 on_error(Handler f) const
63 {
64 return guard<Derived, Handler>(this->derived(), f);
65 }
66 };
67
68 namespace detail {
69 template <typename Parser>
70 static void assert_initialized_rule(Parser const& p) {
71 boost::ignore_unused(p);
72
73 // Assert that we are not copying an unitialized static rule. If
74 // the static is in another TU, it may be initialized after we copy
75 // it. If so, its name member will be nullptr.
76 //
77 // Rather than hardcoding behaviour for rule-type subject parsers,
78 // we simply allow get_info<> to do the check in debug builds.
79 #ifndef NDEBUG
80 what(p); // note: allows get_info<> to diagnose the issue
81 #endif
82 }
83 }
84
85 struct unary_category;
86 struct binary_category;
87
88 template <typename Subject, typename Derived>
89 struct unary_parser : parser<Derived>
90 {
91 typedef unary_category category;
92 typedef Subject subject_type;
93 static bool const has_action = Subject::has_action;
94
95 unary_parser(Subject const& subject)
96 : subject(subject) { detail::assert_initialized_rule(subject); }
97
98 unary_parser const& get_unary() const { return *this; }
99
100 Subject subject;
101 };
102
103 template <typename Left, typename Right, typename Derived>
104 struct binary_parser : parser<Derived>
105 {
106 typedef binary_category category;
107 typedef Left left_type;
108 typedef Right right_type;
109 static bool const has_action =
110 left_type::has_action || right_type::has_action;
111
112 binary_parser(Left const& left, Right const& right)
113 : left(left), right(right)
114 {
115 detail::assert_initialized_rule(left);
116 detail::assert_initialized_rule(right);
117 }
118
119 binary_parser const& get_binary() const { return *this; }
120
121 Left left;
122 Right right;
123 };
124
125 ///////////////////////////////////////////////////////////////////////////
126 // as_parser: convert a type, T, into a parser.
127 ///////////////////////////////////////////////////////////////////////////
128 namespace extension
129 {
130 namespace detail
131 {
132 namespace as_parser_guard
133 {
134 void as_spirit_parser(...);
135
136 template<typename T, typename R =
137 decltype(as_spirit_parser(boost::declval<T const&>()))>
138 struct deduce_as_parser
139 {
140 typedef R type;
141 typedef typename
142 boost::remove_cv<
143 typename boost::remove_reference<R>::type
144 >::type
145 value_type;
146
147 static type call(T const& v)
148 {
149 return as_spirit_parser(v);
150 }
151 };
152 template<typename T>
153 struct deduce_as_parser<T, void>
154 {};
155 }
156 using as_parser_guard::deduce_as_parser;
157 }
158
159 template <typename T, typename Enable = void>
160 struct as_parser : detail::deduce_as_parser<T> {};
161
162 template <>
163 struct as_parser<unused_type>
164 {
165 typedef unused_type type;
166 typedef unused_type value_type;
167 static type call(unused_type)
168 {
169 return unused;
170 }
171 };
172
173 template <typename Derived>
174 struct as_parser<Derived
175 , typename enable_if<is_base_of<parser_base, Derived>>::type>
176 {
177 typedef Derived const& type;
178 typedef Derived value_type;
179 static type call(Derived const& p)
180 {
181 return p;
182 }
183 };
184
185 template <typename Derived>
186 struct as_parser<parser<Derived>>
187 {
188 typedef Derived const& type;
189 typedef Derived value_type;
190 static type call(parser<Derived> const& p)
191 {
192 return p.derived();
193 }
194 };
195 }
196
197 template <typename T>
198 inline typename extension::as_parser<T>::type
199 as_parser(T const& x)
200 {
201 return extension::as_parser<T>::call(x);
202 }
203
204 template <typename Derived>
205 inline Derived const&
206 as_parser(parser<Derived> const& p)
207 {
208 return p.derived();
209 }
210
211 ///////////////////////////////////////////////////////////////////////////
212 // The main what function
213 //
214 // Note: unlike Spirit2, spirit parsers are no longer required to have a
215 // "what" member function. In X3, we specialize the get_info struct
216 // below where needed. If a specialization is not provided, the default
217 // below will be used. The default "what" result will be the typeid
218 // name of the parser if BOOST_SPIRIT_X3_NO_RTTI is not defined, otherwise
219 // "undefined"
220 ///////////////////////////////////////////////////////////////////////////
221 template <typename Parser, typename Enable = void>
222 struct get_info
223 {
224 typedef std::string result_type;
225 std::string operator()(Parser const&) const
226 {
227 #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
228 return typeid(Parser).name();
229 #else
230 return "undefined";
231 #endif
232 }
233 };
234
235 template <typename Parser>
236 std::string what(Parser const& p)
237 {
238 return get_info<Parser>()(p);
239 }
240 }}}
241
242 namespace boost { namespace spirit { namespace x3 { namespace traits
243 {
244 template <typename Subject, typename Derived, typename Context>
245 struct has_attribute<x3::unary_parser<Subject, Derived>, Context>
246 : has_attribute<Subject, Context> {};
247
248 template <typename Left, typename Right, typename Derived, typename Context>
249 struct has_attribute<x3::binary_parser<Left, Right, Derived>, Context>
250 : mpl::bool_<has_attribute<Left, Context>::value ||
251 has_attribute<Right, Context>::value> {};
252 }}}}
253
254 #endif