sequential_or.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. #if !defined(SPIRIT_SEQUENTIAL_OR_MARCH_12_2007_1130PM)
  7. #define SPIRIT_SEQUENTIAL_OR_MARCH_12_2007_1130PM
  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. namespace boost { namespace spirit
  20. {
  21. ///////////////////////////////////////////////////////////////////////////
  22. // Enablers
  23. ///////////////////////////////////////////////////////////////////////////
  24. template <>
  25. struct use_operator<qi::domain, proto::tag::logical_or> // enables ||
  26. : mpl::true_ {};
  27. template <>
  28. struct flatten_tree<qi::domain, proto::tag::logical_or> // flattens ||
  29. : mpl::true_ {};
  30. }}
  31. namespace boost { namespace spirit { namespace qi
  32. {
  33. template <typename Elements>
  34. struct sequential_or : nary_parser<sequential_or<Elements> >
  35. {
  36. template <typename Context, typename Iterator>
  37. struct attribute
  38. {
  39. // Put all the element attributes in a tuple,
  40. // wrapping each element in a boost::optional
  41. typedef typename traits::build_attribute_sequence<
  42. Elements, Context, traits::sequential_or_attribute_transform
  43. , Iterator, qi::domain
  44. >::type all_attributes;
  45. // Now, build a fusion vector over the attributes. Note
  46. // that build_fusion_vector 1) removes all unused attributes
  47. // and 2) may return unused_type if all elements have
  48. // unused_type(s).
  49. typedef typename
  50. traits::build_fusion_vector<all_attributes>::type
  51. type;
  52. };
  53. sequential_or(Elements const& elements_)
  54. : elements(elements_) {}
  55. template <typename Iterator, typename Context
  56. , typename Skipper, typename Attribute>
  57. bool parse(Iterator& first, Iterator const& last
  58. , Context& context, Skipper const& skipper
  59. , Attribute& attr_) const
  60. {
  61. typedef traits::attribute_not_unused<Context, Iterator> predicate;
  62. detail::pass_function<Iterator, Context, Skipper>
  63. f(first, last, context, skipper);
  64. // wrap the attribute in a tuple if it is not a tuple
  65. typename traits::wrap_if_not_tuple<Attribute>::type attr_local(attr_);
  66. // return true if *any* of the parsers succeed
  67. // (we use the non-short-circuiting and strict order version:
  68. // any_if_ns_so to force all the elements to be tested and
  69. // in the defined order: first is first, last is last)
  70. return spirit::any_if_ns_so(elements, attr_local, f, predicate());
  71. }
  72. template <typename Context>
  73. info what(Context& context) const
  74. {
  75. info result("sequential-or");
  76. fusion::for_each(elements,
  77. spirit::detail::what_function<Context>(result, context));
  78. return result;
  79. }
  80. Elements elements;
  81. };
  82. ///////////////////////////////////////////////////////////////////////////
  83. // Parser generators: make_xxx function (objects)
  84. ///////////////////////////////////////////////////////////////////////////
  85. template <typename Elements, typename Modifiers>
  86. struct make_composite<proto::tag::logical_or, Elements, Modifiers>
  87. : make_nary_composite<Elements, sequential_or>
  88. {};
  89. }}}
  90. namespace boost { namespace spirit { namespace traits
  91. {
  92. ///////////////////////////////////////////////////////////////////////////
  93. // We specialize this for sequential_or (see support/attributes.hpp).
  94. // For sequential_or, we only wrap the attribute in a tuple IFF
  95. // it is not already a fusion tuple.
  96. template <typename Elements, typename Attribute>
  97. struct pass_attribute<qi::sequential_or<Elements>, Attribute>
  98. : wrap_if_not_tuple<Attribute> {};
  99. ///////////////////////////////////////////////////////////////////////////
  100. template <typename Elements>
  101. struct has_semantic_action<qi::sequential_or<Elements> >
  102. : nary_has_semantic_action<Elements> {};
  103. ///////////////////////////////////////////////////////////////////////////
  104. template <typename Elements, typename Attribute, typename Context
  105. , typename Iterator>
  106. struct handles_container<qi::sequential_or<Elements>, Attribute, Context
  107. , Iterator>
  108. : nary_handles_container<Elements, Attribute, Context, Iterator> {};
  109. }}}
  110. #endif