Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Copyright (c) 2001-2011 Joel de Guzman
|
Chris@16
|
3 Copyright (c) 2001-2012 Hartmut Kaiser
|
Chris@16
|
4
|
Chris@16
|
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7 ==============================================================================*/
|
Chris@16
|
8 #if !defined(BOOST_SPIRIT_ATTRIBUTES_JANUARY_29_2007_0954AM)
|
Chris@16
|
9 #define BOOST_SPIRIT_ATTRIBUTES_JANUARY_29_2007_0954AM
|
Chris@16
|
10
|
Chris@16
|
11 #if defined(_MSC_VER)
|
Chris@16
|
12 #pragma once
|
Chris@16
|
13 #endif
|
Chris@16
|
14
|
Chris@16
|
15 #include <boost/spirit/home/support/unused.hpp>
|
Chris@16
|
16 #include <boost/spirit/home/support/has_semantic_action.hpp>
|
Chris@16
|
17 #include <boost/spirit/home/support/attributes_fwd.hpp>
|
Chris@16
|
18 #include <boost/spirit/home/support/container.hpp>
|
Chris@16
|
19 #include <boost/spirit/home/support/detail/hold_any.hpp>
|
Chris@16
|
20 #include <boost/spirit/home/support/detail/as_variant.hpp>
|
Chris@16
|
21 #include <boost/optional/optional.hpp>
|
Chris@16
|
22 #include <boost/fusion/include/transform.hpp>
|
Chris@16
|
23 #include <boost/fusion/include/filter_if.hpp>
|
Chris@16
|
24 #include <boost/fusion/include/as_vector.hpp>
|
Chris@16
|
25 #include <boost/fusion/include/push_front.hpp>
|
Chris@16
|
26 #include <boost/fusion/include/pop_front.hpp>
|
Chris@16
|
27 #include <boost/fusion/include/is_sequence.hpp>
|
Chris@16
|
28 #include <boost/fusion/include/for_each.hpp>
|
Chris@16
|
29 #include <boost/fusion/include/is_view.hpp>
|
Chris@16
|
30 #include <boost/fusion/include/mpl.hpp>
|
Chris@16
|
31 #include <boost/foreach.hpp>
|
Chris@16
|
32 #include <boost/utility/value_init.hpp>
|
Chris@16
|
33 #include <boost/type_traits/is_same.hpp>
|
Chris@16
|
34 #include <boost/type_traits/is_convertible.hpp>
|
Chris@16
|
35 #include <boost/mpl/eval_if.hpp>
|
Chris@16
|
36 #include <boost/mpl/end.hpp>
|
Chris@16
|
37 #include <boost/mpl/find_if.hpp>
|
Chris@16
|
38 #include <boost/mpl/identity.hpp>
|
Chris@16
|
39 #include <boost/mpl/deref.hpp>
|
Chris@16
|
40 #include <boost/mpl/distance.hpp>
|
Chris@16
|
41 #include <boost/mpl/or.hpp>
|
Chris@16
|
42 #include <boost/mpl/has_xxx.hpp>
|
Chris@16
|
43 #include <boost/mpl/equal.hpp>
|
Chris@16
|
44 #include <boost/proto/proto_fwd.hpp>
|
Chris@16
|
45 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
46 #include <boost/variant.hpp>
|
Chris@16
|
47 #include <boost/range/iterator_range.hpp>
|
Chris@16
|
48 #include <boost/config.hpp>
|
Chris@16
|
49 #include <vector>
|
Chris@16
|
50 #include <utility>
|
Chris@16
|
51 #include <ios>
|
Chris@16
|
52
|
Chris@16
|
53 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
54 namespace boost { namespace spirit { namespace traits
|
Chris@16
|
55 {
|
Chris@16
|
56 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
57 // This file deals with attribute related functions and meta-functions
|
Chris@16
|
58 // including generalized attribute transformation utilities for Spirit
|
Chris@16
|
59 // components.
|
Chris@16
|
60 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
61
|
Chris@16
|
62 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
63 // Find out if T can be a (strong) substitute for Expected attribute
|
Chris@16
|
64 namespace detail
|
Chris@16
|
65 {
|
Chris@16
|
66 template <typename T, typename Expected>
|
Chris@16
|
67 struct value_type_is_substitute
|
Chris@16
|
68 : is_substitute<
|
Chris@16
|
69 typename container_value<T>::type
|
Chris@16
|
70 , typename container_value<Expected>::type>
|
Chris@16
|
71 {};
|
Chris@16
|
72
|
Chris@16
|
73 template <typename T, typename Expected, typename Enable = void>
|
Chris@16
|
74 struct is_substitute_impl : is_same<T, Expected> {};
|
Chris@16
|
75
|
Chris@16
|
76 template <typename T, typename Expected>
|
Chris@16
|
77 struct is_substitute_impl<T, Expected,
|
Chris@16
|
78 typename enable_if<
|
Chris@16
|
79 mpl::and_<
|
Chris@16
|
80 fusion::traits::is_sequence<T>,
|
Chris@16
|
81 fusion::traits::is_sequence<Expected>,
|
Chris@16
|
82 mpl::equal<T, Expected, is_substitute<mpl::_1, mpl::_2> >
|
Chris@16
|
83 >
|
Chris@16
|
84 >::type>
|
Chris@16
|
85 : mpl::true_ {};
|
Chris@16
|
86
|
Chris@16
|
87 template <typename T, typename Expected>
|
Chris@16
|
88 struct is_substitute_impl<T, Expected,
|
Chris@16
|
89 typename enable_if<
|
Chris@16
|
90 mpl::and_<
|
Chris@16
|
91 is_container<T>,
|
Chris@16
|
92 is_container<Expected>,
|
Chris@16
|
93 detail::value_type_is_substitute<T, Expected>
|
Chris@16
|
94 >
|
Chris@16
|
95 >::type>
|
Chris@16
|
96 : mpl::true_ {};
|
Chris@16
|
97 }
|
Chris@16
|
98
|
Chris@16
|
99 template <typename T, typename Expected, typename Enable /*= void*/>
|
Chris@16
|
100 struct is_substitute
|
Chris@16
|
101 : detail::is_substitute_impl<T, Expected> {};
|
Chris@16
|
102
|
Chris@16
|
103 template <typename T, typename Expected>
|
Chris@16
|
104 struct is_substitute<optional<T>, optional<Expected> >
|
Chris@16
|
105 : is_substitute<T, Expected> {};
|
Chris@16
|
106
|
Chris@16
|
107 template <typename T>
|
Chris@16
|
108 struct is_substitute<T, T
|
Chris@16
|
109 , typename enable_if<not_is_optional<T> >::type>
|
Chris@16
|
110 : mpl::true_ {};
|
Chris@16
|
111
|
Chris@16
|
112 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
113 // Find out if T can be a weak substitute for Expected attribute
|
Chris@16
|
114 namespace detail
|
Chris@16
|
115 {
|
Chris@16
|
116 // A type, which is convertible to the attribute is at the same time
|
Chris@16
|
117 // usable as its weak substitute.
|
Chris@16
|
118 template <typename T, typename Expected, typename Enable = void>
|
Chris@16
|
119 struct is_weak_substitute_impl : is_convertible<T, Expected> {};
|
Chris@16
|
120
|
Chris@16
|
121 // // An exposed attribute is a weak substitute for a supplied container
|
Chris@16
|
122 // // attribute if it is a weak substitute for its value_type. This is
|
Chris@16
|
123 // // true as all character parsers are compatible with a container
|
Chris@16
|
124 // // attribute having the corresponding character type as its value_type.
|
Chris@16
|
125 // template <typename T, typename Expected>
|
Chris@16
|
126 // struct is_weak_substitute_for_value_type
|
Chris@16
|
127 // : is_weak_substitute<T, typename container_value<Expected>::type>
|
Chris@16
|
128 // {};
|
Chris@16
|
129 //
|
Chris@16
|
130 // template <typename T, typename Expected>
|
Chris@16
|
131 // struct is_weak_substitute_impl<T, Expected,
|
Chris@16
|
132 // typename enable_if<
|
Chris@16
|
133 // mpl::and_<
|
Chris@16
|
134 // mpl::not_<is_string<T> >
|
Chris@16
|
135 // , is_string<Expected>
|
Chris@16
|
136 // , is_weak_substitute_for_value_type<T, Expected> >
|
Chris@16
|
137 // >::type>
|
Chris@16
|
138 // : mpl::true_
|
Chris@16
|
139 // {};
|
Chris@16
|
140
|
Chris@16
|
141 // An exposed container attribute is a weak substitute for a supplied
|
Chris@16
|
142 // container attribute if and only if their value_types are weak
|
Chris@16
|
143 // substitutes.
|
Chris@16
|
144 template <typename T, typename Expected>
|
Chris@16
|
145 struct value_type_is_weak_substitute
|
Chris@16
|
146 : is_weak_substitute<
|
Chris@16
|
147 typename container_value<T>::type
|
Chris@16
|
148 , typename container_value<Expected>::type>
|
Chris@16
|
149 {};
|
Chris@16
|
150
|
Chris@16
|
151 template <typename T, typename Expected>
|
Chris@16
|
152 struct is_weak_substitute_impl<T, Expected,
|
Chris@16
|
153 typename enable_if<
|
Chris@16
|
154 mpl::and_<
|
Chris@16
|
155 is_container<T>
|
Chris@16
|
156 , is_container<Expected>
|
Chris@16
|
157 , value_type_is_weak_substitute<T, Expected> >
|
Chris@16
|
158 >::type>
|
Chris@16
|
159 : mpl::true_ {};
|
Chris@16
|
160
|
Chris@16
|
161 // Two fusion sequences are weak substitutes if and only if their
|
Chris@16
|
162 // elements are pairwise weak substitutes.
|
Chris@16
|
163 template <typename T, typename Expected>
|
Chris@16
|
164 struct is_weak_substitute_impl<T, Expected,
|
Chris@16
|
165 typename enable_if<
|
Chris@16
|
166 mpl::and_<
|
Chris@16
|
167 fusion::traits::is_sequence<T>
|
Chris@16
|
168 , fusion::traits::is_sequence<Expected>
|
Chris@16
|
169 , mpl::equal<T, Expected, is_weak_substitute<mpl::_1, mpl::_2> > >
|
Chris@16
|
170 >::type>
|
Chris@16
|
171 : mpl::true_ {};
|
Chris@16
|
172
|
Chris@16
|
173 // If this is not defined, the main template definition above will return
|
Chris@16
|
174 // true if T is convertible to the first type in a fusion::vector. We
|
Chris@16
|
175 // globally declare any non-Fusion sequence T as not compatible with any
|
Chris@16
|
176 // Fusion sequence 'Expected'.
|
Chris@16
|
177 template <typename T, typename Expected>
|
Chris@16
|
178 struct is_weak_substitute_impl<T, Expected,
|
Chris@16
|
179 typename enable_if<
|
Chris@16
|
180 mpl::and_<
|
Chris@16
|
181 mpl::not_<fusion::traits::is_sequence<T> >
|
Chris@16
|
182 , fusion::traits::is_sequence<Expected> >
|
Chris@16
|
183 >::type>
|
Chris@16
|
184 : mpl::false_ {};
|
Chris@16
|
185 }
|
Chris@16
|
186
|
Chris@16
|
187 // main template forwards to detail namespace, this helps older compilers
|
Chris@16
|
188 // to disambiguate things
|
Chris@16
|
189 template <typename T, typename Expected, typename Enable /*= void*/>
|
Chris@16
|
190 struct is_weak_substitute
|
Chris@16
|
191 : detail::is_weak_substitute_impl<T, Expected> {};
|
Chris@16
|
192
|
Chris@16
|
193 template <typename T, typename Expected>
|
Chris@16
|
194 struct is_weak_substitute<optional<T>, optional<Expected> >
|
Chris@16
|
195 : is_weak_substitute<T, Expected> {};
|
Chris@16
|
196
|
Chris@16
|
197 template <typename T, typename Expected>
|
Chris@16
|
198 struct is_weak_substitute<optional<T>, Expected>
|
Chris@16
|
199 : is_weak_substitute<T, Expected> {};
|
Chris@16
|
200
|
Chris@16
|
201 template <typename T, typename Expected>
|
Chris@16
|
202 struct is_weak_substitute<T, optional<Expected> >
|
Chris@16
|
203 : is_weak_substitute<T, Expected> {};
|
Chris@16
|
204
|
Chris@16
|
205 #define BOOST_SPIRIT_IS_WEAK_SUBSTITUTE(z, N, _) \
|
Chris@16
|
206 is_weak_substitute<BOOST_PP_CAT(T, N), Expected>::type::value && \
|
Chris@16
|
207 /***/
|
Chris@16
|
208
|
Chris@16
|
209 // make sure unused variant parameters do not affect the outcome
|
Chris@16
|
210 template <typename Expected>
|
Chris@16
|
211 struct is_weak_substitute<boost::detail::variant::void_, Expected>
|
Chris@16
|
212 : mpl::true_
|
Chris@16
|
213 {};
|
Chris@16
|
214
|
Chris@16
|
215 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Expected>
|
Chris@16
|
216 struct is_weak_substitute<
|
Chris@16
|
217 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Expected>
|
Chris@16
|
218 : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
|
Chris@16
|
219 , BOOST_SPIRIT_IS_WEAK_SUBSTITUTE, _) true>
|
Chris@16
|
220 {};
|
Chris@16
|
221
|
Chris@16
|
222 #undef BOOST_SPIRIT_IS_WEAK_SUBSTITUTE
|
Chris@16
|
223
|
Chris@16
|
224 template <typename T>
|
Chris@16
|
225 struct is_weak_substitute<T, T
|
Chris@16
|
226 , typename enable_if<
|
Chris@16
|
227 mpl::and_<not_is_optional<T>, not_is_variant<T> >
|
Chris@16
|
228 >::type>
|
Chris@16
|
229 : mpl::true_ {};
|
Chris@16
|
230
|
Chris@16
|
231 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
232 template <typename T, typename Enable/* = void*/>
|
Chris@16
|
233 struct is_proxy : mpl::false_ {};
|
Chris@16
|
234
|
Chris@16
|
235 template <typename T>
|
Chris@16
|
236 struct is_proxy<T,
|
Chris@16
|
237 typename enable_if<
|
Chris@16
|
238 mpl::and_<
|
Chris@16
|
239 fusion::traits::is_sequence<T>,
|
Chris@16
|
240 fusion::traits::is_view<T>
|
Chris@16
|
241 >
|
Chris@16
|
242 >::type>
|
Chris@16
|
243 : mpl::true_ {};
|
Chris@16
|
244
|
Chris@16
|
245 namespace detail
|
Chris@16
|
246 {
|
Chris@16
|
247 // By declaring a nested struct in your class/struct, you tell
|
Chris@16
|
248 // spirit that it is regarded as a variant type. The minimum
|
Chris@16
|
249 // required interface for such a variant is that it has constructors
|
Chris@16
|
250 // for various types supported by your variant and a typedef 'types'
|
Chris@16
|
251 // which is an mpl sequence of the contained types.
|
Chris@16
|
252 //
|
Chris@16
|
253 // This is an intrusive interface. For a non-intrusive interface,
|
Chris@16
|
254 // use the not_is_variant trait.
|
Chris@16
|
255 BOOST_MPL_HAS_XXX_TRAIT_DEF(adapted_variant_tag)
|
Chris@16
|
256 }
|
Chris@16
|
257
|
Chris@16
|
258 template <typename T, typename Domain, typename Enable/* = void*/>
|
Chris@16
|
259 struct not_is_variant
|
Chris@16
|
260 : mpl::not_<detail::has_adapted_variant_tag<T> >
|
Chris@16
|
261 {};
|
Chris@16
|
262
|
Chris@16
|
263 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Domain>
|
Chris@16
|
264 struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Domain>
|
Chris@16
|
265 : mpl::false_
|
Chris@16
|
266 {};
|
Chris@16
|
267
|
Chris@16
|
268 template <typename T, typename Domain>
|
Chris@16
|
269 struct not_is_variant<boost::optional<T>, Domain>
|
Chris@16
|
270 : not_is_variant<T, Domain>
|
Chris@16
|
271 {};
|
Chris@16
|
272
|
Chris@16
|
273 // we treat every type as if it where the variant (as this meta function is
|
Chris@16
|
274 // invoked for variant types only)
|
Chris@16
|
275 template <typename T>
|
Chris@16
|
276 struct variant_type
|
Chris@16
|
277 : mpl::identity<T>
|
Chris@16
|
278 {};
|
Chris@16
|
279
|
Chris@16
|
280 template <typename T>
|
Chris@16
|
281 struct variant_type<boost::optional<T> >
|
Chris@16
|
282 : variant_type<T>
|
Chris@16
|
283 {};
|
Chris@16
|
284
|
Chris@16
|
285 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
286 // The compute_compatible_component_variant
|
Chris@16
|
287 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
288 namespace detail
|
Chris@16
|
289 {
|
Chris@16
|
290 // A component is compatible to a given Attribute type if the
|
Chris@16
|
291 // Attribute is the same as the expected type of the component or if
|
Chris@16
|
292 // it is convertible to the expected type.
|
Chris@16
|
293 template <typename Expected, typename Attribute>
|
Chris@16
|
294 struct attribute_is_compatible
|
Chris@16
|
295 : is_convertible<Attribute, Expected>
|
Chris@16
|
296 {};
|
Chris@16
|
297
|
Chris@16
|
298 template <typename Expected, typename Attribute>
|
Chris@16
|
299 struct attribute_is_compatible<Expected, boost::optional<Attribute> >
|
Chris@16
|
300 : is_convertible<Attribute, Expected>
|
Chris@16
|
301 {};
|
Chris@16
|
302
|
Chris@16
|
303 template <typename Container>
|
Chris@16
|
304 struct is_hold_any_container
|
Chris@16
|
305 : traits::is_hold_any<typename traits::container_value<Container>::type>
|
Chris@16
|
306 {};
|
Chris@16
|
307 }
|
Chris@16
|
308
|
Chris@16
|
309 template <typename Attribute, typename Expected
|
Chris@16
|
310 , typename IsNotVariant = mpl::false_, typename Enable = void>
|
Chris@16
|
311 struct compute_compatible_component_variant
|
Chris@16
|
312 : mpl::or_<
|
Chris@16
|
313 traits::detail::attribute_is_compatible<Expected, Attribute>
|
Chris@16
|
314 , traits::is_hold_any<Expected>
|
Chris@16
|
315 , mpl::eval_if<
|
Chris@16
|
316 is_container<Expected>
|
Chris@16
|
317 , traits::detail::is_hold_any_container<Expected>
|
Chris@16
|
318 , mpl::false_> >
|
Chris@16
|
319 {};
|
Chris@16
|
320
|
Chris@16
|
321 namespace detail
|
Chris@16
|
322 {
|
Chris@16
|
323 BOOST_MPL_HAS_XXX_TRAIT_DEF(types)
|
Chris@16
|
324 }
|
Chris@16
|
325
|
Chris@16
|
326 template <typename Variant, typename Expected>
|
Chris@16
|
327 struct compute_compatible_component_variant<Variant, Expected, mpl::false_
|
Chris@16
|
328 , typename enable_if<detail::has_types<Variant> >::type>
|
Chris@16
|
329 {
|
Chris@16
|
330 typedef typename traits::variant_type<Variant>::type variant_type;
|
Chris@16
|
331 typedef typename variant_type::types types;
|
Chris@16
|
332 typedef typename mpl::end<types>::type end;
|
Chris@16
|
333
|
Chris@16
|
334 typedef typename
|
Chris@16
|
335 mpl::find_if<types, is_same<Expected, mpl::_1> >::type
|
Chris@16
|
336 iter;
|
Chris@16
|
337
|
Chris@16
|
338 typedef typename mpl::distance<
|
Chris@16
|
339 typename mpl::begin<types>::type, iter
|
Chris@16
|
340 >::type distance;
|
Chris@16
|
341
|
Chris@16
|
342 // true_ if the attribute matches one of the types in the variant
|
Chris@16
|
343 typedef typename mpl::not_<is_same<iter, end> >::type type;
|
Chris@16
|
344 enum { value = type::value };
|
Chris@16
|
345
|
Chris@16
|
346 // return the type in the variant the attribute is compatible with
|
Chris@16
|
347 typedef typename
|
Chris@16
|
348 mpl::eval_if<type, mpl::deref<iter>, mpl::identity<unused_type> >::type
|
Chris@16
|
349 compatible_type;
|
Chris@16
|
350
|
Chris@16
|
351 // return whether the given type is compatible with the Expected type
|
Chris@16
|
352 static bool is_compatible(int which)
|
Chris@16
|
353 {
|
Chris@16
|
354 return which == distance::value;
|
Chris@16
|
355 }
|
Chris@16
|
356 };
|
Chris@16
|
357
|
Chris@16
|
358 template <typename Expected, typename Attribute, typename Domain>
|
Chris@16
|
359 struct compute_compatible_component
|
Chris@16
|
360 : compute_compatible_component_variant<Attribute, Expected
|
Chris@16
|
361 , typename spirit::traits::not_is_variant<Attribute, Domain>::type> {};
|
Chris@16
|
362
|
Chris@16
|
363 template <typename Expected, typename Domain>
|
Chris@16
|
364 struct compute_compatible_component<Expected, unused_type, Domain>
|
Chris@16
|
365 : mpl::false_ {};
|
Chris@16
|
366
|
Chris@16
|
367 template <typename Attribute, typename Domain>
|
Chris@16
|
368 struct compute_compatible_component<unused_type, Attribute, Domain>
|
Chris@16
|
369 : mpl::false_ {};
|
Chris@16
|
370
|
Chris@16
|
371 template <typename Domain>
|
Chris@16
|
372 struct compute_compatible_component<unused_type, unused_type, Domain>
|
Chris@16
|
373 : mpl::false_ {};
|
Chris@16
|
374
|
Chris@16
|
375 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
376 // return the type currently stored in the given variant
|
Chris@16
|
377 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
Chris@16
|
378 struct variant_which<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
Chris@16
|
379 {
|
Chris@16
|
380 static int call(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& v)
|
Chris@16
|
381 {
|
Chris@16
|
382 return v.which();
|
Chris@16
|
383 }
|
Chris@16
|
384 };
|
Chris@16
|
385
|
Chris@16
|
386 template <typename T>
|
Chris@16
|
387 int which(T const& v)
|
Chris@16
|
388 {
|
Chris@16
|
389 return variant_which<T>::call(v);
|
Chris@16
|
390 }
|
Chris@16
|
391
|
Chris@16
|
392 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
393 template <typename T, typename Domain, typename Enable/* = void*/>
|
Chris@16
|
394 struct not_is_optional
|
Chris@16
|
395 : mpl::true_
|
Chris@16
|
396 {};
|
Chris@16
|
397
|
Chris@16
|
398 template <typename T, typename Domain>
|
Chris@16
|
399 struct not_is_optional<boost::optional<T>, Domain>
|
Chris@16
|
400 : mpl::false_
|
Chris@16
|
401 {};
|
Chris@16
|
402
|
Chris@16
|
403 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
404 // attribute_of
|
Chris@16
|
405 //
|
Chris@16
|
406 // Get the component's attribute
|
Chris@16
|
407 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
408 template <typename Component
|
Chris@16
|
409 , typename Context = unused_type, typename Iterator = unused_type>
|
Chris@16
|
410 struct attribute_of
|
Chris@16
|
411 {
|
Chris@16
|
412 typedef typename Component::template
|
Chris@16
|
413 attribute<Context, Iterator>::type type;
|
Chris@16
|
414 };
|
Chris@16
|
415
|
Chris@16
|
416 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
417 // attribute_not_unused
|
Chris@16
|
418 //
|
Chris@16
|
419 // An mpl meta-function class that determines whether a component's
|
Chris@16
|
420 // attribute is not unused.
|
Chris@16
|
421 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
422 template <typename Context, typename Iterator = unused_type>
|
Chris@16
|
423 struct attribute_not_unused
|
Chris@16
|
424 {
|
Chris@16
|
425 template <typename Component>
|
Chris@16
|
426 struct apply
|
Chris@16
|
427 : not_is_unused<typename
|
Chris@16
|
428 attribute_of<Component, Context, Iterator>::type>
|
Chris@16
|
429 {};
|
Chris@16
|
430 };
|
Chris@16
|
431
|
Chris@16
|
432 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
433 // Retrieve the attribute type to use from the given type
|
Chris@16
|
434 //
|
Chris@16
|
435 // This is needed to extract the correct attribute type from proxy classes
|
Chris@16
|
436 // as utilized in FUSION_ADAPT_ADT et. al.
|
Chris@16
|
437 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
438 template <typename Attribute, typename Enable/* = void*/>
|
Chris@16
|
439 struct attribute_type : mpl::identity<Attribute> {};
|
Chris@16
|
440
|
Chris@16
|
441 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
442 // Retrieve the size of a fusion sequence (compile time)
|
Chris@16
|
443 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
444 template <typename T>
|
Chris@16
|
445 struct sequence_size
|
Chris@16
|
446 : fusion::result_of::size<T>
|
Chris@16
|
447 {};
|
Chris@16
|
448
|
Chris@16
|
449 template <>
|
Chris@16
|
450 struct sequence_size<unused_type>
|
Chris@16
|
451 : mpl::int_<0>
|
Chris@16
|
452 {};
|
Chris@16
|
453
|
Chris@16
|
454 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
455 // Retrieve the size of an attribute (runtime)
|
Chris@16
|
456 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
457 namespace detail
|
Chris@16
|
458 {
|
Chris@16
|
459 template <typename Attribute, typename Enable = void>
|
Chris@16
|
460 struct attribute_size_impl
|
Chris@16
|
461 {
|
Chris@16
|
462 typedef std::size_t type;
|
Chris@16
|
463
|
Chris@16
|
464 static type call(Attribute const&)
|
Chris@16
|
465 {
|
Chris@16
|
466 return 1;
|
Chris@16
|
467 }
|
Chris@16
|
468 };
|
Chris@16
|
469
|
Chris@16
|
470 template <typename Attribute>
|
Chris@16
|
471 struct attribute_size_impl<Attribute
|
Chris@16
|
472 , typename enable_if<
|
Chris@16
|
473 mpl::and_<
|
Chris@16
|
474 fusion::traits::is_sequence<Attribute>
|
Chris@16
|
475 , mpl::not_<traits::is_container<Attribute> >
|
Chris@16
|
476 >
|
Chris@16
|
477 >::type>
|
Chris@16
|
478 {
|
Chris@16
|
479 typedef typename fusion::result_of::size<Attribute>::value_type type;
|
Chris@16
|
480
|
Chris@16
|
481 static type call(Attribute const& attr)
|
Chris@16
|
482 {
|
Chris@16
|
483 return fusion::size(attr);
|
Chris@16
|
484 }
|
Chris@16
|
485 };
|
Chris@16
|
486
|
Chris@16
|
487 template <typename Attribute>
|
Chris@16
|
488 struct attribute_size_impl<Attribute
|
Chris@16
|
489 , typename enable_if<
|
Chris@16
|
490 mpl::and_<
|
Chris@16
|
491 traits::is_container<Attribute>
|
Chris@16
|
492 , mpl::not_<traits::is_iterator_range<Attribute> >
|
Chris@16
|
493 >
|
Chris@16
|
494 >::type>
|
Chris@16
|
495 {
|
Chris@16
|
496 typedef typename Attribute::size_type type;
|
Chris@16
|
497
|
Chris@16
|
498 static type call(Attribute const& attr)
|
Chris@16
|
499 {
|
Chris@16
|
500 return attr.size();
|
Chris@16
|
501 }
|
Chris@16
|
502 };
|
Chris@16
|
503 }
|
Chris@16
|
504
|
Chris@16
|
505 template <typename Attribute, typename Enable/* = void*/>
|
Chris@16
|
506 struct attribute_size
|
Chris@16
|
507 : detail::attribute_size_impl<Attribute>
|
Chris@16
|
508 {};
|
Chris@16
|
509
|
Chris@16
|
510 template <typename Attribute>
|
Chris@16
|
511 struct attribute_size<optional<Attribute> >
|
Chris@16
|
512 {
|
Chris@16
|
513 typedef typename attribute_size<Attribute>::type type;
|
Chris@16
|
514
|
Chris@16
|
515 static type call(optional<Attribute> const& val)
|
Chris@16
|
516 {
|
Chris@16
|
517 if (!val)
|
Chris@16
|
518 return 0;
|
Chris@16
|
519 return val.get();
|
Chris@16
|
520 }
|
Chris@16
|
521 };
|
Chris@16
|
522
|
Chris@16
|
523 namespace detail
|
Chris@16
|
524 {
|
Chris@16
|
525 struct attribute_size_visitor : static_visitor<std::size_t>
|
Chris@16
|
526 {
|
Chris@16
|
527 template <typename T>
|
Chris@16
|
528 std::size_t operator()(T const& val) const
|
Chris@16
|
529 {
|
Chris@16
|
530 return spirit::traits::size(val);
|
Chris@16
|
531 }
|
Chris@16
|
532 };
|
Chris@16
|
533 }
|
Chris@16
|
534
|
Chris@16
|
535 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
Chris@16
|
536 struct attribute_size<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
Chris@16
|
537 {
|
Chris@16
|
538 typedef std::size_t type;
|
Chris@16
|
539
|
Chris@16
|
540 static type call(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& val)
|
Chris@16
|
541 {
|
Chris@16
|
542 return apply_visitor(detail::attribute_size_visitor(), val);
|
Chris@16
|
543 }
|
Chris@16
|
544 };
|
Chris@16
|
545
|
Chris@16
|
546 template <typename Iterator>
|
Chris@16
|
547 struct attribute_size<iterator_range<Iterator> >
|
Chris@16
|
548 {
|
Chris@16
|
549 typedef typename boost::detail::iterator_traits<Iterator>::
|
Chris@16
|
550 difference_type type;
|
Chris@16
|
551
|
Chris@16
|
552 static type call(iterator_range<Iterator> const& r)
|
Chris@16
|
553 {
|
Chris@16
|
554 return boost::detail::distance(r.begin(), r.end());
|
Chris@16
|
555 }
|
Chris@16
|
556 };
|
Chris@16
|
557
|
Chris@16
|
558 template <>
|
Chris@16
|
559 struct attribute_size<unused_type>
|
Chris@16
|
560 {
|
Chris@16
|
561 typedef std::size_t type;
|
Chris@16
|
562
|
Chris@16
|
563 static type call(unused_type)
|
Chris@16
|
564 {
|
Chris@16
|
565 return 0;
|
Chris@16
|
566 }
|
Chris@16
|
567 };
|
Chris@16
|
568
|
Chris@16
|
569 template <typename Attribute>
|
Chris@16
|
570 typename attribute_size<Attribute>::type
|
Chris@16
|
571 size (Attribute const& attr)
|
Chris@16
|
572 {
|
Chris@16
|
573 return attribute_size<Attribute>::call(attr);
|
Chris@16
|
574 }
|
Chris@16
|
575
|
Chris@16
|
576 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
577 // pass_attribute
|
Chris@16
|
578 //
|
Chris@16
|
579 // Determines how we pass attributes to semantic actions. This
|
Chris@16
|
580 // may be specialized. By default, all attributes are wrapped in
|
Chris@16
|
581 // a fusion sequence, because the attribute has to be treated as being
|
Chris@16
|
582 // a single value in any case (even if it actually already is a fusion
|
Chris@16
|
583 // sequence in its own).
|
Chris@16
|
584 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
585 template <typename Component, typename Attribute, typename Enable/* = void*/>
|
Chris@16
|
586 struct pass_attribute
|
Chris@16
|
587 {
|
Chris@16
|
588 typedef fusion::vector1<Attribute&> type;
|
Chris@16
|
589 };
|
Chris@16
|
590
|
Chris@16
|
591 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
592 // Subclass a pass_attribute specialization from this to wrap
|
Chris@16
|
593 // the attribute in a tuple only IFF it is not already a fusion tuple.
|
Chris@16
|
594 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
595 template <typename Attribute, typename Force = mpl::false_>
|
Chris@16
|
596 struct wrap_if_not_tuple
|
Chris@16
|
597 : mpl::if_<
|
Chris@16
|
598 fusion::traits::is_sequence<Attribute>
|
Chris@16
|
599 , Attribute&, fusion::vector1<Attribute&> >
|
Chris@16
|
600 {};
|
Chris@16
|
601
|
Chris@16
|
602 template <typename Attribute>
|
Chris@16
|
603 struct wrap_if_not_tuple<Attribute, mpl::true_>
|
Chris@16
|
604 {
|
Chris@16
|
605 typedef fusion::vector1<Attribute&> type;
|
Chris@16
|
606 };
|
Chris@16
|
607
|
Chris@16
|
608 template <>
|
Chris@16
|
609 struct wrap_if_not_tuple<unused_type, mpl::false_>
|
Chris@16
|
610 {
|
Chris@16
|
611 typedef unused_type type;
|
Chris@16
|
612 };
|
Chris@16
|
613
|
Chris@16
|
614 template <>
|
Chris@16
|
615 struct wrap_if_not_tuple<unused_type const, mpl::false_>
|
Chris@16
|
616 {
|
Chris@16
|
617 typedef unused_type type;
|
Chris@16
|
618 };
|
Chris@16
|
619
|
Chris@16
|
620 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
621 // build_optional
|
Chris@16
|
622 //
|
Chris@16
|
623 // Build a boost::optional from T. Return unused_type if T is unused_type.
|
Chris@16
|
624 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
625 template <typename T>
|
Chris@16
|
626 struct build_optional
|
Chris@16
|
627 {
|
Chris@16
|
628 typedef boost::optional<T> type;
|
Chris@16
|
629 };
|
Chris@16
|
630
|
Chris@16
|
631 template <typename T>
|
Chris@16
|
632 struct build_optional<boost::optional<T> >
|
Chris@16
|
633 {
|
Chris@16
|
634 typedef boost::optional<T> type;
|
Chris@16
|
635 };
|
Chris@16
|
636
|
Chris@16
|
637 template <>
|
Chris@16
|
638 struct build_optional<unused_type>
|
Chris@16
|
639 {
|
Chris@16
|
640 typedef unused_type type;
|
Chris@16
|
641 };
|
Chris@16
|
642
|
Chris@16
|
643 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
644 // build_std_vector
|
Chris@16
|
645 //
|
Chris@16
|
646 // Build a std::vector from T. Return unused_type if T is unused_type.
|
Chris@16
|
647 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
648 template <typename T>
|
Chris@16
|
649 struct build_std_vector
|
Chris@16
|
650 {
|
Chris@16
|
651 typedef std::vector<T> type;
|
Chris@16
|
652 };
|
Chris@16
|
653
|
Chris@16
|
654 template <>
|
Chris@16
|
655 struct build_std_vector<unused_type>
|
Chris@16
|
656 {
|
Chris@16
|
657 typedef unused_type type;
|
Chris@16
|
658 };
|
Chris@16
|
659
|
Chris@16
|
660 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
661 // filter_unused_attributes
|
Chris@16
|
662 //
|
Chris@16
|
663 // Remove unused_types from a sequence
|
Chris@16
|
664 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
665
|
Chris@16
|
666 // Compute the list of all *used* attributes of sub-components
|
Chris@16
|
667 // (filter all unused attributes from the list)
|
Chris@16
|
668 template <typename Sequence>
|
Chris@16
|
669 struct filter_unused_attributes
|
Chris@16
|
670 : fusion::result_of::filter_if<Sequence, not_is_unused<mpl::_> >
|
Chris@16
|
671 {};
|
Chris@16
|
672
|
Chris@16
|
673 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
674 // sequence_attribute_transform
|
Chris@16
|
675 //
|
Chris@16
|
676 // This transform is invoked for every attribute in a sequence allowing
|
Chris@16
|
677 // to modify the attribute type exposed by a component to the enclosing
|
Chris@16
|
678 // sequence component. By default no transformation is performed.
|
Chris@16
|
679 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
680 template <typename Attribute, typename Domain>
|
Chris@16
|
681 struct sequence_attribute_transform
|
Chris@16
|
682 : mpl::identity<Attribute>
|
Chris@16
|
683 {};
|
Chris@16
|
684
|
Chris@16
|
685 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
686 // permutation_attribute_transform
|
Chris@16
|
687 //
|
Chris@16
|
688 // This transform is invoked for every attribute in a sequence allowing
|
Chris@16
|
689 // to modify the attribute type exposed by a component to the enclosing
|
Chris@16
|
690 // permutation component. By default a build_optional transformation is
|
Chris@16
|
691 // performed.
|
Chris@16
|
692 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
693 template <typename Attribute, typename Domain>
|
Chris@16
|
694 struct permutation_attribute_transform
|
Chris@16
|
695 : traits::build_optional<Attribute>
|
Chris@16
|
696 {};
|
Chris@16
|
697
|
Chris@16
|
698 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
699 // sequential_or_attribute_transform
|
Chris@16
|
700 //
|
Chris@16
|
701 // This transform is invoked for every attribute in a sequential_or allowing
|
Chris@16
|
702 // to modify the attribute type exposed by a component to the enclosing
|
Chris@16
|
703 // sequential_or component. By default a build_optional transformation is
|
Chris@16
|
704 // performed.
|
Chris@16
|
705 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
706 template <typename Attribute, typename Domain>
|
Chris@16
|
707 struct sequential_or_attribute_transform
|
Chris@16
|
708 : traits::build_optional<Attribute>
|
Chris@16
|
709 {};
|
Chris@16
|
710
|
Chris@16
|
711 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
712 // build_fusion_vector
|
Chris@16
|
713 //
|
Chris@16
|
714 // Build a fusion vector from a fusion sequence. All unused attributes
|
Chris@16
|
715 // are filtered out. If the result is empty after the removal of unused
|
Chris@16
|
716 // types, return unused_type. If the input sequence is an unused_type,
|
Chris@16
|
717 // also return unused_type.
|
Chris@16
|
718 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
719 template <typename Sequence>
|
Chris@16
|
720 struct build_fusion_vector
|
Chris@16
|
721 {
|
Chris@16
|
722 // Remove all unused attributes
|
Chris@16
|
723 typedef typename
|
Chris@16
|
724 filter_unused_attributes<Sequence>::type
|
Chris@16
|
725 filtered_attributes;
|
Chris@16
|
726
|
Chris@16
|
727 // Build a fusion vector from a fusion sequence (Sequence),
|
Chris@16
|
728 // But *only if* the sequence is not empty. i.e. if the
|
Chris@16
|
729 // sequence is empty, our result will be unused_type.
|
Chris@16
|
730
|
Chris@16
|
731 typedef typename
|
Chris@16
|
732 mpl::eval_if<
|
Chris@16
|
733 fusion::result_of::empty<filtered_attributes>
|
Chris@16
|
734 , mpl::identity<unused_type>
|
Chris@16
|
735 , fusion::result_of::as_vector<filtered_attributes>
|
Chris@16
|
736 >::type
|
Chris@16
|
737 type;
|
Chris@16
|
738 };
|
Chris@16
|
739
|
Chris@16
|
740 template <>
|
Chris@16
|
741 struct build_fusion_vector<unused_type>
|
Chris@16
|
742 {
|
Chris@16
|
743 typedef unused_type type;
|
Chris@16
|
744 };
|
Chris@16
|
745
|
Chris@16
|
746 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
747 // build_attribute_sequence
|
Chris@16
|
748 //
|
Chris@16
|
749 // Build a fusion sequence attribute sequence from a sequence of
|
Chris@16
|
750 // components. Transform<T>::type is called on each element.
|
Chris@16
|
751 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
752 template <typename Sequence, typename Context
|
Chris@16
|
753 , template <typename T, typename D> class Transform
|
Chris@16
|
754 , typename Iterator = unused_type, typename Domain = unused_type>
|
Chris@16
|
755 struct build_attribute_sequence
|
Chris@16
|
756 {
|
Chris@16
|
757 struct element_attribute
|
Chris@16
|
758 {
|
Chris@16
|
759 template <typename T>
|
Chris@16
|
760 struct result;
|
Chris@16
|
761
|
Chris@16
|
762 template <typename F, typename Element>
|
Chris@16
|
763 struct result<F(Element)>
|
Chris@16
|
764 {
|
Chris@16
|
765 typedef typename
|
Chris@16
|
766 Transform<
|
Chris@16
|
767 typename attribute_of<Element, Context, Iterator>::type
|
Chris@16
|
768 , Domain
|
Chris@16
|
769 >::type
|
Chris@16
|
770 type;
|
Chris@16
|
771 };
|
Chris@16
|
772
|
Chris@16
|
773 // never called, but needed for decltype-based result_of (C++0x)
|
Chris@16
|
774 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
775 template <typename Element>
|
Chris@16
|
776 typename result<element_attribute(Element)>::type
|
Chris@16
|
777 operator()(Element&&) const;
|
Chris@16
|
778 #endif
|
Chris@16
|
779 };
|
Chris@16
|
780
|
Chris@16
|
781 // Compute the list of attributes of all sub-components
|
Chris@16
|
782 typedef typename
|
Chris@16
|
783 fusion::result_of::transform<Sequence, element_attribute>::type
|
Chris@16
|
784 type;
|
Chris@16
|
785 };
|
Chris@16
|
786
|
Chris@16
|
787 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
788 // has_no_unused
|
Chris@16
|
789 //
|
Chris@16
|
790 // Test if there are no unused attributes in Sequence
|
Chris@16
|
791 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
792 template <typename Sequence>
|
Chris@16
|
793 struct has_no_unused
|
Chris@16
|
794 : is_same<
|
Chris@16
|
795 typename mpl::find_if<Sequence, is_same<mpl::_, unused_type> >::type
|
Chris@16
|
796 , typename mpl::end<Sequence>::type>
|
Chris@16
|
797 {};
|
Chris@16
|
798
|
Chris@16
|
799 namespace detail
|
Chris@16
|
800 {
|
Chris@16
|
801 template <typename Sequence, bool no_unused
|
Chris@16
|
802 , int size = mpl::size<Sequence>::value>
|
Chris@16
|
803 struct build_collapsed_variant;
|
Chris@16
|
804
|
Chris@16
|
805 // N element case, no unused
|
Chris@16
|
806 template <typename Sequence, int size>
|
Chris@16
|
807 struct build_collapsed_variant<Sequence, true, size>
|
Chris@16
|
808 : spirit::detail::as_variant<Sequence> {};
|
Chris@16
|
809
|
Chris@16
|
810 // N element case with unused
|
Chris@16
|
811 template <typename Sequence, int size>
|
Chris@16
|
812 struct build_collapsed_variant<Sequence, false, size>
|
Chris@16
|
813 {
|
Chris@16
|
814 typedef boost::optional<
|
Chris@16
|
815 typename spirit::detail::as_variant<
|
Chris@16
|
816 typename fusion::result_of::pop_front<Sequence>::type
|
Chris@16
|
817 >::type
|
Chris@16
|
818 > type;
|
Chris@16
|
819 };
|
Chris@16
|
820
|
Chris@16
|
821 // 1 element case, no unused
|
Chris@16
|
822 template <typename Sequence>
|
Chris@16
|
823 struct build_collapsed_variant<Sequence, true, 1>
|
Chris@16
|
824 : mpl::front<Sequence> {};
|
Chris@16
|
825
|
Chris@16
|
826 // 1 element case, with unused
|
Chris@16
|
827 template <typename Sequence>
|
Chris@16
|
828 struct build_collapsed_variant<Sequence, false, 1>
|
Chris@16
|
829 : mpl::front<Sequence> {};
|
Chris@16
|
830
|
Chris@16
|
831 // 2 element case, no unused
|
Chris@16
|
832 template <typename Sequence>
|
Chris@16
|
833 struct build_collapsed_variant<Sequence, true, 2>
|
Chris@16
|
834 : spirit::detail::as_variant<Sequence> {};
|
Chris@16
|
835
|
Chris@16
|
836 // 2 element case, with unused
|
Chris@16
|
837 template <typename Sequence>
|
Chris@16
|
838 struct build_collapsed_variant<Sequence, false, 2>
|
Chris@16
|
839 {
|
Chris@16
|
840 typedef boost::optional<
|
Chris@16
|
841 typename mpl::deref<
|
Chris@16
|
842 typename mpl::next<
|
Chris@16
|
843 typename mpl::begin<Sequence>::type
|
Chris@16
|
844 >::type
|
Chris@16
|
845 >::type
|
Chris@16
|
846 >
|
Chris@16
|
847 type;
|
Chris@16
|
848 };
|
Chris@16
|
849 }
|
Chris@16
|
850
|
Chris@16
|
851 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
852 // alternative_attribute_transform
|
Chris@16
|
853 //
|
Chris@16
|
854 // This transform is invoked for every attribute in an alternative allowing
|
Chris@16
|
855 // to modify the attribute type exposed by a component to the enclosing
|
Chris@16
|
856 // alternative component. By default no transformation is performed.
|
Chris@16
|
857 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
858 template <typename Attribute, typename Domain>
|
Chris@16
|
859 struct alternative_attribute_transform
|
Chris@16
|
860 : mpl::identity<Attribute>
|
Chris@16
|
861 {};
|
Chris@16
|
862
|
Chris@16
|
863 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
864 // build_variant
|
Chris@16
|
865 //
|
Chris@16
|
866 // Build a boost::variant from a fusion sequence. build_variant makes sure
|
Chris@16
|
867 // that 1) all attributes in the variant are unique 2) puts the unused
|
Chris@16
|
868 // attribute, if there is any, to the front and 3) collapses single element
|
Chris@16
|
869 // variants, variant<T> to T.
|
Chris@16
|
870 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
871 template <typename Sequence>
|
Chris@16
|
872 struct build_variant
|
Chris@16
|
873 {
|
Chris@16
|
874 // Remove all unused attributes.
|
Chris@16
|
875 typedef typename
|
Chris@16
|
876 filter_unused_attributes<Sequence>::type
|
Chris@16
|
877 filtered_attributes;
|
Chris@16
|
878
|
Chris@16
|
879 typedef has_no_unused<Sequence> no_unused;
|
Chris@16
|
880
|
Chris@16
|
881 // If the original attribute list does not contain any unused
|
Chris@16
|
882 // attributes, it is used, otherwise a single unused_type is
|
Chris@16
|
883 // pushed to the front of the list. This is to make sure that if
|
Chris@16
|
884 // there is an unused_type in the list, it is the first one.
|
Chris@16
|
885 typedef typename
|
Chris@16
|
886 mpl::eval_if<
|
Chris@16
|
887 no_unused,
|
Chris@16
|
888 mpl::identity<Sequence>,
|
Chris@16
|
889 fusion::result_of::push_front<filtered_attributes, unused_type>
|
Chris@16
|
890 >::type
|
Chris@16
|
891 attribute_sequence;
|
Chris@16
|
892
|
Chris@16
|
893 // Make sure each of the types occur only once in the type list
|
Chris@16
|
894 typedef typename
|
Chris@16
|
895 mpl::fold<
|
Chris@16
|
896 attribute_sequence, mpl::vector<>,
|
Chris@16
|
897 mpl::if_<
|
Chris@16
|
898 mpl::contains<mpl::_1, mpl::_2>,
|
Chris@16
|
899 mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
|
Chris@16
|
900 >
|
Chris@16
|
901 >::type
|
Chris@16
|
902 no_duplicates;
|
Chris@16
|
903
|
Chris@16
|
904 // If there is only one type in the list of types we strip off the
|
Chris@16
|
905 // variant. IOTW, collapse single element variants, variant<T> to T.
|
Chris@16
|
906 // Take note that this also collapses variant<unused_type, T> to T.
|
Chris@16
|
907 typedef typename
|
Chris@16
|
908 traits::detail::build_collapsed_variant<
|
Chris@16
|
909 no_duplicates, no_unused::value>::type
|
Chris@16
|
910 type;
|
Chris@16
|
911 };
|
Chris@16
|
912
|
Chris@16
|
913 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
914 // transform_attribute
|
Chris@16
|
915 //
|
Chris@16
|
916 // Sometimes the user needs to transform the attribute types for certain
|
Chris@16
|
917 // attributes. This template can be used as a customization point, where
|
Chris@16
|
918 // the user is able specify specific transformation rules for any attribute
|
Chris@16
|
919 // type.
|
Chris@16
|
920 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
921 template <typename Exposed, typename Transformed, typename Domain
|
Chris@16
|
922 , typename Enable/* = void*/>
|
Chris@16
|
923 struct transform_attribute;
|
Chris@16
|
924
|
Chris@16
|
925 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
926 template <typename Domain, typename Transformed, typename Exposed>
|
Chris@16
|
927 typename spirit::result_of::pre_transform<Exposed, Transformed, Domain>::type
|
Chris@16
|
928 pre_transform(Exposed& attr BOOST_PROTO_DISABLE_IF_IS_CONST(Exposed))
|
Chris@16
|
929 {
|
Chris@16
|
930 return transform_attribute<Exposed, Transformed, Domain>::pre(attr);
|
Chris@16
|
931 }
|
Chris@16
|
932
|
Chris@16
|
933 template <typename Domain, typename Transformed, typename Exposed>
|
Chris@16
|
934 typename spirit::result_of::pre_transform<Exposed const, Transformed, Domain>::type
|
Chris@16
|
935 pre_transform(Exposed const& attr)
|
Chris@16
|
936 {
|
Chris@16
|
937 return transform_attribute<Exposed const, Transformed, Domain>::pre(attr);
|
Chris@16
|
938 }
|
Chris@16
|
939
|
Chris@16
|
940 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
941 // make_attribute
|
Chris@16
|
942 //
|
Chris@16
|
943 // All parsers and generators have specific attribute types.
|
Chris@16
|
944 // Spirit parsers and generators are passed an attribute; these are either
|
Chris@16
|
945 // references to the expected type, or an unused_type -- to flag that we do
|
Chris@16
|
946 // not care about the attribute. For semantic actions, however, we need to
|
Chris@16
|
947 // have a real value to pass to the semantic action. If the client did not
|
Chris@16
|
948 // provide one, we will have to synthesize the value. This class takes care
|
Chris@16
|
949 // of that. *Note that this behavior has changed. From Boost 1.47, semantic
|
Chris@16
|
950 // actions always take in the passed attribute as-is if the PP constant:
|
Chris@16
|
951 // BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT is defined.
|
Chris@16
|
952 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
953 template <typename Attribute, typename ActualAttribute>
|
Chris@16
|
954 struct make_attribute
|
Chris@16
|
955 {
|
Chris@16
|
956 typedef typename remove_const<Attribute>::type attribute_type;
|
Chris@16
|
957 typedef typename
|
Chris@16
|
958 mpl::if_<
|
Chris@16
|
959 is_same<typename remove_const<ActualAttribute>::type, unused_type>
|
Chris@16
|
960 , attribute_type
|
Chris@16
|
961 , ActualAttribute&>::type
|
Chris@16
|
962 type;
|
Chris@16
|
963
|
Chris@16
|
964 typedef typename
|
Chris@16
|
965 mpl::if_<
|
Chris@16
|
966 is_same<typename remove_const<ActualAttribute>::type, unused_type>
|
Chris@16
|
967 , attribute_type
|
Chris@16
|
968 , ActualAttribute>::type
|
Chris@16
|
969 value_type;
|
Chris@16
|
970
|
Chris@16
|
971 static Attribute call(unused_type)
|
Chris@16
|
972 {
|
Chris@16
|
973 // synthesize the attribute/parameter
|
Chris@16
|
974 return boost::get(value_initialized<attribute_type>());
|
Chris@16
|
975 }
|
Chris@16
|
976
|
Chris@16
|
977 template <typename T>
|
Chris@16
|
978 static T& call(T& value)
|
Chris@16
|
979 {
|
Chris@16
|
980 return value; // just pass the one provided
|
Chris@16
|
981 }
|
Chris@16
|
982 };
|
Chris@16
|
983
|
Chris@16
|
984 template <typename Attribute, typename ActualAttribute>
|
Chris@16
|
985 struct make_attribute<Attribute&, ActualAttribute>
|
Chris@16
|
986 : make_attribute<Attribute, ActualAttribute>
|
Chris@16
|
987 {};
|
Chris@16
|
988
|
Chris@16
|
989 template <typename Attribute, typename ActualAttribute>
|
Chris@16
|
990 struct make_attribute<Attribute const&, ActualAttribute>
|
Chris@16
|
991 : make_attribute<Attribute const, ActualAttribute>
|
Chris@16
|
992 {};
|
Chris@16
|
993
|
Chris@16
|
994 template <typename ActualAttribute>
|
Chris@16
|
995 struct make_attribute<unused_type, ActualAttribute>
|
Chris@16
|
996 {
|
Chris@16
|
997 typedef unused_type type;
|
Chris@16
|
998 typedef unused_type value_type;
|
Chris@16
|
999 static unused_type call(unused_type)
|
Chris@16
|
1000 {
|
Chris@16
|
1001 return unused;
|
Chris@16
|
1002 }
|
Chris@16
|
1003 };
|
Chris@16
|
1004
|
Chris@16
|
1005 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1006 // swap_impl
|
Chris@16
|
1007 //
|
Chris@16
|
1008 // Swap (with proper handling of unused_types)
|
Chris@16
|
1009 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1010 template <typename A, typename B>
|
Chris@16
|
1011 void swap_impl(A& a, B& b)
|
Chris@16
|
1012 {
|
Chris@16
|
1013 A temp = a;
|
Chris@16
|
1014 a = b;
|
Chris@16
|
1015 b = temp;
|
Chris@16
|
1016 }
|
Chris@16
|
1017
|
Chris@16
|
1018 template <typename T>
|
Chris@16
|
1019 void swap_impl(T& a, T& b)
|
Chris@16
|
1020 {
|
Chris@16
|
1021 using namespace std;
|
Chris@16
|
1022 swap(a, b);
|
Chris@16
|
1023 }
|
Chris@16
|
1024
|
Chris@16
|
1025 template <typename A>
|
Chris@16
|
1026 void swap_impl(A&, unused_type)
|
Chris@16
|
1027 {
|
Chris@16
|
1028 }
|
Chris@16
|
1029
|
Chris@16
|
1030 template <typename A>
|
Chris@16
|
1031 void swap_impl(unused_type, A&)
|
Chris@16
|
1032 {
|
Chris@16
|
1033 }
|
Chris@16
|
1034
|
Chris@16
|
1035 inline void swap_impl(unused_type, unused_type)
|
Chris@16
|
1036 {
|
Chris@16
|
1037 }
|
Chris@16
|
1038
|
Chris@16
|
1039 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1040 // Strips single element fusion vectors into its 'naked'
|
Chris@16
|
1041 // form: vector<T> --> T
|
Chris@16
|
1042 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1043 template <typename T>
|
Chris@16
|
1044 struct strip_single_element_vector
|
Chris@16
|
1045 {
|
Chris@16
|
1046 typedef T type;
|
Chris@16
|
1047 };
|
Chris@16
|
1048
|
Chris@16
|
1049 template <typename T>
|
Chris@16
|
1050 struct strip_single_element_vector<fusion::vector1<T> >
|
Chris@16
|
1051 {
|
Chris@16
|
1052 typedef T type;
|
Chris@16
|
1053 };
|
Chris@16
|
1054
|
Chris@16
|
1055 template <typename T>
|
Chris@16
|
1056 struct strip_single_element_vector<fusion::vector<T> >
|
Chris@16
|
1057 {
|
Chris@16
|
1058 typedef T type;
|
Chris@16
|
1059 };
|
Chris@16
|
1060
|
Chris@16
|
1061 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1062 // meta function to return whether the argument is a one element fusion
|
Chris@16
|
1063 // sequence
|
Chris@16
|
1064 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1065 template <typename T
|
Chris@16
|
1066 , bool IsFusionSeq = fusion::traits::is_sequence<T>::value
|
Chris@16
|
1067 , bool IsProtoExpr = proto::is_expr<T>::value>
|
Chris@16
|
1068 struct one_element_sequence
|
Chris@16
|
1069 : mpl::false_
|
Chris@16
|
1070 {};
|
Chris@16
|
1071
|
Chris@16
|
1072 template <typename T>
|
Chris@16
|
1073 struct one_element_sequence<T, true, false>
|
Chris@16
|
1074 : mpl::bool_<mpl::size<T>::value == 1>
|
Chris@16
|
1075 {};
|
Chris@16
|
1076
|
Chris@16
|
1077 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1078 // clear
|
Chris@16
|
1079 //
|
Chris@16
|
1080 // Clear data efficiently
|
Chris@16
|
1081 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1082 template <typename T>
|
Chris@16
|
1083 void clear(T& val);
|
Chris@16
|
1084
|
Chris@16
|
1085 namespace detail
|
Chris@16
|
1086 {
|
Chris@16
|
1087 // this is used by the variant and fusion sequence dispatch
|
Chris@16
|
1088 struct clear_visitor : static_visitor<>
|
Chris@16
|
1089 {
|
Chris@16
|
1090 template <typename T>
|
Chris@16
|
1091 void operator()(T& val) const
|
Chris@16
|
1092 {
|
Chris@16
|
1093 spirit::traits::clear(val);
|
Chris@16
|
1094 }
|
Chris@16
|
1095 };
|
Chris@16
|
1096
|
Chris@16
|
1097 // default
|
Chris@16
|
1098 template <typename T>
|
Chris@16
|
1099 void clear_impl2(T& val, mpl::false_)
|
Chris@16
|
1100 {
|
Chris@16
|
1101 val = T();
|
Chris@16
|
1102 }
|
Chris@16
|
1103
|
Chris@16
|
1104 // for fusion sequences
|
Chris@16
|
1105 template <typename T>
|
Chris@16
|
1106 void clear_impl2(T& val, mpl::true_)
|
Chris@16
|
1107 {
|
Chris@16
|
1108 fusion::for_each(val, clear_visitor());
|
Chris@16
|
1109 }
|
Chris@16
|
1110
|
Chris@16
|
1111 // dispatch default or fusion sequence
|
Chris@16
|
1112 template <typename T>
|
Chris@16
|
1113 void clear_impl(T& val, mpl::false_)
|
Chris@16
|
1114 {
|
Chris@16
|
1115 clear_impl2(val, fusion::traits::is_sequence<T>());
|
Chris@16
|
1116 }
|
Chris@16
|
1117
|
Chris@16
|
1118 // STL containers
|
Chris@16
|
1119 template <typename T>
|
Chris@16
|
1120 void clear_impl(T& val, mpl::true_)
|
Chris@16
|
1121 {
|
Chris@16
|
1122 val.clear();
|
Chris@16
|
1123 }
|
Chris@16
|
1124 }
|
Chris@16
|
1125
|
Chris@16
|
1126 template <typename T, typename Enable/* = void*/>
|
Chris@16
|
1127 struct clear_value
|
Chris@16
|
1128 {
|
Chris@16
|
1129 static void call(T& val)
|
Chris@16
|
1130 {
|
Chris@16
|
1131 detail::clear_impl(val, typename is_container<T>::type());
|
Chris@16
|
1132 }
|
Chris@16
|
1133 };
|
Chris@16
|
1134
|
Chris@16
|
1135 // optionals
|
Chris@16
|
1136 template <typename T>
|
Chris@16
|
1137 struct clear_value<boost::optional<T> >
|
Chris@16
|
1138 {
|
Chris@16
|
1139 static void call(boost::optional<T>& val)
|
Chris@16
|
1140 {
|
Chris@16
|
1141 if (val)
|
Chris@16
|
1142 val = none_t(); // leave optional uninitialized
|
Chris@16
|
1143 }
|
Chris@16
|
1144 };
|
Chris@16
|
1145
|
Chris@16
|
1146 // variants
|
Chris@16
|
1147 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
Chris@16
|
1148 struct clear_value<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
Chris@16
|
1149 {
|
Chris@16
|
1150 static void call(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& val)
|
Chris@16
|
1151 {
|
Chris@16
|
1152 apply_visitor(detail::clear_visitor(), val);
|
Chris@16
|
1153 }
|
Chris@16
|
1154 };
|
Chris@16
|
1155
|
Chris@16
|
1156 // iterator range
|
Chris@16
|
1157 template <typename T>
|
Chris@16
|
1158 struct clear_value<iterator_range<T> >
|
Chris@16
|
1159 {
|
Chris@16
|
1160 static void call(iterator_range<T>& val)
|
Chris@16
|
1161 {
|
Chris@16
|
1162 val = iterator_range<T>(val.end(), val.end());
|
Chris@16
|
1163 }
|
Chris@16
|
1164 };
|
Chris@16
|
1165
|
Chris@16
|
1166 // main dispatch
|
Chris@16
|
1167 template <typename T>
|
Chris@16
|
1168 void clear(T& val)
|
Chris@16
|
1169 {
|
Chris@16
|
1170 clear_value<T>::call(val);
|
Chris@16
|
1171 }
|
Chris@16
|
1172
|
Chris@16
|
1173 // for unused
|
Chris@16
|
1174 inline void clear(unused_type)
|
Chris@16
|
1175 {
|
Chris@16
|
1176 }
|
Chris@16
|
1177
|
Chris@16
|
1178 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1179 namespace detail
|
Chris@16
|
1180 {
|
Chris@16
|
1181 template <typename Out>
|
Chris@16
|
1182 struct print_fusion_sequence
|
Chris@16
|
1183 {
|
Chris@16
|
1184 print_fusion_sequence(Out& out_)
|
Chris@16
|
1185 : out(out_), is_first(true) {}
|
Chris@16
|
1186
|
Chris@16
|
1187 typedef void result_type;
|
Chris@16
|
1188
|
Chris@16
|
1189 template <typename T>
|
Chris@16
|
1190 void operator()(T const& val) const
|
Chris@16
|
1191 {
|
Chris@16
|
1192 if (is_first)
|
Chris@16
|
1193 is_first = false;
|
Chris@16
|
1194 else
|
Chris@16
|
1195 out << ", ";
|
Chris@16
|
1196 spirit::traits::print_attribute(out, val);
|
Chris@16
|
1197 }
|
Chris@16
|
1198
|
Chris@16
|
1199 Out& out;
|
Chris@16
|
1200 mutable bool is_first;
|
Chris@16
|
1201 };
|
Chris@16
|
1202
|
Chris@16
|
1203 // print elements in a variant
|
Chris@16
|
1204 template <typename Out>
|
Chris@16
|
1205 struct print_visitor : static_visitor<>
|
Chris@16
|
1206 {
|
Chris@16
|
1207 print_visitor(Out& out_) : out(out_) {}
|
Chris@16
|
1208
|
Chris@16
|
1209 template <typename T>
|
Chris@16
|
1210 void operator()(T const& val) const
|
Chris@16
|
1211 {
|
Chris@16
|
1212 spirit::traits::print_attribute(out, val);
|
Chris@16
|
1213 }
|
Chris@16
|
1214
|
Chris@16
|
1215 Out& out;
|
Chris@16
|
1216 };
|
Chris@16
|
1217 }
|
Chris@16
|
1218
|
Chris@16
|
1219 template <typename Out, typename T, typename Enable>
|
Chris@16
|
1220 struct print_attribute_debug
|
Chris@16
|
1221 {
|
Chris@16
|
1222 // for plain data types
|
Chris@16
|
1223 template <typename T_>
|
Chris@16
|
1224 static void call_impl3(Out& out, T_ const& val, mpl::false_)
|
Chris@16
|
1225 {
|
Chris@16
|
1226 out << val;
|
Chris@16
|
1227 }
|
Chris@16
|
1228
|
Chris@16
|
1229 // for fusion data types
|
Chris@16
|
1230 template <typename T_>
|
Chris@16
|
1231 static void call_impl3(Out& out, T_ const& val, mpl::true_)
|
Chris@16
|
1232 {
|
Chris@16
|
1233 out << '[';
|
Chris@16
|
1234 fusion::for_each(val, detail::print_fusion_sequence<Out>(out));
|
Chris@16
|
1235 out << ']';
|
Chris@16
|
1236 }
|
Chris@16
|
1237
|
Chris@16
|
1238 // non-stl container
|
Chris@16
|
1239 template <typename T_>
|
Chris@16
|
1240 static void call_impl2(Out& out, T_ const& val, mpl::false_)
|
Chris@16
|
1241 {
|
Chris@16
|
1242 call_impl3(out, val, fusion::traits::is_sequence<T_>());
|
Chris@16
|
1243 }
|
Chris@16
|
1244
|
Chris@16
|
1245 // stl container
|
Chris@16
|
1246 template <typename T_>
|
Chris@16
|
1247 static void call_impl2(Out& out, T_ const& val, mpl::true_)
|
Chris@16
|
1248 {
|
Chris@16
|
1249 out << '[';
|
Chris@16
|
1250 if (!traits::is_empty(val))
|
Chris@16
|
1251 {
|
Chris@16
|
1252 bool first = true;
|
Chris@16
|
1253 typename container_iterator<T_ const>::type iend = traits::end(val);
|
Chris@16
|
1254 for (typename container_iterator<T_ const>::type i = traits::begin(val);
|
Chris@16
|
1255 !traits::compare(i, iend); traits::next(i))
|
Chris@16
|
1256 {
|
Chris@16
|
1257 if (!first)
|
Chris@16
|
1258 out << ", ";
|
Chris@16
|
1259 first = false;
|
Chris@16
|
1260 spirit::traits::print_attribute(out, traits::deref(i));
|
Chris@16
|
1261 }
|
Chris@16
|
1262 }
|
Chris@16
|
1263 out << ']';
|
Chris@16
|
1264 }
|
Chris@16
|
1265
|
Chris@16
|
1266 // for variant types
|
Chris@16
|
1267 template <typename T_>
|
Chris@16
|
1268 static void call_impl(Out& out, T_ const& val, mpl::false_)
|
Chris@16
|
1269 {
|
Chris@16
|
1270 apply_visitor(detail::print_visitor<Out>(out), val);
|
Chris@16
|
1271 }
|
Chris@16
|
1272
|
Chris@16
|
1273 // for non-variant types
|
Chris@16
|
1274 template <typename T_>
|
Chris@16
|
1275 static void call_impl(Out& out, T_ const& val, mpl::true_)
|
Chris@16
|
1276 {
|
Chris@16
|
1277 call_impl2(out, val, is_container<T_>());
|
Chris@16
|
1278 }
|
Chris@16
|
1279
|
Chris@16
|
1280 // main entry point
|
Chris@16
|
1281 static void call(Out& out, T const& val)
|
Chris@16
|
1282 {
|
Chris@16
|
1283 call_impl(out, val, not_is_variant<T>());
|
Chris@16
|
1284 }
|
Chris@16
|
1285 };
|
Chris@16
|
1286
|
Chris@16
|
1287 template <typename Out, typename T>
|
Chris@16
|
1288 struct print_attribute_debug<Out, boost::optional<T> >
|
Chris@16
|
1289 {
|
Chris@16
|
1290 static void call(Out& out, boost::optional<T> const& val)
|
Chris@16
|
1291 {
|
Chris@16
|
1292 if (val)
|
Chris@16
|
1293 spirit::traits::print_attribute(out, *val);
|
Chris@16
|
1294 else
|
Chris@16
|
1295 out << "[empty]";
|
Chris@16
|
1296 }
|
Chris@16
|
1297 };
|
Chris@16
|
1298
|
Chris@16
|
1299 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1300 template <typename Out, typename T>
|
Chris@16
|
1301 inline void print_attribute(Out& out, T const& val)
|
Chris@16
|
1302 {
|
Chris@16
|
1303 print_attribute_debug<Out, T>::call(out, val);
|
Chris@16
|
1304 }
|
Chris@16
|
1305
|
Chris@16
|
1306 template <typename Out>
|
Chris@16
|
1307 inline void print_attribute(Out&, unused_type)
|
Chris@16
|
1308 {
|
Chris@16
|
1309 }
|
Chris@16
|
1310
|
Chris@16
|
1311 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1312 // generate debug output for lookahead token (character) stream
|
Chris@16
|
1313 namespace detail
|
Chris@16
|
1314 {
|
Chris@16
|
1315 struct token_printer_debug_for_chars
|
Chris@16
|
1316 {
|
Chris@16
|
1317 template<typename Out, typename Char>
|
Chris@16
|
1318 static void print(Out& o, Char c)
|
Chris@16
|
1319 {
|
Chris@16
|
1320 using namespace std; // allow for ADL to find the proper iscntrl
|
Chris@16
|
1321
|
Chris@16
|
1322 if (c == static_cast<Char>('\a'))
|
Chris@16
|
1323 o << "\\a";
|
Chris@16
|
1324 else if (c == static_cast<Char>('\b'))
|
Chris@16
|
1325 o << "\\b";
|
Chris@16
|
1326 else if (c == static_cast<Char>('\f'))
|
Chris@16
|
1327 o << "\\f";
|
Chris@16
|
1328 else if (c == static_cast<Char>('\n'))
|
Chris@16
|
1329 o << "\\n";
|
Chris@16
|
1330 else if (c == static_cast<Char>('\r'))
|
Chris@16
|
1331 o << "\\r";
|
Chris@16
|
1332 else if (c == static_cast<Char>('\t'))
|
Chris@16
|
1333 o << "\\t";
|
Chris@16
|
1334 else if (c == static_cast<Char>('\v'))
|
Chris@16
|
1335 o << "\\v";
|
Chris@16
|
1336 else if (c >= 0 && c < 127 && iscntrl(c))
|
Chris@16
|
1337 o << "\\" << std::oct << static_cast<int>(c);
|
Chris@16
|
1338 else
|
Chris@16
|
1339 o << static_cast<char>(c);
|
Chris@16
|
1340 }
|
Chris@16
|
1341 };
|
Chris@16
|
1342
|
Chris@16
|
1343 // for token types where the comparison with char constants wouldn't work
|
Chris@16
|
1344 struct token_printer_debug
|
Chris@16
|
1345 {
|
Chris@16
|
1346 template<typename Out, typename T>
|
Chris@16
|
1347 static void print(Out& o, T const& val)
|
Chris@16
|
1348 {
|
Chris@16
|
1349 o << val;
|
Chris@16
|
1350 }
|
Chris@16
|
1351 };
|
Chris@16
|
1352 }
|
Chris@16
|
1353
|
Chris@16
|
1354 template <typename T, typename Enable>
|
Chris@16
|
1355 struct token_printer_debug
|
Chris@16
|
1356 : mpl::if_<
|
Chris@16
|
1357 mpl::and_<
|
Chris@16
|
1358 is_convertible<T, char>, is_convertible<char, T> >
|
Chris@16
|
1359 , detail::token_printer_debug_for_chars
|
Chris@16
|
1360 , detail::token_printer_debug>::type
|
Chris@16
|
1361 {};
|
Chris@16
|
1362
|
Chris@16
|
1363 template <typename Out, typename T>
|
Chris@16
|
1364 inline void print_token(Out& out, T const& val)
|
Chris@16
|
1365 {
|
Chris@16
|
1366 // allow to customize the token printer routine
|
Chris@16
|
1367 token_printer_debug<T>::print(out, val);
|
Chris@16
|
1368 }
|
Chris@16
|
1369 }}}
|
Chris@16
|
1370
|
Chris@16
|
1371 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1372 namespace boost { namespace spirit { namespace result_of
|
Chris@16
|
1373 {
|
Chris@16
|
1374 template <typename Exposed, typename Transformed, typename Domain>
|
Chris@16
|
1375 struct pre_transform
|
Chris@16
|
1376 : traits::transform_attribute<Exposed, Transformed, Domain>
|
Chris@16
|
1377 {};
|
Chris@16
|
1378 }}}
|
Chris@16
|
1379
|
Chris@16
|
1380
|
Chris@16
|
1381 #endif
|