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