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