]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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> | |
63 | 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 | { | |
90 | negated_char_parser(Positive const& positive_) | |
91 | : positive(positive_) {} | |
92 | ||
93 | template <typename CharParam, typename Context> | |
94 | bool test(CharParam ch, Context& context) const | |
95 | { | |
96 | return !positive.test(ch, context); | |
97 | } | |
98 | ||
99 | template <typename Context> | |
100 | 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; | |
117 | 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; | |
127 | 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 | ||
149 | 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 |