alternative.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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_ALTERNATIVE_FEBRUARY_05_2007_1153AM)
  8. #define SPIRIT_ALTERNATIVE_FEBRUARY_05_2007_1153AM
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/spirit/home/qi/detail/alternative_function.hpp>
  13. #include <boost/spirit/home/qi/meta_compiler.hpp>
  14. #include <boost/spirit/home/qi/parser.hpp>
  15. #include <boost/spirit/home/qi/detail/attributes.hpp>
  16. #include <boost/spirit/home/support/has_semantic_action.hpp>
  17. #include <boost/spirit/home/support/handles_container.hpp>
  18. #include <boost/spirit/home/support/detail/what_function.hpp>
  19. #include <boost/spirit/home/support/unused.hpp>
  20. #include <boost/spirit/home/support/info.hpp>
  21. #include <boost/fusion/include/any.hpp>
  22. #include <boost/fusion/include/mpl.hpp>
  23. #include <boost/fusion/include/for_each.hpp>
  24. namespace boost { namespace spirit
  25. {
  26. ///////////////////////////////////////////////////////////////////////////
  27. // Enablers
  28. ///////////////////////////////////////////////////////////////////////////
  29. template <>
  30. struct use_operator<qi::domain, proto::tag::bitwise_or> // enables |
  31. : mpl::true_ {};
  32. template <>
  33. struct flatten_tree<qi::domain, proto::tag::bitwise_or> // flattens |
  34. : mpl::true_ {};
  35. }}
  36. namespace boost { namespace spirit { namespace qi
  37. {
  38. template <typename Elements>
  39. struct alternative : nary_parser<alternative<Elements> >
  40. {
  41. template <typename Context, typename Iterator>
  42. struct attribute
  43. {
  44. // Put all the element attributes in a tuple
  45. typedef typename traits::build_attribute_sequence<
  46. Elements, Context, traits::alternative_attribute_transform
  47. , Iterator, qi::domain
  48. >::type all_attributes;
  49. // Ok, now make a variant over the attribute sequence. Note that
  50. // build_variant makes sure that 1) all attributes in the variant
  51. // are unique 2) puts the unused attribute, if there is any, to
  52. // the front and 3) collapses single element variants, variant<T>
  53. // to T.
  54. typedef typename
  55. traits::build_variant<all_attributes>::type
  56. type;
  57. };
  58. alternative(Elements const& elements_)
  59. : elements(elements_) {}
  60. template <typename Iterator, typename Context
  61. , typename Skipper, typename Attribute>
  62. bool parse(Iterator& first, Iterator const& last
  63. , Context& context, Skipper const& skipper
  64. , Attribute& attr_) const
  65. {
  66. detail::alternative_function<Iterator, Context, Skipper, Attribute>
  67. f(first, last, context, skipper, attr_);
  68. // return true if *any* of the parsers succeed
  69. return fusion::any(elements, f);
  70. }
  71. template <typename Context>
  72. info what(Context& context) const
  73. {
  74. info result("alternative");
  75. fusion::for_each(elements,
  76. spirit::detail::what_function<Context>(result, context));
  77. return result;
  78. }
  79. Elements elements;
  80. };
  81. ///////////////////////////////////////////////////////////////////////////
  82. // Parser generators: make_xxx function (objects)
  83. ///////////////////////////////////////////////////////////////////////////
  84. template <typename Elements, typename Modifiers>
  85. struct make_composite<proto::tag::bitwise_or, Elements, Modifiers>
  86. : make_nary_composite<Elements, alternative>
  87. {};
  88. }}}
  89. namespace boost { namespace spirit { namespace traits
  90. {
  91. ///////////////////////////////////////////////////////////////////////////
  92. template <typename Elements>
  93. struct has_semantic_action<qi::alternative<Elements> >
  94. : nary_has_semantic_action<Elements> {};
  95. ///////////////////////////////////////////////////////////////////////////
  96. template <typename Elements, typename Attribute, typename Context
  97. , typename Iterator>
  98. struct handles_container<qi::alternative<Elements>, Attribute, Context
  99. , Iterator>
  100. : nary_handles_container<Elements, Attribute, Context, Iterator> {};
  101. }}}
  102. #endif