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