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