File indexing completed on 2024-11-15 09:31:47
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_SPIRIT_QI_DETAIL_PASS_CONTAINER_HPP
0009 #define BOOST_SPIRIT_QI_DETAIL_PASS_CONTAINER_HPP
0010
0011 #if defined(_MSC_VER)
0012 #pragma once
0013 #endif
0014
0015 #include <boost/spirit/home/qi/detail/attributes.hpp>
0016 #include <boost/spirit/home/support/container.hpp>
0017 #include <boost/spirit/home/support/handles_container.hpp>
0018 #include <boost/type_traits/is_base_of.hpp>
0019 #include <boost/type_traits/is_convertible.hpp>
0020 #include <boost/mpl/bool.hpp>
0021 #include <boost/mpl/and.hpp>
0022 #include <boost/mpl/or.hpp>
0023 #include <boost/preprocessor/cat.hpp>
0024 #include <boost/preprocessor/repetition/repeat.hpp>
0025
0026 namespace boost { namespace spirit { namespace qi { namespace detail
0027 {
0028
0029
0030 template <typename Sequence, typename Attribute, typename ValueType>
0031 struct negate_weak_substitute_if_not
0032 : mpl::if_<
0033 Sequence
0034 , typename traits::is_weak_substitute<Attribute, ValueType>::type
0035 , typename mpl::not_<
0036 traits::is_weak_substitute<Attribute, ValueType>
0037 >::type>
0038 {};
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 template <typename Container, typename ValueType, typename Attribute
0049 , typename Sequence, typename Enable = void>
0050 struct pass_through_container_base
0051 : negate_weak_substitute_if_not<Sequence, Attribute, ValueType>
0052 {};
0053
0054
0055
0056
0057
0058
0059
0060 template <typename Container, typename ValueType, typename Attribute
0061 , typename Sequence = mpl::true_>
0062 struct not_compatible_element
0063 : mpl::and_<
0064 negate_weak_substitute_if_not<Sequence, Attribute, Container>
0065 , negate_weak_substitute_if_not<Sequence, Attribute, ValueType> >
0066 {};
0067
0068
0069
0070
0071 template <typename Container, typename ValueType, typename Attribute
0072 , typename Sequence
0073 , bool IsSequence = fusion::traits::is_sequence<ValueType>::value>
0074 struct pass_through_container_fusion_sequence
0075 {
0076 typedef typename mpl::find_if<
0077 Attribute, not_compatible_element<Container, ValueType, mpl::_1>
0078 >::type iter;
0079 typedef typename mpl::end<Attribute>::type end;
0080
0081 typedef typename is_same<iter, end>::type type;
0082 };
0083
0084
0085
0086
0087 template <typename Container, typename ValueType, typename Attribute
0088 , typename Sequence>
0089 struct pass_through_container_fusion_sequence<
0090 Container, ValueType, Attribute, Sequence, true>
0091 {
0092 typedef typename mpl::find_if<
0093 Attribute
0094 , not_compatible_element<Container, ValueType, mpl::_1, Sequence>
0095 >::type iter;
0096 typedef typename mpl::end<Attribute>::type end;
0097
0098 typedef typename is_same<iter, end>::type type;
0099 };
0100
0101 template <typename Container, typename ValueType, typename Attribute
0102 , typename Sequence>
0103 struct pass_through_container_base<Container, ValueType, Attribute
0104 , Sequence
0105 , typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
0106 : pass_through_container_fusion_sequence<
0107 Container, ValueType, Attribute, Sequence>
0108 {};
0109
0110
0111
0112
0113
0114
0115 template <typename Container, typename ValueType, typename Attribute
0116 , typename Sequence, typename AttributeValueType
0117 , bool IsSequence = fusion::traits::is_sequence<AttributeValueType>::value>
0118 struct pass_through_container_container
0119 : mpl::or_<
0120 traits::is_weak_substitute<Attribute, Container>
0121 , traits::is_weak_substitute<AttributeValueType, Container> >
0122 {};
0123
0124
0125
0126 template <typename Container, typename ValueType, typename Attribute
0127 , typename Sequence, typename AttributeValueType>
0128 struct pass_through_container_container<
0129 Container, ValueType, Attribute, Sequence, AttributeValueType, true>
0130 : pass_through_container_fusion_sequence<
0131 Container, ValueType, AttributeValueType, Sequence>
0132 {};
0133
0134 template <typename Container, typename ValueType, typename Attribute
0135 , typename Sequence>
0136 struct pass_through_container_base<
0137 Container, ValueType, Attribute, Sequence
0138 , typename enable_if<traits::is_container<Attribute> >::type>
0139 : detail::pass_through_container_container<
0140 Container, ValueType, Attribute, Sequence
0141 , typename traits::container_value<Attribute>::type>
0142 {};
0143
0144
0145
0146
0147
0148
0149
0150 template <typename Container, typename ValueType, typename Attribute
0151 , typename Sequence
0152 , bool IsSequence = fusion::traits::is_sequence<Attribute>::value>
0153 struct pass_through_container_optional
0154 : mpl::or_<
0155 traits::is_weak_substitute<Attribute, Container>
0156 , traits::is_weak_substitute<Attribute, ValueType> >
0157 {};
0158
0159
0160
0161 template <typename Container, typename ValueType, typename Attribute
0162 , typename Sequence>
0163 struct pass_through_container_optional<
0164 Container, ValueType, Attribute, Sequence, true>
0165 : pass_through_container_fusion_sequence<
0166 Container, ValueType, Attribute, Sequence>
0167 {};
0168
0169
0170 template <typename Container, typename ValueType, typename Attribute
0171 , typename Sequence>
0172 struct pass_through_container
0173 : pass_through_container_base<Container, ValueType, Attribute, Sequence>
0174 {};
0175
0176
0177 template <typename Container, typename ValueType, typename Attribute
0178 , typename Sequence>
0179 struct pass_through_container<
0180 Container, ValueType, boost::optional<Attribute>, Sequence>
0181 : pass_through_container_optional<
0182 Container, ValueType, Attribute, Sequence>
0183 {};
0184
0185
0186
0187
0188 template <typename Container, typename ValueType, typename Attribute
0189 , typename Sequence>
0190 struct pass_through_container<
0191 Container, boost::optional<ValueType>, boost::optional<Attribute>
0192 , Sequence>
0193 : mpl::not_<traits::is_weak_substitute<Attribute, ValueType> >
0194 {};
0195
0196
0197
0198
0199
0200
0201 #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
0202 template <typename Container, typename ValueType, typename Sequence
0203 , typename T>
0204 struct pass_through_container<Container, ValueType, boost::variant<T>
0205 , Sequence>
0206 : pass_through_container<Container, ValueType, T, Sequence>
0207 {};
0208
0209 template <typename Container, typename ValueType, typename Sequence
0210 , typename T0, typename ...TN>
0211 struct pass_through_container<Container, ValueType
0212 , boost::variant<T0, TN...>, Sequence>
0213 : mpl::bool_<pass_through_container<
0214 Container, ValueType, T0, Sequence
0215 >::type::value || pass_through_container<
0216 Container, ValueType, boost::variant<TN...>, Sequence
0217 >::type::value>
0218 {};
0219 #else
0220 #define BOOST_SPIRIT_PASS_THROUGH_CONTAINER(z, N, _) \
0221 pass_through_container<Container, ValueType, \
0222 BOOST_PP_CAT(T, N), Sequence>::type::value || \
0223
0224
0225
0226 template <typename Container, typename ValueType, typename Sequence>
0227 struct pass_through_container<Container, ValueType
0228 , boost::detail::variant::void_, Sequence>
0229 : mpl::false_
0230 {};
0231
0232 template <typename Container, typename ValueType, typename Sequence
0233 , BOOST_VARIANT_ENUM_PARAMS(typename T)>
0234 struct pass_through_container<Container, ValueType
0235 , boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Sequence>
0236 : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
0237 , BOOST_SPIRIT_PASS_THROUGH_CONTAINER, _) false>
0238 {};
0239
0240 #undef BOOST_SPIRIT_PASS_THROUGH_CONTAINER
0241 #endif
0242 }}}}
0243
0244
0245 namespace boost { namespace spirit { namespace traits
0246 {
0247
0248
0249 template <typename Container, typename ValueType, typename Attribute
0250 , typename Sequence>
0251 struct pass_through_container<
0252 Container, ValueType, Attribute, Sequence, qi::domain>
0253 : qi::detail::pass_through_container<
0254 Container, ValueType, Attribute, Sequence>
0255 {};
0256 }}}
0257
0258 namespace boost { namespace spirit { namespace qi { namespace detail
0259 {
0260
0261
0262
0263
0264 #ifdef _MSC_VER
0265 # pragma warning(push)
0266 # pragma warning(disable: 4512)
0267 #endif
0268 template <typename F, typename Attr, typename Sequence>
0269 struct pass_container
0270 {
0271 typedef typename F::context_type context_type;
0272 typedef typename F::iterator_type iterator_type;
0273
0274 pass_container(F const& f_, Attr& attr_)
0275 : f(f_), attr(attr_) {}
0276
0277
0278
0279 template <typename Component>
0280 bool dispatch_container(Component const& component, mpl::false_) const
0281 {
0282
0283 typename traits::container_value<Attr>::type val =
0284 typename traits::container_value<Attr>::type();
0285
0286 iterator_type save = f.first;
0287 bool r = f(component, val);
0288 if (!r)
0289 {
0290
0291 r = !traits::push_back(attr, val);
0292 if (r)
0293 f.first = save;
0294 }
0295 return r;
0296 }
0297
0298
0299
0300
0301 template <typename Component>
0302 bool dispatch_container(Component const& component, mpl::true_) const
0303 {
0304 return f(component, attr);
0305 }
0306
0307
0308
0309
0310 template <typename Component>
0311 bool dispatch_attribute(Component const& component, mpl::false_) const
0312 {
0313 return f(component, unused);
0314 }
0315
0316
0317 template <typename Component>
0318 bool dispatch_attribute(Component const& component, mpl::true_) const
0319 {
0320 typedef typename traits::container_value<Attr>::type value_type;
0321 typedef typename traits::attribute_of<
0322 Component, context_type, iterator_type>::type
0323 rhs_attribute;
0324
0325
0326
0327
0328 typedef mpl::and_<
0329 traits::handles_container<
0330 Component, Attr, context_type, iterator_type>
0331 , traits::pass_through_container<
0332 Attr, value_type, rhs_attribute, Sequence, qi::domain>
0333 > predicate;
0334
0335 return dispatch_container(component, predicate());
0336 }
0337
0338
0339
0340 template <typename Component>
0341 bool operator()(Component const& component) const
0342 {
0343
0344
0345
0346 typedef typename traits::not_is_unused<
0347 typename traits::attribute_of<
0348 Component, context_type, iterator_type
0349 >::type
0350 >::type predicate;
0351
0352
0353 traits::make_container(attr);
0354
0355 return dispatch_attribute(component, predicate());
0356 }
0357
0358 F f;
0359 Attr& attr;
0360 };
0361 #ifdef _MSC_VER
0362 # pragma warning(pop)
0363 #endif
0364
0365
0366
0367
0368 template <typename F, typename Attr>
0369 inline pass_container<F, Attr, mpl::false_>
0370 make_pass_container(F const& f, Attr& attr)
0371 {
0372 return pass_container<F, Attr, mpl::false_>(f, attr);
0373 }
0374
0375
0376 template <typename F, typename Attr>
0377 inline pass_container<F, Attr, mpl::true_>
0378 make_sequence_pass_container(F const& f, Attr& attr)
0379 {
0380 return pass_container<F, Attr, mpl::true_>(f, attr);
0381 }
0382 }}}}
0383
0384 #endif
0385