1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
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
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>
22 namespace boost
{ namespace spirit
24 ///////////////////////////////////////////////////////////////////////////
26 ///////////////////////////////////////////////////////////////////////////
28 struct use_operator
<qi::domain
, proto::tag::complement
> // enables ~
32 namespace boost
{ namespace spirit
{ namespace traits
// classification
36 BOOST_MPL_HAS_XXX_TRAIT_DEF(char_parser_id
)
40 struct is_char_parser
: detail::has_char_parser_id
<T
> {};
43 namespace boost
{ namespace spirit
{ namespace qi
45 ///////////////////////////////////////////////////////////////////////////
46 // The base char_parser
47 ///////////////////////////////////////////////////////////////////////////
48 template <typename Derived
, typename Char
, typename Attr
= Char
>
49 struct char_parser
: primitive_parser
<Derived
>
51 typedef Char char_type
;
52 struct char_parser_id
;
54 // if Attr is unused_type, Derived must supply its own attribute
56 template <typename Context
, typename Iterator
>
62 template <typename Iterator
, typename Context
, typename Skipper
, typename Attribute
>
63 bool parse(Iterator
& first
, Iterator
const& last
64 , Context
& context
, Skipper
const& skipper
, Attribute
& attr_
) const
66 qi::skip_over(first
, last
, skipper
);
68 if (first
!= last
&& this->derived().test(*first
, context
))
70 spirit::traits::assign_to(*first
, attr_
);
77 // Requirement: p.test(ch, context) -> bool
79 // ch: character being parsed
80 // context: enclosing rule context
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
>
90 negated_char_parser(Positive
const& positive_
)
91 : positive(positive_
) {}
93 template <typename CharParam
, typename Context
>
94 bool test(CharParam ch
, Context
& context
) const
96 return !positive
.test(ch
, context
);
99 template <typename Context
>
100 info
what(Context
& context
) const
102 return info("not", positive
.what(context
));
108 ///////////////////////////////////////////////////////////////////////////
109 // Parser generators: make_xxx function (objects)
110 ///////////////////////////////////////////////////////////////////////////
113 template <typename Positive
>
114 struct make_negated_char_parser
116 typedef negated_char_parser
<Positive
> result_type
;
117 result_type
operator()(Positive
const& positive
) const
119 return result_type(positive
);
123 template <typename Positive
>
124 struct make_negated_char_parser
<negated_char_parser
<Positive
> >
126 typedef Positive result_type
;
127 result_type
operator()(negated_char_parser
<Positive
> const& ncp
) const
134 template <typename Elements
, typename Modifiers
>
135 struct make_composite
<proto::tag::complement
, Elements
, Modifiers
>
138 fusion::result_of::value_at_c
<Elements
, 0>::type
141 BOOST_SPIRIT_ASSERT_MSG((
142 traits::is_char_parser
<subject
>::value
143 ), subject_is_not_negatable
, (subject
));
146 detail::make_negated_char_parser
<subject
>::result_type
149 result_type
operator()(Elements
const& elements
, unused_type
) const
151 return detail::make_negated_char_parser
<subject
>()(
152 fusion::at_c
<0>(elements
));