Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/spirit/home/karma/nonterminal/rule.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 // Copyright (c) 2001-2011 Joel de Guzman | |
2 // Copyright (c) 2001-2011 Hartmut Kaiser | |
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_KARMA_RULE_MAR_05_2007_0455PM) | |
8 #define BOOST_SPIRIT_KARMA_RULE_MAR_05_2007_0455PM | |
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_const.hpp> | |
19 #include <boost/type_traits/add_reference.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/karma/delimit_out.hpp> | |
34 #include <boost/spirit/home/karma/detail/attributes.hpp> | |
35 #include <boost/spirit/home/support/nonterminal/extract_param.hpp> | |
36 #include <boost/spirit/home/support/nonterminal/locals.hpp> | |
37 #include <boost/spirit/home/karma/reference.hpp> | |
38 #include <boost/spirit/home/karma/detail/output_iterator.hpp> | |
39 #include <boost/spirit/home/karma/nonterminal/nonterminal_fwd.hpp> | |
40 #include <boost/spirit/home/karma/nonterminal/detail/generator_binder.hpp> | |
41 #include <boost/spirit/home/karma/nonterminal/detail/parameterized.hpp> | |
42 | |
43 #if defined(BOOST_MSVC) | |
44 # pragma warning(push) | |
45 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning | |
46 #endif | |
47 | |
48 namespace boost { namespace spirit { namespace karma | |
49 { | |
50 BOOST_PP_REPEAT(SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_USING_ATTRIBUTE, _) | |
51 | |
52 using spirit::_pass_type; | |
53 using spirit::_val_type; | |
54 using spirit::_a_type; | |
55 using spirit::_b_type; | |
56 using spirit::_c_type; | |
57 using spirit::_d_type; | |
58 using spirit::_e_type; | |
59 using spirit::_f_type; | |
60 using spirit::_g_type; | |
61 using spirit::_h_type; | |
62 using spirit::_i_type; | |
63 using spirit::_j_type; | |
64 | |
65 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS | |
66 | |
67 using spirit::_pass; | |
68 using spirit::_val; | |
69 using spirit::_a; | |
70 using spirit::_b; | |
71 using spirit::_c; | |
72 using spirit::_d; | |
73 using spirit::_e; | |
74 using spirit::_f; | |
75 using spirit::_g; | |
76 using spirit::_h; | |
77 using spirit::_i; | |
78 using spirit::_j; | |
79 | |
80 #endif | |
81 | |
82 using spirit::info; | |
83 using spirit::locals; | |
84 | |
85 template < | |
86 typename OutputIterator, typename T1, typename T2, typename T3 | |
87 , typename T4> | |
88 struct rule | |
89 : proto::extends< | |
90 typename proto::terminal< | |
91 reference<rule<OutputIterator, T1, T2, T3, T4> const> | |
92 >::type | |
93 , rule<OutputIterator, T1, T2, T3, T4> | |
94 > | |
95 , generator<rule<OutputIterator, T1, T2, T3, T4> > | |
96 { | |
97 typedef mpl::int_<generator_properties::all_properties> properties; | |
98 | |
99 typedef OutputIterator iterator_type; | |
100 typedef rule<OutputIterator, T1, T2, T3, T4> this_type; | |
101 typedef reference<this_type const> reference_; | |
102 typedef typename proto::terminal<reference_>::type terminal; | |
103 typedef proto::extends<terminal, this_type> base_type; | |
104 typedef mpl::vector<T1, T2, T3, T4> template_params; | |
105 | |
106 // the output iterator is always wrapped by karma | |
107 typedef detail::output_iterator<OutputIterator, properties> | |
108 output_iterator; | |
109 | |
110 // locals_type is a sequence of types to be used as local variables | |
111 typedef typename | |
112 spirit::detail::extract_locals<template_params>::type | |
113 locals_type; | |
114 | |
115 // The delimiter-generator type | |
116 typedef typename | |
117 spirit::detail::extract_component< | |
118 karma::domain, template_params>::type | |
119 delimiter_type; | |
120 | |
121 // The rule's signature | |
122 typedef typename | |
123 spirit::detail::extract_sig<template_params>::type | |
124 sig_type; | |
125 | |
126 // The rule's encoding type | |
127 typedef typename | |
128 spirit::detail::extract_encoding<template_params>::type | |
129 encoding_type; | |
130 | |
131 // This is the rule's attribute type | |
132 typedef typename | |
133 spirit::detail::attr_from_sig<sig_type>::type | |
134 attr_type; | |
135 typedef typename add_reference< | |
136 typename add_const<attr_type>::type>::type | |
137 attr_reference_type; | |
138 | |
139 // parameter_types is a sequence of types passed as parameters to the rule | |
140 typedef typename | |
141 spirit::detail::params_from_sig<sig_type>::type | |
142 parameter_types; | |
143 | |
144 static size_t const params_size = | |
145 fusion::result_of::size<parameter_types>::type::value; | |
146 | |
147 // the context passed to the right hand side of a rule contains | |
148 // the attribute and the parameters for this particular rule invocation | |
149 typedef context< | |
150 fusion::cons<attr_reference_type, parameter_types> | |
151 , locals_type> | |
152 context_type; | |
153 | |
154 typedef function< | |
155 bool(output_iterator&, context_type&, delimiter_type const&)> | |
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 karma expression. | |
185 BOOST_SPIRIT_ASSERT_MATCH(karma::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_generator<Auto>( | |
192 compile<karma::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<karma::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<karma::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<karma::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<karma::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 Unused> | |
276 struct attribute | |
277 { | |
278 typedef attr_type type; | |
279 }; | |
280 | |
281 template <typename Context, typename Delimiter, typename Attribute> | |
282 bool generate(output_iterator& sink, Context&, Delimiter const& delim | |
283 , Attribute const& attr) const | |
284 { | |
285 if (f) | |
286 { | |
287 // Create an attribute if none is supplied. | |
288 typedef traits::make_attribute<attr_type, Attribute> | |
289 make_attribute; | |
290 typedef traits::transform_attribute< | |
291 typename make_attribute::type, attr_type, domain> | |
292 transform; | |
293 | |
294 typename transform::type attr_ = | |
295 traits::pre_transform<domain, attr_type>( | |
296 make_attribute::call(attr)); | |
297 | |
298 // If you are seeing a compilation error here, you are probably | |
299 // trying to use a rule or a grammar which has inherited | |
300 // attributes, without passing values for them. | |
301 context_type context(attr_); | |
302 | |
303 // If you are seeing a compilation error here stating that the | |
304 // third parameter can't be converted to a karma::reference | |
305 // then you are probably trying to use a rule or a grammar with | |
306 // an incompatible delimiter type. | |
307 if (f(sink, context, delim)) | |
308 { | |
309 // do a post-delimit if this is an implied verbatim | |
310 if (is_same<delimiter_type, unused_type>::value) | |
311 karma::delimit_out(sink, delim); | |
312 | |
313 return true; | |
314 } | |
315 } | |
316 return false; | |
317 } | |
318 | |
319 template <typename Context, typename Delimiter, typename Attribute | |
320 , typename Params> | |
321 bool generate(output_iterator& sink, Context& caller_context | |
322 , Delimiter const& delim, Attribute const& attr | |
323 , Params const& params) const | |
324 { | |
325 if (f) | |
326 { | |
327 // Create an attribute if none is supplied. | |
328 typedef traits::make_attribute<attr_type, Attribute> | |
329 make_attribute; | |
330 typedef traits::transform_attribute< | |
331 typename make_attribute::type, attr_type, domain> | |
332 transform; | |
333 | |
334 typename transform::type attr_ = | |
335 traits::pre_transform<domain, attr_type>( | |
336 make_attribute::call(attr)); | |
337 | |
338 // If you are seeing a compilation error here, you are probably | |
339 // trying to use a rule or a grammar which has inherited | |
340 // attributes, passing values of incompatible types for them. | |
341 context_type context(attr_, params, caller_context); | |
342 | |
343 // If you are seeing a compilation error here stating that the | |
344 // third parameter can't be converted to a karma::reference | |
345 // then you are probably trying to use a rule or a grammar with | |
346 // an incompatible delimiter type. | |
347 if (f(sink, context, delim)) | |
348 { | |
349 // do a post-delimit if this is an implied verbatim | |
350 if (is_same<delimiter_type, unused_type>::value) | |
351 karma::delimit_out(sink, delim); | |
352 | |
353 return true; | |
354 } | |
355 } | |
356 return false; | |
357 } | |
358 | |
359 template <typename Context> | |
360 info what(Context& /*context*/) const | |
361 { | |
362 return info(name_); | |
363 } | |
364 | |
365 reference_ alias() const | |
366 { | |
367 return reference_(*this); | |
368 } | |
369 | |
370 typename proto::terminal<this_type>::type copy() const | |
371 { | |
372 typename proto::terminal<this_type>::type result = {*this}; | |
373 return result; | |
374 } | |
375 | |
376 // bring in the operator() overloads | |
377 rule const& get_parameterized_subject() const { return *this; } | |
378 typedef rule parameterized_subject_type; | |
379 #include <boost/spirit/home/karma/nonterminal/detail/fcall.hpp> | |
380 | |
381 std::string name_; | |
382 function_type f; | |
383 }; | |
384 | |
385 #if BOOST_WORKAROUND(BOOST_MSVC, < 1400) | |
386 template <typename OutputIterator_, typename T1_, typename T2_ | |
387 , typename T3_, typename T4_, typename Expr> | |
388 rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=( | |
389 rule<OutputIterator_, T1_, T2_, T3_, T4_>&r, Expr const& expr) | |
390 { | |
391 // Report invalid expression error as early as possible. | |
392 // If you got an error_invalid_expression error message here, then | |
393 // the expression (expr) is not a valid spirit karma expression. | |
394 BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr); | |
395 | |
396 typedef typename | |
397 rule<OutputIterator_, T1_, T2_, T3_, T4_>::encoding_modifier_type | |
398 encoding_modifier_type; | |
399 | |
400 r.f = detail::bind_generator<mpl::true_>( | |
401 compile<karma::domain>(expr, encoding_modifier_type())); | |
402 return r; | |
403 } | |
404 | |
405 // non-const version needed to suppress proto's %= kicking in | |
406 template <typename OutputIterator_, typename T1_, typename T2_ | |
407 , typename T3_, typename T4_, typename Expr> | |
408 rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=( | |
409 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr& expr) | |
410 { | |
411 return r %= static_cast<Expr const&>(expr); | |
412 } | |
413 #endif | |
414 }}} | |
415 | |
416 namespace boost { namespace spirit { namespace traits | |
417 { | |
418 namespace detail | |
419 { | |
420 template <typename RuleAttribute, typename Attribute> | |
421 struct nonterminal_handles_container | |
422 : mpl::and_< | |
423 traits::is_container<RuleAttribute> | |
424 , is_convertible<Attribute, RuleAttribute> > | |
425 {}; | |
426 } | |
427 | |
428 /////////////////////////////////////////////////////////////////////////// | |
429 template < | |
430 typename IteratorA, typename IteratorB, typename Attribute | |
431 , typename Context, typename T1, typename T2, typename T3, typename T4> | |
432 struct handles_container< | |
433 karma::rule<IteratorA, T1, T2, T3, T4>, Attribute, Context | |
434 , IteratorB> | |
435 : detail::nonterminal_handles_container< | |
436 typename attribute_of< | |
437 karma::rule<IteratorA, T1, T2, T3, T4> | |
438 , Context, IteratorB | |
439 >::type, Attribute> | |
440 {}; | |
441 }}} | |
442 | |
443 #if defined(BOOST_MSVC) | |
444 # pragma warning(pop) | |
445 #endif | |
446 | |
447 #endif |