/Src/Dependencies/Boost/boost/spirit/home/qi/detail/pass_container.hpp

http://hadesmem.googlecode.com/ · C++ Header · 362 lines · 233 code · 43 blank · 86 comment · 3 complexity · 5a03fcfdf0d3a286e7073b944dbd786c MD5 · raw file

  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. =============================================================================*/
  7. #if !defined(SPIRIT_PASS_CONTAINER_JANUARY_06_2009_0802PM)
  8. #define SPIRIT_PASS_CONTAINER_JANUARY_06_2009_0802PM
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/spirit/home/qi/detail/attributes.hpp>
  13. #include <boost/spirit/home/support/container.hpp>
  14. #include <boost/spirit/home/support/handles_container.hpp>
  15. #include <boost/type_traits/is_base_of.hpp>
  16. #include <boost/type_traits/is_convertible.hpp>
  17. #include <boost/mpl/bool.hpp>
  18. #include <boost/mpl/and.hpp>
  19. #include <boost/mpl/or.hpp>
  20. #include <boost/preprocessor/cat.hpp>
  21. #include <boost/preprocessor/repetition/repeat.hpp>
  22. namespace boost { namespace spirit { namespace qi { namespace detail
  23. {
  24. // Helper meta-function allowing to evaluate weak substitutability and
  25. // negate the result if the predicate (Sequence) is not true
  26. template <typename Sequence, typename Attribute, typename ValueType>
  27. struct negate_weak_substitute_if_not
  28. : mpl::if_<
  29. Sequence
  30. , typename traits::is_weak_substitute<Attribute, ValueType>::type
  31. , typename mpl::not_<
  32. traits::is_weak_substitute<Attribute, ValueType>
  33. >::type>
  34. {};
  35. // pass_through_container: utility to check decide whether a provided
  36. // container attribute needs to be passed through to the current component
  37. // or of we need to split the container by passing along instances of its
  38. // value type
  39. // if the expected attribute of the current component is neither a Fusion
  40. // sequence nor a container, we will pass through the provided container
  41. // only if its value type is not compatible with the component
  42. template <typename Container, typename ValueType, typename Attribute
  43. , typename Sequence, typename Enable = void>
  44. struct pass_through_container_base
  45. : negate_weak_substitute_if_not<Sequence, Attribute, ValueType>
  46. {};
  47. // Specialization for fusion sequences, in this case we check whether all
  48. // the types in the sequence are convertible to the lhs attribute.
  49. //
  50. // We return false if the rhs attribute itself is a fusion sequence, which
  51. // is compatible with the LHS sequence (we want to pass through this
  52. // attribute without it being split apart).
  53. template <typename Container, typename ValueType, typename Attribute
  54. , typename Sequence = mpl::true_>
  55. struct not_compatible_element
  56. : mpl::and_<
  57. negate_weak_substitute_if_not<Sequence, Attribute, Container>
  58. , negate_weak_substitute_if_not<Sequence, Attribute, ValueType> >
  59. {};
  60. // If the value type of the container is not a Fusion sequence, we pass
  61. // through the container if each of the elements of the Attribute
  62. // sequence is compatible with either the container or its value type.
  63. template <typename Container, typename ValueType, typename Attribute
  64. , typename Sequence
  65. , bool IsSequence = fusion::traits::is_sequence<ValueType>::value>
  66. struct pass_through_container_fusion_sequence
  67. {
  68. typedef typename mpl::find_if<
  69. Attribute, not_compatible_element<Container, ValueType, mpl::_1>
  70. >::type iter;
  71. typedef typename mpl::end<Attribute>::type end;
  72. typedef typename is_same<iter, end>::type type;
  73. };
  74. // If both, the Attribute and the value type of the provided container
  75. // are Fusion sequences, we pass the container only if the two
  76. // sequences are not compatible.
  77. template <typename Container, typename ValueType, typename Attribute
  78. , typename Sequence>
  79. struct pass_through_container_fusion_sequence<
  80. Container, ValueType, Attribute, Sequence, true>
  81. {
  82. typedef typename mpl::find_if<
  83. Attribute
  84. , not_compatible_element<Container, ValueType, mpl::_1, Sequence>
  85. >::type iter;
  86. typedef typename mpl::end<Attribute>::type end;
  87. typedef typename is_same<iter, end>::type type;
  88. };
  89. template <typename Container, typename ValueType, typename Attribute
  90. , typename Sequence>
  91. struct pass_through_container_base<Container, ValueType, Attribute
  92. , Sequence
  93. , typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
  94. : pass_through_container_fusion_sequence<
  95. Container, ValueType, Attribute, Sequence>
  96. {};
  97. // Specialization for containers
  98. //
  99. // If the value type of the attribute of the current component is not
  100. // a Fusion sequence, we have to pass through the provided container if
  101. // both are compatible.
  102. template <typename Container, typename ValueType, typename Attribute
  103. , typename Sequence, typename AttributeValueType
  104. , bool IsSequence = fusion::traits::is_sequence<AttributeValueType>::value>
  105. struct pass_through_container_container
  106. : mpl::or_<
  107. traits::is_weak_substitute<Attribute, Container>
  108. , traits::is_weak_substitute<AttributeValueType, Container> >
  109. {};
  110. // If the value type of the exposed container attribute is a Fusion
  111. // sequence, we use the already existing logic for those.
  112. template <typename Container, typename ValueType, typename Attribute
  113. , typename Sequence, typename AttributeValueType>
  114. struct pass_through_container_container<
  115. Container, ValueType, Attribute, Sequence, AttributeValueType, true>
  116. : pass_through_container_fusion_sequence<
  117. Container, ValueType, AttributeValueType, Sequence>
  118. {};
  119. template <typename Container, typename ValueType, typename Attribute
  120. , typename Sequence>
  121. struct pass_through_container_base<
  122. Container, ValueType, Attribute, Sequence
  123. , typename enable_if<traits::is_container<Attribute> >::type>
  124. : detail::pass_through_container_container<
  125. Container, ValueType, Attribute, Sequence
  126. , typename traits::container_value<Attribute>::type>
  127. {};
  128. // Specialization for exposed optional attributes
  129. //
  130. // If the type embedded in the exposed optional is not a Fusion
  131. // sequence we pass through the container attribute if it is compatible
  132. // either to the optionals embedded type or to the containers value
  133. // type.
  134. template <typename Container, typename ValueType, typename Attribute
  135. , typename Sequence
  136. , bool IsSequence = fusion::traits::is_sequence<Attribute>::value>
  137. struct pass_through_container_optional
  138. : mpl::or_<
  139. traits::is_weak_substitute<Attribute, Container>
  140. , traits::is_weak_substitute<Attribute, ValueType> >
  141. {};
  142. // If the embedded type of the exposed optional attribute is a Fusion
  143. // sequence, we use the already existing logic for those.
  144. template <typename Container, typename ValueType, typename Attribute
  145. , typename Sequence>
  146. struct pass_through_container_optional<
  147. Container, ValueType, Attribute, Sequence, true>
  148. : pass_through_container_fusion_sequence<
  149. Container, ValueType, Attribute, Sequence>
  150. {};
  151. ///////////////////////////////////////////////////////////////////////////
  152. template <typename Container, typename ValueType, typename Attribute
  153. , typename Sequence>
  154. struct pass_through_container
  155. : pass_through_container_base<Container, ValueType, Attribute, Sequence>
  156. {};
  157. // Handle optional attributes
  158. template <typename Container, typename ValueType, typename Attribute
  159. , typename Sequence>
  160. struct pass_through_container<
  161. Container, ValueType, boost::optional<Attribute>, Sequence>
  162. : pass_through_container_optional<
  163. Container, ValueType, Attribute, Sequence>
  164. {};
  165. // If both, the containers value type and the exposed attribute type are
  166. // optionals we are allowed to pass through the the container only if the
  167. // embedded types of those optionals are not compatible.
  168. template <typename Container, typename ValueType, typename Attribute
  169. , typename Sequence>
  170. struct pass_through_container<
  171. Container, boost::optional<ValueType>, boost::optional<Attribute>
  172. , Sequence>
  173. : mpl::not_<traits::is_weak_substitute<Attribute, ValueType> >
  174. {};
  175. // Specialization for exposed variant attributes
  176. //
  177. // We pass through the container attribute if at least one of the embedded
  178. // types in the variant requires to pass through the attribute
  179. #define BOOST_SPIRIT_PASS_THROUGH_CONTAINER(z, N, _) \
  180. pass_through_container<Container, ValueType, \
  181. BOOST_PP_CAT(T, N), Sequence>::type::value || \
  182. /***/
  183. // make sure unused variant parameters do not affect the outcome
  184. template <typename Container, typename ValueType, typename Sequence>
  185. struct pass_through_container<Container, ValueType
  186. , boost::detail::variant::void_, Sequence>
  187. : mpl::false_
  188. {};
  189. template <typename Container, typename ValueType, typename Sequence
  190. , BOOST_VARIANT_ENUM_PARAMS(typename T)>
  191. struct pass_through_container<Container, ValueType
  192. , boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Sequence>
  193. : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
  194. , BOOST_SPIRIT_PASS_THROUGH_CONTAINER, _) false>
  195. {};
  196. #undef BOOST_SPIRIT_PASS_THROUGH_CONTAINER
  197. }}}}
  198. ///////////////////////////////////////////////////////////////////////////////
  199. namespace boost { namespace spirit { namespace traits
  200. {
  201. ///////////////////////////////////////////////////////////////////////////
  202. // forwarding customization point for domain qi::domain
  203. template <typename Container, typename ValueType, typename Attribute
  204. , typename Sequence>
  205. struct pass_through_container<
  206. Container, ValueType, Attribute, Sequence, qi::domain>
  207. : qi::detail::pass_through_container<
  208. Container, ValueType, Attribute, Sequence>
  209. {};
  210. }}}
  211. namespace boost { namespace spirit { namespace qi { namespace detail
  212. {
  213. ///////////////////////////////////////////////////////////////////////////
  214. // This function handles the case where the attribute (Attr) given
  215. // the sequence is an STL container. This is a wrapper around F.
  216. // The function F does the actual parsing.
  217. template <typename F, typename Attr, typename Sequence>
  218. struct pass_container
  219. {
  220. typedef typename F::context_type context_type;
  221. typedef typename F::iterator_type iterator_type;
  222. pass_container(F const& f, Attr& attr)
  223. : f(f), attr(attr) {}
  224. // this is for the case when the current element exposes an attribute
  225. // which is pushed back onto the container
  226. template <typename Component>
  227. bool dispatch_container(Component const& component, mpl::false_) const
  228. {
  229. // synthesized attribute needs to be default constructed
  230. typename traits::container_value<Attr>::type val =
  231. typename traits::container_value<Attr>::type();
  232. iterator_type save = f.first;
  233. bool r = f(component, val);
  234. if (!r)
  235. {
  236. // push the parsed value into our attribute
  237. r = !traits::push_back(attr, val);
  238. if (r)
  239. f.first = save;
  240. }
  241. return r;
  242. }
  243. // this is for the case when the current element is able to handle an
  244. // attribute which is a container itself, this element will push its
  245. // data directly into the attribute container
  246. template <typename Component>
  247. bool dispatch_container(Component const& component, mpl::true_) const
  248. {
  249. return f(component, attr);
  250. }
  251. ///////////////////////////////////////////////////////////////////////
  252. // this is for the case when the current element doesn't expect an
  253. // attribute
  254. template <typename Component>
  255. bool dispatch_attribute(Component const& component, mpl::false_) const
  256. {
  257. return f(component, unused);
  258. }
  259. // the current element expects an attribute
  260. template <typename Component>
  261. bool dispatch_attribute(Component const& component, mpl::true_) const
  262. {
  263. typedef typename traits::container_value<Attr>::type value_type;
  264. typedef typename traits::attribute_of<
  265. Component, context_type, iterator_type>::type
  266. rhs_attribute;
  267. // this predicate detects, whether the attribute of the current
  268. // element is a substitute for the value type of the container
  269. // attribute
  270. typedef mpl::and_<
  271. traits::handles_container<
  272. Component, Attr, context_type, iterator_type>
  273. , traits::pass_through_container<
  274. Attr, value_type, rhs_attribute, Sequence, qi::domain>
  275. > predicate;
  276. return dispatch_container(component, predicate());
  277. }
  278. // Dispatches to dispatch_main depending on the attribute type
  279. // of the Component
  280. template <typename Component>
  281. bool operator()(Component const& component) const
  282. {
  283. // we need to dispatch depending on the type of the attribute
  284. // of the current element (component). If this is has no attribute
  285. // we shouldn't pass an attribute at all.
  286. typedef typename traits::not_is_unused<
  287. typename traits::attribute_of<
  288. Component, context_type, iterator_type
  289. >::type
  290. >::type predicate;
  291. // ensure the attribute is actually a container type
  292. traits::make_container(attr);
  293. return dispatch_attribute(component, predicate());
  294. }
  295. F f;
  296. Attr& attr;
  297. private:
  298. // silence MSVC warning C4512: assignment operator could not be generated
  299. pass_container& operator= (pass_container const&);
  300. };
  301. ///////////////////////////////////////////////////////////////////////////
  302. // Utility function to make a pass_container for container components
  303. // (kleene, list, plus, repeat)
  304. template <typename F, typename Attr>
  305. inline pass_container<F, Attr, mpl::false_>
  306. make_pass_container(F const& f, Attr& attr)
  307. {
  308. return pass_container<F, Attr, mpl::false_>(f, attr);
  309. }
  310. // Utility function to make a pass_container for sequences
  311. template <typename F, typename Attr>
  312. inline pass_container<F, Attr, mpl::true_>
  313. make_sequence_pass_container(F const& f, Attr& attr)
  314. {
  315. return pass_container<F, Attr, mpl::true_>(f, attr);
  316. }
  317. }}}}
  318. #endif