1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3 
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 #if !defined(BOOST_SPIRIT_CHAR_PARSER_APR_16_2006_0906AM)
8 #define BOOST_SPIRIT_CHAR_PARSER_APR_16_2006_0906AM
9 
10 #if defined(_MSC_VER)
11 #pragma once
12 #endif
13 
14 #include <boost/spirit/home/qi/domain.hpp>
15 #include <boost/spirit/home/qi/parser.hpp>
16 #include <boost/spirit/home/qi/detail/assign_to.hpp>
17 #include <boost/spirit/home/qi/meta_compiler.hpp>
18 #include <boost/spirit/home/qi/skip_over.hpp>
19 #include <boost/spirit/home/support/unused.hpp>
20 #include <boost/spirit/home/support/info.hpp>
21 
22 namespace boost { namespace spirit
23 {
24     ///////////////////////////////////////////////////////////////////////////
25     // Enablers
26     ///////////////////////////////////////////////////////////////////////////
27     template <>
28     struct use_operator<qi::domain, proto::tag::complement> // enables ~
29       : mpl::true_ {};
30 }}
31 
32 namespace boost { namespace spirit { namespace traits // classification
33 {
34     namespace detail
35     {
36         BOOST_MPL_HAS_XXX_TRAIT_DEF(char_parser_id)
37     }
38 
39     template <typename T>
40     struct is_char_parser : detail::has_char_parser_id<T> {};
41 }}}
42 
43 namespace boost { namespace spirit { namespace qi
44 {
45     ///////////////////////////////////////////////////////////////////////////
46     // The base char_parser
47     ///////////////////////////////////////////////////////////////////////////
48     template <typename Derived, typename Char, typename Attr = Char>
49     struct char_parser : primitive_parser<Derived>
50     {
51         typedef Char char_type;
52         struct char_parser_id;
53 
54         // if Attr is unused_type, Derived must supply its own attribute
55         // metafunction
56         template <typename Context, typename Iterator>
57         struct attribute
58         {
59             typedef Attr type;
60         };
61 
62         template <typename Iterator, typename Context, typename Skipper, typename Attribute>
parseboost::spirit::qi::char_parser63         bool parse(Iterator& first, Iterator const& last
64           , Context& context, Skipper const& skipper, Attribute& attr_) const
65         {
66             qi::skip_over(first, last, skipper);
67 
68             if (first != last && this->derived().test(*first, context))
69             {
70                 spirit::traits::assign_to(*first, attr_);
71                 ++first;
72                 return true;
73             }
74             return false;
75         }
76 
77         // Requirement: p.test(ch, context) -> bool
78         //
79         //  ch:         character being parsed
80         //  context:    enclosing rule context
81     };
82 
83     ///////////////////////////////////////////////////////////////////////////
84     // negated_char_parser handles ~cp expressions (cp is a char_parser)
85     ///////////////////////////////////////////////////////////////////////////
86     template <typename Positive>
87     struct negated_char_parser :
88         char_parser<negated_char_parser<Positive>, typename Positive::char_type>
89     {
negated_char_parserboost::spirit::qi::negated_char_parser90         negated_char_parser(Positive const& positive_)
91           : positive(positive_) {}
92 
93         template <typename CharParam, typename Context>
testboost::spirit::qi::negated_char_parser94         bool test(CharParam ch, Context& context) const
95         {
96             return !positive.test(ch, context);
97         }
98 
99         template <typename Context>
whatboost::spirit::qi::negated_char_parser100         info what(Context& context) const
101         {
102             return info("not", positive.what(context));
103         }
104 
105         Positive positive;
106     };
107 
108     ///////////////////////////////////////////////////////////////////////////
109     // Parser generators: make_xxx function (objects)
110     ///////////////////////////////////////////////////////////////////////////
111     namespace detail
112     {
113         template <typename Positive>
114         struct make_negated_char_parser
115         {
116             typedef negated_char_parser<Positive> result_type;
operator ()boost::spirit::qi::detail::make_negated_char_parser117             result_type operator()(Positive const& positive) const
118             {
119                 return result_type(positive);
120             }
121         };
122 
123         template <typename Positive>
124         struct make_negated_char_parser<negated_char_parser<Positive> >
125         {
126             typedef Positive result_type;
operator ()boost::spirit::qi::detail::make_negated_char_parser127             result_type operator()(negated_char_parser<Positive> const& ncp) const
128             {
129                 return ncp.positive;
130             }
131         };
132     }
133 
134     template <typename Elements, typename Modifiers>
135     struct make_composite<proto::tag::complement, Elements, Modifiers>
136     {
137         typedef typename
138             fusion::result_of::value_at_c<Elements, 0>::type
139         subject;
140 
141         BOOST_SPIRIT_ASSERT_MSG((
142             traits::is_char_parser<subject>::value
143         ), subject_is_not_negatable, (subject));
144 
145         typedef typename
146             detail::make_negated_char_parser<subject>::result_type
147         result_type;
148 
operator ()boost::spirit::qi::make_composite149         result_type operator()(Elements const& elements, unused_type) const
150         {
151             return detail::make_negated_char_parser<subject>()(
152                 fusion::at_c<0>(elements));
153         }
154     };
155 }}}
156 
157 #endif
158