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