• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #ifndef BOOST_SPIRIT_REPOSITORY_QI_DIRECTIVE_DISTINCT_HPP
9 #define BOOST_SPIRIT_REPOSITORY_QI_DIRECTIVE_DISTINCT_HPP
10 
11 #if defined(_MSC_VER)
12 #pragma once
13 #endif
14 
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>
30 
31 #include <boost/spirit/repository/home/support/distinct.hpp>
32 
33 #include <boost/fusion/include/at.hpp>
34 #include <boost/fusion/include/vector.hpp>
35 
36 ///////////////////////////////////////////////////////////////////////////////
37 namespace boost { namespace spirit
38 {
39     ///////////////////////////////////////////////////////////////////////////
40     // Enablers
41     ///////////////////////////////////////////////////////////////////////////
42 
43     // enables distinct(...)[...]
44     template <typename Tail>
45     struct use_directive<qi::domain
46           , terminal_ex<repository::tag::distinct, fusion::vector1<Tail> > >
47       : mpl::true_ {};
48 
49     // enables *lazy* distinct(...)[...]
50     template <>
51     struct use_lazy_directive<qi::domain, repository::tag::distinct, 1>
52       : mpl::true_ {};
53 
54 }}
55 
56 ///////////////////////////////////////////////////////////////////////////////
57 namespace boost { namespace spirit { namespace repository {namespace qi
58 {
59 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
60     using repository::distinct;
61 #endif
62     using repository::distinct_type;
63 
64     template <typename Subject, typename Tail, typename Modifier>
65     struct distinct_parser
66       : spirit::qi::unary_parser<distinct_parser<Subject, Tail, Modifier> >
67     {
68         template <typename Context, typename Iterator>
69         struct attribute
70           : traits::attribute_of<Subject, Context, Iterator>
71         {};
72 
distinct_parserboost::spirit::repository::qi::distinct_parser73         distinct_parser(Subject const& subject, Tail const& tail)
74           : subject(subject), tail(tail) {}
75 
76         template <typename Iterator, typename Context
77           , typename Skipper, typename Attribute>
parseboost::spirit::repository::qi::distinct_parser78         bool parse(Iterator& first, Iterator const& last
79           , Context& context, Skipper const& skipper, Attribute& attr) const
80         {
81             Iterator iter = first;
82 
83             spirit::qi::skip_over(iter, last, skipper);
84             if (!subject.parse(iter, last, context
85               , spirit::qi::detail::unused_skipper<Skipper>(skipper), attr))
86                 return false;
87 
88             Iterator i = iter;
89             if (tail.parse(i, last, context, unused, unused))
90                 return false;
91 
92             first = iter;
93             return true;
94         }
95 
96         template <typename Context>
whatboost::spirit::repository::qi::distinct_parser97         info what(Context& /*ctx*/) const
98         {
99             return info("distinct");
100         }
101 
102         Subject subject;
103         Tail tail;
104     };
105 
106 }}}}
107 
108 ///////////////////////////////////////////////////////////////////////////////
109 namespace boost { namespace spirit { namespace qi
110 {
111     ///////////////////////////////////////////////////////////////////////////
112     // Parser generators: make_xxx function (objects)
113     ///////////////////////////////////////////////////////////////////////////
114     template <typename Tail, typename Subject, typename Modifiers>
115     struct make_directive<
116         terminal_ex<repository::tag::distinct, fusion::vector1<Tail> >
117       , Subject, Modifiers>
118     {
119         typedef typename result_of::compile<qi::domain, Tail, Modifiers>::type
120             tail_type;
121 
122         typedef repository::qi::distinct_parser<
123             Subject, tail_type, Modifiers> result_type;
124 
125         template <typename Terminal>
operator ()boost::spirit::qi::make_directive126         result_type operator()(Terminal const& term, Subject const& subject
127           , Modifiers const& modifiers) const
128         {
129             return result_type(subject
130               , compile<qi::domain>(fusion::at_c<0>(term.args), modifiers));
131         }
132     };
133 
134 }}}
135 
136 namespace boost { namespace spirit { namespace traits
137 {
138     template <typename Subject, typename Tail, typename Modifier>
139     struct has_semantic_action<
140             repository::qi::distinct_parser<Subject, Tail, Modifier> >
141       : unary_has_semantic_action<Subject> {};
142 }}}
143 
144 #endif
145 
146