distinct.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. // Copyright (c) 2001-2011 Joel de Guzman
  3. // Copyright (c) 2003 Vaclav Vesely
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #if !defined(SPIRIT_REPOSITORY_QI_DISTINCT_MAY_20_2009_0825M)
  8. #define SPIRIT_REPOSITORY_QI_DISTINCT_MAY_20_2009_0825M
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/spirit/home/qi/skip_over.hpp>
  13. #include <boost/spirit/home/qi/domain.hpp>
  14. #include <boost/spirit/home/qi/parser.hpp>
  15. #include <boost/spirit/home/qi/meta_compiler.hpp>
  16. #include <boost/spirit/home/qi/detail/unused_skipper.hpp>
  17. #include <boost/spirit/home/support/common_terminals.hpp>
  18. #include <boost/spirit/home/support/make_component.hpp>
  19. #include <boost/spirit/home/support/info.hpp>
  20. #include <boost/spirit/home/support/unused.hpp>
  21. #include <boost/spirit/home/qi/detail/attributes.hpp>
  22. #include <boost/spirit/home/support/string_traits.hpp>
  23. #include <boost/spirit/home/qi/auxiliary/eps.hpp>
  24. #include <boost/spirit/home/qi/auxiliary/lazy.hpp>
  25. #include <boost/spirit/home/qi/directive/lexeme.hpp>
  26. #include <boost/spirit/home/qi/operator/not_predicate.hpp>
  27. #include <boost/spirit/repository/home/support/distinct.hpp>
  28. #include <boost/fusion/include/at.hpp>
  29. #include <boost/fusion/include/vector.hpp>
  30. ///////////////////////////////////////////////////////////////////////////////
  31. namespace boost { namespace spirit
  32. {
  33. ///////////////////////////////////////////////////////////////////////////
  34. // Enablers
  35. ///////////////////////////////////////////////////////////////////////////
  36. // enables distinct(...)[...]
  37. template <typename Tail>
  38. struct use_directive<qi::domain
  39. , terminal_ex<repository::tag::distinct, fusion::vector1<Tail> > >
  40. : mpl::true_ {};
  41. // enables *lazy* distinct(...)[...]
  42. template <>
  43. struct use_lazy_directive<qi::domain, repository::tag::distinct, 1>
  44. : mpl::true_ {};
  45. }}
  46. ///////////////////////////////////////////////////////////////////////////////
  47. namespace boost { namespace spirit { namespace repository {namespace qi
  48. {
  49. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  50. using repository::distinct;
  51. #endif
  52. using repository::distinct_type;
  53. template <typename Subject, typename Tail, typename Modifier>
  54. struct distinct_parser
  55. : spirit::qi::unary_parser<distinct_parser<Subject, Tail, Modifier> >
  56. {
  57. template <typename Context, typename Iterator>
  58. struct attribute
  59. : traits::attribute_of<Subject, Context, Iterator>
  60. {};
  61. distinct_parser(Subject const& subject, Tail const& tail)
  62. : subject(subject), tail(tail) {}
  63. template <typename Iterator, typename Context
  64. , typename Skipper, typename Attribute>
  65. bool parse(Iterator& first, Iterator const& last
  66. , Context& context, Skipper const& skipper, Attribute& attr) const
  67. {
  68. Iterator iter = first;
  69. spirit::qi::skip_over(iter, last, skipper);
  70. if (!subject.parse(iter, last, context
  71. , spirit::qi::detail::unused_skipper<Skipper>(skipper), attr))
  72. return false;
  73. Iterator i = iter;
  74. if (tail.parse(i, last, context, unused, unused))
  75. return false;
  76. first = iter;
  77. return true;
  78. }
  79. template <typename Context>
  80. info what(Context& /*ctx*/) const
  81. {
  82. return info("distinct");
  83. }
  84. Subject subject;
  85. Tail tail;
  86. };
  87. }}}}
  88. ///////////////////////////////////////////////////////////////////////////////
  89. namespace boost { namespace spirit { namespace qi
  90. {
  91. ///////////////////////////////////////////////////////////////////////////
  92. // Parser generators: make_xxx function (objects)
  93. ///////////////////////////////////////////////////////////////////////////
  94. template <typename Tail, typename Subject, typename Modifiers>
  95. struct make_directive<
  96. terminal_ex<repository::tag::distinct, fusion::vector1<Tail> >
  97. , Subject, Modifiers>
  98. {
  99. typedef typename result_of::compile<qi::domain, Tail, Modifiers>::type
  100. tail_type;
  101. typedef repository::qi::distinct_parser<
  102. Subject, tail_type, Modifiers> result_type;
  103. template <typename Terminal>
  104. result_type operator()(Terminal const& term, Subject const& subject
  105. , Modifiers const& modifiers) const
  106. {
  107. return result_type(subject
  108. , compile<qi::domain>(fusion::at_c<0>(term.args), modifiers));
  109. }
  110. };
  111. }}}
  112. namespace boost { namespace spirit { namespace traits
  113. {
  114. template <typename Subject, typename Tail, typename Modifier>
  115. struct has_semantic_action<
  116. repository::qi::distinct_parser<Subject, Tail, Modifier> >
  117. : unary_has_semantic_action<Subject> {};
  118. }}}
  119. #endif