alternative.hpp 4.5 KB

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