1 // Copyright (c) 2001-2011 Hartmut Kaiser
2 // Copyright (c) 2001-2011 Joel de Guzman
3 // Copyright (c) 2003 Vaclav Vesely
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)
8 #if !defined(SPIRIT_REPOSITORY_QI_DISTINCT_MAY_20_2009_0825M)
9 #define SPIRIT_REPOSITORY_QI_DISTINCT_MAY_20_2009_0825M
15 #include <boost/spirit/home/qi/skip_over.hpp>
16 #include <boost/spirit/home/qi/domain.hpp>
17 #include <boost/spirit/home/qi/parser.hpp>
18 #include <boost/spirit/home/qi/meta_compiler.hpp>
19 #include <boost/spirit/home/qi/detail/unused_skipper.hpp>
20 #include <boost/spirit/home/support/common_terminals.hpp>
21 #include <boost/spirit/home/support/make_component.hpp>
22 #include <boost/spirit/home/support/info.hpp>
23 #include <boost/spirit/home/support/unused.hpp>
24 #include <boost/spirit/home/qi/detail/attributes.hpp>
25 #include <boost/spirit/home/support/string_traits.hpp>
26 #include <boost/spirit/home/qi/auxiliary/eps.hpp>
27 #include <boost/spirit/home/qi/auxiliary/lazy.hpp>
28 #include <boost/spirit/home/qi/directive/lexeme.hpp>
29 #include <boost/spirit/home/qi/operator/not_predicate.hpp>
31 #include <boost/spirit/repository/home/support/distinct.hpp>
33 #include <boost/fusion/include/at.hpp>
34 #include <boost/fusion/include/vector.hpp>
36 ///////////////////////////////////////////////////////////////////////////////
37 namespace boost { namespace spirit
39 ///////////////////////////////////////////////////////////////////////////
41 ///////////////////////////////////////////////////////////////////////////
43 // enables distinct(...)[...]
44 template <typename Tail>
45 struct use_directive<qi::domain
46 , terminal_ex<repository::tag::distinct, fusion::vector1<Tail> > >
49 // enables *lazy* distinct(...)[...]
51 struct use_lazy_directive<qi::domain, repository::tag::distinct, 1>
56 ///////////////////////////////////////////////////////////////////////////////
57 namespace boost { namespace spirit { namespace repository {namespace qi
59 using repository::distinct_type;
60 using repository::distinct;
62 template <typename Subject, typename Tail, typename Modifier>
63 struct distinct_parser
64 : spirit::qi::unary_parser<distinct_parser<Subject, Tail, Modifier> >
66 template <typename Context, typename Iterator>
68 : traits::attribute_of<Subject, Context, Iterator>
71 distinct_parser(Subject const& subject, Tail const& tail)
72 : subject(subject), tail(tail) {}
74 template <typename Iterator, typename Context
75 , typename Skipper, typename Attribute>
76 bool parse(Iterator& first, Iterator const& last
77 , Context& context, Skipper const& skipper, Attribute& attr) const
79 Iterator iter = first;
81 spirit::qi::skip_over(iter, last, skipper);
82 if (!subject.parse(iter, last, context
83 , spirit::qi::detail::unused_skipper<Skipper>(skipper), attr))
87 if (tail.parse(i, last, context, unused, unused))
94 template <typename Context>
95 info what(Context& /*ctx*/) const
97 return info("distinct");
106 ///////////////////////////////////////////////////////////////////////////////
107 namespace boost { namespace spirit { namespace qi
109 ///////////////////////////////////////////////////////////////////////////
110 // Parser generators: make_xxx function (objects)
111 ///////////////////////////////////////////////////////////////////////////
112 template <typename Tail, typename Subject, typename Modifiers>
113 struct make_directive<
114 terminal_ex<repository::tag::distinct, fusion::vector1<Tail> >
115 , Subject, Modifiers>
117 typedef typename result_of::compile<qi::domain, Tail, Modifiers>::type
120 typedef repository::qi::distinct_parser<
121 Subject, tail_type, Modifiers> result_type;
123 template <typename Terminal>
124 result_type operator()(Terminal const& term, Subject const& subject
125 , Modifiers const& modifiers) const
127 return result_type(subject
128 , compile<qi::domain>(fusion::at_c<0>(term.args), modifiers));
134 namespace boost { namespace spirit { namespace traits
136 template <typename Subject, typename Tail, typename Modifier>
137 struct has_semantic_action<
138 repository::qi::distinct_parser<Subject, Tail, Modifier> >
139 : unary_has_semantic_action<Subject> {};