]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/qi/nonterminal/rule.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / boost / spirit / home / qi / nonterminal / rule.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 #if !defined(BOOST_SPIRIT_RULE_FEBRUARY_12_2007_1020AM)
8 #define BOOST_SPIRIT_RULE_FEBRUARY_12_2007_1020AM
9
10 #if defined(_MSC_VER)
11 #pragma once
12 #endif
13
14 #include <boost/assert.hpp>
15 #include <boost/static_assert.hpp>
16 #include <boost/config.hpp>
17 #include <boost/function.hpp>
18 #include <boost/mpl/vector.hpp>
19 #include <boost/type_traits/is_convertible.hpp>
20 #include <boost/type_traits/is_same.hpp>
21
22 #include <boost/fusion/include/vector.hpp>
23 #include <boost/fusion/include/size.hpp>
24 #include <boost/fusion/include/make_vector.hpp>
25 #include <boost/fusion/include/cons.hpp>
26 #include <boost/fusion/include/as_list.hpp>
27 #include <boost/fusion/include/as_vector.hpp>
28
29 #include <boost/spirit/home/support/unused.hpp>
30 #include <boost/spirit/home/support/argument.hpp>
31 #include <boost/spirit/home/support/context.hpp>
32 #include <boost/spirit/home/support/info.hpp>
33 #include <boost/spirit/home/qi/detail/attributes.hpp>
34 #include <boost/spirit/home/support/nonterminal/extract_param.hpp>
35 #include <boost/spirit/home/support/nonterminal/locals.hpp>
36 #include <boost/spirit/home/qi/reference.hpp>
37 #include <boost/spirit/home/qi/nonterminal/detail/parameterized.hpp>
38 #include <boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp>
39 #include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp>
40 #include <boost/spirit/home/qi/skip_over.hpp>
41
42 #include <boost/proto/extends.hpp>
43 #include <boost/proto/traits.hpp>
44 #include <boost/type_traits/is_reference.hpp>
45
46 #if defined(BOOST_MSVC)
47 # pragma warning(push)
48 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
49 # pragma warning(disable: 4127) // conditional expression is constant
50 #endif
51
52 namespace boost { namespace spirit { namespace qi
53 {
54 BOOST_PP_REPEAT(SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_USING_ATTRIBUTE, _)
55
56 using spirit::_pass_type;
57 using spirit::_val_type;
58 using spirit::_a_type;
59 using spirit::_b_type;
60 using spirit::_c_type;
61 using spirit::_d_type;
62 using spirit::_e_type;
63 using spirit::_f_type;
64 using spirit::_g_type;
65 using spirit::_h_type;
66 using spirit::_i_type;
67 using spirit::_j_type;
68
69 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
70
71 using spirit::_pass;
72 using spirit::_val;
73 using spirit::_a;
74 using spirit::_b;
75 using spirit::_c;
76 using spirit::_d;
77 using spirit::_e;
78 using spirit::_f;
79 using spirit::_g;
80 using spirit::_h;
81 using spirit::_i;
82 using spirit::_j;
83
84 #endif
85
86 using spirit::info;
87 using spirit::locals;
88
89 template <
90 typename Iterator, typename T1, typename T2, typename T3
91 , typename T4>
92 struct rule
93 : proto::extends<
94 typename proto::terminal<
95 reference<rule<Iterator, T1, T2, T3, T4> const>
96 >::type
97 , rule<Iterator, T1, T2, T3, T4>
98 >
99 , parser<rule<Iterator, T1, T2, T3, T4> >
100 {
101 typedef Iterator iterator_type;
102 typedef rule<Iterator, T1, T2, T3, T4> this_type;
103 typedef reference<this_type const> reference_;
104 typedef typename proto::terminal<reference_>::type terminal;
105 typedef proto::extends<terminal, this_type> base_type;
106 typedef mpl::vector<T1, T2, T3, T4> template_params;
107
108 // The rule's locals_type: a sequence of types to be used as local variables
109 typedef typename
110 spirit::detail::extract_locals<template_params>::type
111 locals_type;
112
113 // The rule's skip-parser type
114 typedef typename
115 spirit::detail::extract_component<
116 qi::domain, template_params>::type
117 skipper_type;
118
119 // The rule's encoding type
120 typedef typename
121 spirit::detail::extract_encoding<template_params>::type
122 encoding_type;
123
124 // The rule's signature
125 typedef typename
126 spirit::detail::extract_sig<template_params, encoding_type, qi::domain>::type
127 sig_type;
128
129 // This is the rule's attribute type
130 typedef typename
131 spirit::detail::attr_from_sig<sig_type>::type
132 attr_type;
133 BOOST_STATIC_ASSERT_MSG(
134 !is_reference<attr_type>::value,
135 "Reference qualifier on Qi rule attribute is meaningless");
136 typedef attr_type& attr_reference_type;
137
138 // parameter_types is a sequence of types passed as parameters to the rule
139 typedef typename
140 spirit::detail::params_from_sig<sig_type>::type
141 parameter_types;
142
143 static size_t const params_size =
144 fusion::result_of::size<parameter_types>::type::value;
145
146 typedef context<
147 fusion::cons<attr_reference_type, parameter_types>
148 , locals_type>
149 context_type;
150
151 typedef function<
152 bool(Iterator& first, Iterator const& last
153 , context_type& context
154 , skipper_type const& skipper
155 )>
156 function_type;
157
158 typedef typename
159 mpl::if_<
160 is_same<encoding_type, unused_type>
161 , unused_type
162 , tag::char_code<tag::encoding, encoding_type>
163 >::type
164 encoding_modifier_type;
165
166 explicit rule(std::string const& name = "unnamed-rule")
167 : base_type(terminal::make(reference_(*this)))
168 , name_(name)
169 {
170 }
171
172 rule(rule const& rhs)
173 : base_type(terminal::make(reference_(*this)))
174 , name_(rhs.name_)
175 , f(rhs.f)
176 {
177 }
178
179 template <typename Auto, typename Expr>
180 static void define(rule& /*lhs*/, Expr const& /*expr*/, mpl::false_)
181 {
182 // Report invalid expression error as early as possible.
183 // If you got an error_invalid_expression error message here,
184 // then the expression (expr) is not a valid spirit qi expression.
185 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
186 }
187
188 template <typename Auto, typename Expr>
189 static void define(rule& lhs, Expr const& expr, mpl::true_)
190 {
191 lhs.f = detail::bind_parser<Auto>(
192 compile<qi::domain>(expr, encoding_modifier_type()));
193 }
194
195 template <typename Expr>
196 rule(Expr const& expr, std::string const& name = "unnamed-rule")
197 : base_type(terminal::make(reference_(*this)))
198 , name_(name)
199 {
200 define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>());
201 }
202
203 rule& operator=(rule const& rhs)
204 {
205 // The following assertion fires when you try to initialize a rule
206 // from an uninitialized one. Did you mean to refer to the right
207 // hand side rule instead of assigning from it? In this case you
208 // should write lhs = rhs.alias();
209 BOOST_ASSERT(rhs.f && "Did you mean rhs.alias() instead of rhs?");
210
211 f = rhs.f;
212 name_ = rhs.name_;
213 return *this;
214 }
215
216 std::string const& name() const
217 {
218 return name_;
219 }
220
221 void name(std::string const& str)
222 {
223 name_ = str;
224 }
225
226 template <typename Expr>
227 rule& operator=(Expr const& expr)
228 {
229 define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>());
230 return *this;
231 }
232
233 // VC7.1 has problems to resolve 'rule' without explicit template parameters
234 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
235 // g++ 3.3 barfs if this is a member function :(
236 template <typename Expr>
237 friend rule& operator%=(rule& r, Expr const& expr)
238 {
239 define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>());
240 return r;
241 }
242
243 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
244 // non-const version needed to suppress proto's %= kicking in
245 template <typename Expr>
246 friend rule& operator%=(rule& r, Expr& expr)
247 {
248 return r %= static_cast<Expr const&>(expr);
249 }
250 #else
251 // for rvalue references
252 template <typename Expr>
253 friend rule& operator%=(rule& r, Expr&& expr)
254 {
255 define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>());
256 return r;
257 }
258 #endif
259
260 #else
261 // both friend functions have to be defined out of class as VC7.1
262 // will complain otherwise
263 template <typename OutputIterator_, typename T1_, typename T2_
264 , typename T3_, typename T4_, typename Expr>
265 friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
266 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr);
267
268 // non-const version needed to suppress proto's %= kicking in
269 template <typename OutputIterator_, typename T1_, typename T2_
270 , typename T3_, typename T4_, typename Expr>
271 friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
272 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr& expr);
273 #endif
274
275 template <typename Context, typename Iterator_>
276 struct attribute
277 {
278 typedef attr_type type;
279 };
280
281 template <typename Context, typename Skipper, typename Attribute>
282 bool parse(Iterator& first, Iterator const& last
283 , Context& /*context*/, Skipper const& skipper
284 , Attribute& attr_param) const
285 {
286 BOOST_STATIC_ASSERT_MSG((is_same<skipper_type, unused_type>::value ||
287 !is_same<Skipper, unused_type>::value),
288 "The rule was instantiated with a skipper type but you have not pass any. "
289 "Did you use `parse` instead of `phrase_parse`?");
290 BOOST_STATIC_ASSERT_MSG(
291 (is_convertible<Skipper const&, skipper_type>::value),
292 "The passed skipper is not compatible/convertible to one "
293 "that the rule was instantiated with");
294 if (f)
295 {
296 // do a preskip if this is an implied lexeme
297 if (is_same<skipper_type, unused_type>::value)
298 qi::skip_over(first, last, skipper);
299
300 // do down-stream transformation, provides attribute for
301 // rhs parser
302 typedef traits::transform_attribute<
303 Attribute, attr_type, domain>
304 transform;
305
306 typename transform::type attr_ = transform::pre(attr_param);
307
308 // If you are seeing a compilation error here, you are probably
309 // trying to use a rule or a grammar which has inherited
310 // attributes, without passing values for them.
311 context_type context(attr_);
312
313 // If you are seeing a compilation error here stating that the
314 // fourth parameter can't be converted to a required target type
315 // then you are probably trying to use a rule or a grammar with
316 // an incompatible skipper type.
317 if (f(first, last, context, skipper))
318 {
319 // do up-stream transformation, this integrates the results
320 // back into the original attribute value, if appropriate
321 transform::post(attr_param, attr_);
322 return true;
323 }
324
325 // inform attribute transformation of failed rhs
326 transform::fail(attr_param);
327 }
328 return false;
329 }
330
331 template <typename Context, typename Skipper
332 , typename Attribute, typename Params>
333 bool parse(Iterator& first, Iterator const& last
334 , Context& caller_context, Skipper const& skipper
335 , Attribute& attr_param, Params const& params) const
336 {
337 BOOST_STATIC_ASSERT_MSG((is_same<skipper_type, unused_type>::value ||
338 !is_same<Skipper, unused_type>::value),
339 "The rule was instantiated with a skipper type but you have not pass any. "
340 "Did you use `parse` instead of `phrase_parse`?");
341 BOOST_STATIC_ASSERT_MSG(
342 (is_convertible<Skipper const&, skipper_type>::value),
343 "The passed skipper is not compatible/convertible to one "
344 "that the rule was instantiated with");
345 if (f)
346 {
347 // do a preskip if this is an implied lexeme
348 if (is_same<skipper_type, unused_type>::value)
349 qi::skip_over(first, last, skipper);
350
351 // do down-stream transformation, provides attribute for
352 // rhs parser
353 typedef traits::transform_attribute<
354 Attribute, attr_type, domain>
355 transform;
356
357 typename transform::type attr_ = transform::pre(attr_param);
358
359 // If you are seeing a compilation error here, you are probably
360 // trying to use a rule or a grammar which has inherited
361 // attributes, passing values of incompatible types for them.
362 context_type context(attr_, params, caller_context);
363
364 // If you are seeing a compilation error here stating that the
365 // fourth parameter can't be converted to a required target type
366 // then you are probably trying to use a rule or a grammar with
367 // an incompatible skipper type.
368 if (f(first, last, context, skipper))
369 {
370 // do up-stream transformation, this integrates the results
371 // back into the original attribute value, if appropriate
372 transform::post(attr_param, attr_);
373 return true;
374 }
375
376 // inform attribute transformation of failed rhs
377 transform::fail(attr_param);
378 }
379 return false;
380 }
381
382 template <typename Context>
383 info what(Context& /*context*/) const
384 {
385 return info(name_);
386 }
387
388 reference_ alias() const
389 {
390 return reference_(*this);
391 }
392
393 typename proto::terminal<this_type>::type copy() const
394 {
395 typename proto::terminal<this_type>::type result = {*this};
396 return result;
397 }
398
399 // bring in the operator() overloads
400 rule const& get_parameterized_subject() const { return *this; }
401 typedef rule parameterized_subject_type;
402 #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp>
403
404 std::string name_;
405 function_type f;
406 };
407
408 #if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
409 template <typename OutputIterator_, typename T1_, typename T2_
410 , typename T3_, typename T4_, typename Expr>
411 rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
412 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr)
413 {
414 // Report invalid expression error as early as possible.
415 // If you got an error_invalid_expression error message here,
416 // then the expression (expr) is not a valid spirit qi expression.
417 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
418
419 typedef typename
420 rule<OutputIterator_, T1_, T2_, T3_, T4_>::encoding_modifier_type
421 encoding_modifier_type;
422
423 r.f = detail::bind_parser<mpl::true_>(
424 compile<qi::domain>(expr, encoding_modifier_type()));
425 return r;
426 }
427
428 template <typename Iterator_, typename T1_, typename T2_
429 , typename T3_, typename T4_, typename Expr>
430 rule<Iterator_, T1_, T2_, T3_, T4_>& operator%=(
431 rule<Iterator_, T1_, T2_, T3_, T4_>& r, Expr& expr)
432 {
433 return r %= static_cast<Expr const&>(expr);
434 }
435 #endif
436 }}}
437
438 namespace boost { namespace spirit { namespace traits
439 {
440 ///////////////////////////////////////////////////////////////////////////
441 template <
442 typename IteratorA, typename IteratorB, typename Attribute
443 , typename Context, typename T1, typename T2, typename T3, typename T4>
444 struct handles_container<
445 qi::rule<IteratorA, T1, T2, T3, T4>, Attribute, Context, IteratorB>
446 : traits::is_container<
447 typename attribute_of<
448 qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB
449 >::type
450 >
451 {};
452 }}}
453
454 #if defined(BOOST_MSVC)
455 # pragma warning(pop)
456 #endif
457
458 #endif