sequential_or.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. =============================================================================*/
  6. #ifndef BOOST_SPIRIT_QI_OPERATOR_SEQUENTIAL_OR_HPP
  7. #define BOOST_SPIRIT_QI_OPERATOR_SEQUENTIAL_OR_HPP
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/qi/meta_compiler.hpp>
  12. #include <boost/spirit/home/qi/detail/pass_function.hpp>
  13. #include <boost/spirit/home/qi/detail/attributes.hpp>
  14. #include <boost/spirit/home/support/detail/what_function.hpp>
  15. #include <boost/spirit/home/support/algorithm/any_if_ns_so.hpp>
  16. #include <boost/spirit/home/support/handles_container.hpp>
  17. #include <boost/fusion/include/as_vector.hpp>
  18. #include <boost/fusion/include/for_each.hpp>
  19. #include <boost/proto/operators.hpp>
  20. #include <boost/proto/tags.hpp>
  21. namespace boost { namespace spirit
  22. {
  23. ///////////////////////////////////////////////////////////////////////////
  24. // Enablers
  25. ///////////////////////////////////////////////////////////////////////////
  26. template <>
  27. struct use_operator<qi::domain, proto::tag::logical_or> // enables ||
  28. : mpl::true_ {};
  29. template <>
  30. struct flatten_tree<qi::domain, proto::tag::logical_or> // flattens ||
  31. : mpl::true_ {};
  32. }}
  33. namespace boost { namespace spirit { namespace qi
  34. {
  35. template <typename Elements>
  36. struct sequential_or : nary_parser<sequential_or<Elements> >
  37. {
  38. template <typename Context, typename Iterator>
  39. struct attribute
  40. {
  41. // Put all the element attributes in a tuple,
  42. // wrapping each element in a boost::optional
  43. typedef typename traits::build_attribute_sequence<
  44. Elements, Context, traits::sequential_or_attribute_transform
  45. , Iterator, qi::domain
  46. >::type all_attributes;
  47. // Now, build a fusion vector over the attributes. Note
  48. // that build_fusion_vector 1) removes all unused attributes
  49. // and 2) may return unused_type if all elements have
  50. // unused_type(s).
  51. typedef typename
  52. traits::build_fusion_vector<all_attributes>::type
  53. type;
  54. };
  55. sequential_or(Elements const& elements_)
  56. : elements(elements_) {}
  57. template <typename Iterator, typename Context
  58. , typename Skipper, typename Attribute>
  59. bool parse(Iterator& first, Iterator const& last
  60. , Context& context, Skipper const& skipper
  61. , Attribute& attr_) const
  62. {
  63. typedef traits::attribute_not_unused<Context, Iterator> predicate;
  64. detail::pass_function<Iterator, Context, Skipper>
  65. f(first, last, context, skipper);
  66. // wrap the attribute in a tuple if it is not a tuple
  67. typename traits::wrap_if_not_tuple<Attribute>::type attr_local(attr_);
  68. // return true if *any* of the parsers succeed
  69. // (we use the non-short-circuiting and strict order version:
  70. // any_if_ns_so to force all the elements to be tested and
  71. // in the defined order: first is first, last is last)
  72. return spirit::any_if_ns_so(elements, attr_local, f, predicate());
  73. }
  74. template <typename Context>
  75. info what(Context& context) const
  76. {
  77. info result("sequential-or");
  78. fusion::for_each(elements,
  79. spirit::detail::what_function<Context>(result, context));
  80. return result;
  81. }
  82. Elements elements;
  83. };
  84. ///////////////////////////////////////////////////////////////////////////
  85. // Parser generators: make_xxx function (objects)
  86. ///////////////////////////////////////////////////////////////////////////
  87. template <typename Elements, typename Modifiers>
  88. struct make_composite<proto::tag::logical_or, Elements, Modifiers>
  89. : make_nary_composite<Elements, sequential_or>
  90. {};
  91. }}}
  92. namespace boost { namespace spirit { namespace traits
  93. {
  94. ///////////////////////////////////////////////////////////////////////////
  95. // We specialize this for sequential_or (see support/attributes.hpp).
  96. // For sequential_or, we only wrap the attribute in a tuple IFF
  97. // it is not already a fusion tuple.
  98. template <typename Elements, typename Attribute>
  99. struct pass_attribute<qi::sequential_or<Elements>, Attribute>
  100. : wrap_if_not_tuple<Attribute> {};
  101. ///////////////////////////////////////////////////////////////////////////
  102. template <typename Elements>
  103. struct has_semantic_action<qi::sequential_or<Elements> >
  104. : nary_has_semantic_action<Elements> {};
  105. ///////////////////////////////////////////////////////////////////////////
  106. template <typename Elements, typename Attribute, typename Context
  107. , typename Iterator>
  108. struct handles_container<qi::sequential_or<Elements>, Attribute, Context
  109. , Iterator>
  110. : nary_handles_container<Elements, Attribute, Context, Iterator> {};
  111. }}}
  112. #endif