]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright (c) 2001-2011 Hartmut Kaiser |
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_GENERATOR_SEP_07_2009_0417PM) | |
8 | #define BOOST_SPIRIT_CHAR_GENERATOR_SEP_07_2009_0417PM | |
9 | ||
10 | #if defined(_MSC_VER) | |
11 | #pragma once | |
12 | #endif | |
13 | ||
14 | #include <boost/spirit/home/karma/domain.hpp> | |
15 | #include <boost/spirit/home/karma/generator.hpp> | |
16 | #include <boost/spirit/home/karma/detail/generate_to.hpp> | |
17 | #include <boost/spirit/home/karma/detail/extract_from.hpp> | |
18 | #include <boost/spirit/home/karma/meta_compiler.hpp> | |
19 | #include <boost/spirit/home/karma/delimit_out.hpp> | |
20 | #include <boost/spirit/home/support/unused.hpp> | |
21 | #include <boost/spirit/home/support/info.hpp> | |
22 | #include <boost/spirit/home/support/container.hpp> | |
23 | ||
24 | namespace boost { namespace spirit | |
25 | { | |
26 | /////////////////////////////////////////////////////////////////////////// | |
27 | // Enablers | |
28 | /////////////////////////////////////////////////////////////////////////// | |
29 | template <> | |
30 | struct use_operator<karma::domain, proto::tag::complement> // enables ~ | |
31 | : mpl::true_ {}; | |
32 | ||
33 | }} | |
34 | ||
35 | namespace boost { namespace spirit { namespace traits // classification | |
36 | { | |
37 | namespace detail | |
38 | { | |
39 | BOOST_MPL_HAS_XXX_TRAIT_DEF(char_generator_id) | |
40 | } | |
41 | ||
42 | template <typename T> | |
43 | struct is_char_generator : detail::has_char_generator_id<T> {}; | |
44 | }}} | |
45 | ||
46 | namespace boost { namespace spirit { namespace karma | |
47 | { | |
48 | /////////////////////////////////////////////////////////////////////////// | |
49 | // The base char_parser | |
50 | /////////////////////////////////////////////////////////////////////////// | |
51 | template <typename Derived, typename CharEncoding, typename Tag | |
52 | , typename Char = typename CharEncoding::char_type, typename Attr = Char> | |
53 | struct char_generator : primitive_generator<Derived> | |
54 | { | |
55 | typedef CharEncoding char_encoding; | |
56 | typedef Tag tag; | |
57 | typedef Char char_type; | |
58 | struct char_generator_id; | |
59 | ||
60 | // if Attr is unused_type, Derived must supply its own attribute | |
61 | // metafunction | |
62 | template <typename Context, typename Unused> | |
63 | struct attribute | |
64 | { | |
65 | typedef Attr type; | |
66 | }; | |
67 | ||
68 | template < | |
69 | typename OutputIterator, typename Context, typename Delimiter | |
70 | , typename Attribute> | |
71 | bool generate(OutputIterator& sink, Context& context, Delimiter const& d | |
72 | , Attribute const& attr) const | |
73 | { | |
74 | if (!traits::has_optional_value(attr)) | |
75 | return false; | |
76 | ||
77 | Attr ch = Attr(); | |
78 | if (!this->derived().test(traits::extract_from<Attr>(attr, context), ch, context)) | |
79 | return false; | |
80 | ||
81 | return karma::detail::generate_to(sink, ch, char_encoding(), tag()) && | |
82 | karma::delimit_out(sink, d); // always do post-delimiting | |
83 | } | |
84 | ||
85 | // Requirement: g.test(attr, ch, context) -> bool | |
86 | // | |
87 | // attr: associated attribute | |
88 | // ch: character to be generated (set by test()) | |
89 | // context: enclosing rule context | |
90 | }; | |
91 | ||
92 | /////////////////////////////////////////////////////////////////////////// | |
93 | // negated_char_generator handles ~cg expressions (cg is a char_generator) | |
94 | /////////////////////////////////////////////////////////////////////////// | |
95 | template <typename Positive> | |
96 | struct negated_char_generator | |
97 | : char_generator<negated_char_generator<Positive> | |
98 | , typename Positive::char_encoding, typename Positive::tag> | |
99 | { | |
100 | negated_char_generator(Positive const& positive) | |
101 | : positive(positive) {} | |
102 | ||
103 | template <typename Attribute, typename CharParam, typename Context> | |
104 | bool test(Attribute const& attr, CharParam& ch, Context& context) const | |
105 | { | |
106 | return !positive.test(attr, ch, context); | |
107 | } | |
108 | ||
109 | template <typename Context> | |
110 | info what(Context& context) const | |
111 | { | |
112 | return info("not", positive.what(context)); | |
113 | } | |
114 | ||
115 | Positive positive; | |
116 | }; | |
117 | ||
118 | /////////////////////////////////////////////////////////////////////////// | |
119 | // Generator generators: make_xxx function (objects) | |
120 | /////////////////////////////////////////////////////////////////////////// | |
121 | namespace detail | |
122 | { | |
123 | template <typename Positive> | |
124 | struct make_negated_char_generator | |
125 | { | |
126 | typedef negated_char_generator<Positive> result_type; | |
127 | result_type operator()(Positive const& positive) const | |
128 | { | |
129 | return result_type(positive); | |
130 | } | |
131 | }; | |
132 | ||
133 | template <typename Positive> | |
134 | struct make_negated_char_generator<negated_char_generator<Positive> > | |
135 | { | |
136 | typedef Positive result_type; | |
137 | result_type operator()(negated_char_generator<Positive> const& ncg) const | |
138 | { | |
139 | return ncg.positive; | |
140 | } | |
141 | }; | |
142 | } | |
143 | ||
144 | template <typename Elements, typename Modifiers> | |
145 | struct make_composite<proto::tag::complement, Elements, Modifiers> | |
146 | { | |
147 | typedef typename | |
148 | fusion::result_of::value_at_c<Elements, 0>::type | |
149 | subject; | |
150 | ||
151 | BOOST_SPIRIT_ASSERT_MSG(( | |
152 | traits::is_char_generator<subject>::value | |
153 | ), subject_is_not_negatable, (subject)); | |
154 | ||
155 | typedef typename | |
156 | detail::make_negated_char_generator<subject>::result_type | |
157 | result_type; | |
158 | ||
159 | result_type operator()(Elements const& elements, unused_type) const | |
160 | { | |
161 | return detail::make_negated_char_generator<subject>()( | |
162 | fusion::at_c<0>(elements)); | |
163 | } | |
164 | }; | |
165 | ||
166 | }}} | |
167 | ||
168 | #endif |