]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright (c) 2001-2011 Hartmut Kaiser |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #if !defined(BOOST_SPIRIT_KARMA_CHAR_CLASS_AUG_10_2009_0720AM) | |
7 | #define BOOST_SPIRIT_KARMA_CHAR_CLASS_AUG_10_2009_0720AM | |
8 | ||
9 | #if defined(_MSC_VER) | |
10 | #pragma once | |
11 | #endif | |
12 | ||
13 | #include <boost/spirit/home/support/common_terminals.hpp> | |
14 | #include <boost/spirit/home/support/string_traits.hpp> | |
15 | #include <boost/spirit/home/support/info.hpp> | |
16 | #include <boost/spirit/home/support/char_class.hpp> | |
17 | #include <boost/spirit/home/support/detail/get_encoding.hpp> | |
18 | #include <boost/spirit/home/karma/domain.hpp> | |
19 | #include <boost/spirit/home/karma/meta_compiler.hpp> | |
20 | #include <boost/spirit/home/karma/delimit_out.hpp> | |
21 | #include <boost/spirit/home/karma/char/char_generator.hpp> | |
22 | #include <boost/spirit/home/karma/auxiliary/lazy.hpp> | |
23 | #include <boost/spirit/home/karma/detail/get_casetag.hpp> | |
24 | #include <boost/spirit/home/karma/detail/generate_to.hpp> | |
25 | ||
26 | /////////////////////////////////////////////////////////////////////////////// | |
27 | namespace boost { namespace spirit | |
28 | { | |
29 | /////////////////////////////////////////////////////////////////////////// | |
30 | // Enablers | |
31 | /////////////////////////////////////////////////////////////////////////// | |
32 | // enables alnum, alpha, graph, etc. | |
33 | template <typename CharClass, typename CharEncoding> | |
34 | struct use_terminal<karma::domain | |
35 | , tag::char_code<CharClass, CharEncoding> > | |
36 | : mpl::true_ {}; | |
37 | ||
38 | }} | |
39 | ||
40 | /////////////////////////////////////////////////////////////////////////////// | |
41 | namespace boost { namespace spirit { namespace karma | |
42 | { | |
43 | // hoist the char classification namespaces into karma sub-namespaces of | |
44 | // the same name | |
45 | namespace ascii { using namespace boost::spirit::ascii; } | |
46 | namespace iso8859_1 { using namespace boost::spirit::iso8859_1; } | |
47 | namespace standard { using namespace boost::spirit::standard; } | |
48 | namespace standard_wide { using namespace boost::spirit::standard_wide; } | |
49 | #if defined(BOOST_SPIRIT_UNICODE) | |
50 | namespace unicode { using namespace boost::spirit::unicode; } | |
51 | #endif | |
52 | ||
53 | // Import the standard namespace into the karma namespace. This allows | |
54 | // for default handling of all character/string related operations if not | |
55 | // prefixed with a character set namespace. | |
56 | using namespace boost::spirit::standard; | |
57 | ||
58 | // Import encoding | |
59 | using spirit::encoding; | |
60 | ||
61 | /////////////////////////////////////////////////////////////////////////// | |
62 | // | |
63 | // char_class | |
64 | // generates a single character if it matches the given character | |
65 | // class | |
66 | // | |
67 | /////////////////////////////////////////////////////////////////////////// | |
68 | template <typename Tag, typename CharEncoding, typename CharClass> | |
69 | struct char_class | |
70 | : char_generator< | |
71 | char_class<Tag, CharEncoding, CharClass> | |
72 | , CharEncoding, CharClass> | |
73 | { | |
74 | typedef typename Tag::char_encoding char_encoding; | |
75 | typedef typename char_encoding::char_type char_type; | |
76 | typedef typename Tag::char_class classification; | |
77 | ||
78 | template <typename Context, typename Unused> | |
79 | struct attribute | |
80 | { | |
81 | typedef char_type type; | |
82 | }; | |
83 | ||
84 | // char_class needs an attached attribute | |
85 | template <typename Attribute, typename CharParam, typename Context> | |
86 | bool test(Attribute const& attr, CharParam& ch, Context&) const | |
87 | { | |
88 | ch = attr; | |
89 | ||
90 | using spirit::char_class::classify; | |
91 | return classify<char_encoding>::is(classification(), attr); | |
92 | } | |
93 | ||
94 | // char_class shouldn't be used without any associated attribute | |
95 | template <typename CharParam, typename Context> | |
96 | bool test(unused_type, CharParam&, Context&) const | |
97 | { | |
98 | // It is not possible (doesn't make sense) to use char_ generators | |
99 | // without providing any attribute, as the generator doesn't 'know' | |
100 | // what to output. The following assertion fires if this situation | |
101 | // is detected in your code. | |
102 | BOOST_SPIRIT_ASSERT_FAIL(CharParam | |
103 | , char_class_not_usable_without_attribute, ()); | |
104 | return false; | |
105 | } | |
106 | ||
107 | template <typename Context> | |
108 | static info what(Context const& /*context*/) | |
109 | { | |
110 | typedef spirit::char_class::what<char_encoding> what_; | |
111 | return info(what_::is(classification())); | |
112 | } | |
113 | }; | |
114 | ||
115 | /////////////////////////////////////////////////////////////////////////// | |
116 | // | |
117 | // space | |
118 | // generates a single character from the associated parameter | |
119 | // | |
120 | /////////////////////////////////////////////////////////////////////////// | |
121 | template <typename CharEncoding> | |
122 | struct any_space | |
123 | : char_generator<any_space<CharEncoding>, CharEncoding, tag::space> | |
124 | { | |
125 | typedef typename CharEncoding::char_type char_type; | |
126 | typedef CharEncoding char_encoding; | |
127 | ||
128 | template <typename Context, typename Unused> | |
129 | struct attribute | |
130 | { | |
131 | typedef char_type type; | |
132 | }; | |
133 | ||
134 | // any_space has an attached parameter | |
135 | template <typename Attribute, typename CharParam, typename Context> | |
136 | bool test(Attribute const& attr, CharParam& ch, Context&) const | |
137 | { | |
138 | ch = CharParam(attr); | |
139 | ||
140 | using spirit::char_class::classify; | |
141 | return classify<char_encoding>::is(tag::space(), attr); | |
142 | } | |
143 | ||
144 | // any_space has no attribute attached, use single space character | |
145 | template <typename CharParam, typename Context> | |
146 | bool test(unused_type, CharParam& ch, Context&) const | |
147 | { | |
148 | ch = ' '; | |
149 | return true; | |
150 | } | |
151 | ||
152 | template <typename Context> | |
153 | static info what(Context const& /*context*/) | |
154 | { | |
155 | return info("space"); | |
156 | } | |
157 | }; | |
158 | ||
159 | /////////////////////////////////////////////////////////////////////////// | |
160 | // Generator generators: make_xxx function (objects) | |
161 | /////////////////////////////////////////////////////////////////////////// | |
162 | ||
163 | namespace detail | |
164 | { | |
165 | template <typename Tag, bool lower = false, bool upper = false> | |
166 | struct make_char_class : mpl::identity<Tag> {}; | |
167 | ||
168 | template <> | |
169 | struct make_char_class<tag::alpha, true, false> | |
170 | : mpl::identity<tag::lower> {}; | |
171 | ||
172 | template <> | |
173 | struct make_char_class<tag::alpha, false, true> | |
174 | : mpl::identity<tag::upper> {}; | |
175 | ||
176 | template <> | |
177 | struct make_char_class<tag::alnum, true, false> | |
178 | : mpl::identity<tag::lowernum> {}; | |
179 | ||
180 | template <> | |
181 | struct make_char_class<tag::alnum, false, true> | |
182 | : mpl::identity<tag::uppernum> {}; | |
183 | } | |
184 | ||
185 | // enables alnum, alpha, graph, etc. | |
186 | template <typename CharClass, typename CharEncoding, typename Modifiers> | |
187 | struct make_primitive<tag::char_code<CharClass, CharEncoding>, Modifiers> | |
188 | { | |
189 | static bool const lower = | |
190 | has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value; | |
191 | static bool const upper = | |
192 | has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value; | |
193 | ||
194 | typedef tag::char_code< | |
195 | typename detail::make_char_class<CharClass, lower, upper>::type | |
196 | , CharEncoding> | |
197 | tag_type; | |
198 | ||
199 | typedef char_class< | |
200 | tag_type | |
201 | , typename spirit::detail::get_encoding_with_case< | |
202 | Modifiers, CharEncoding, lower || upper>::type | |
203 | , typename detail::get_casetag<Modifiers, lower || upper>::type | |
204 | > result_type; | |
205 | ||
206 | result_type operator()(unused_type, unused_type) const | |
207 | { | |
208 | return result_type(); | |
209 | } | |
210 | }; | |
211 | ||
212 | // space is special | |
213 | template <typename CharEncoding, typename Modifiers> | |
214 | struct make_primitive<tag::char_code<tag::space, CharEncoding>, Modifiers> | |
215 | { | |
216 | typedef any_space<CharEncoding> result_type; | |
217 | ||
218 | result_type operator()(unused_type, unused_type) const | |
219 | { | |
220 | return result_type(); | |
221 | } | |
222 | }; | |
223 | ||
224 | }}} // namespace boost::spirit::karma | |
225 | ||
226 | #endif // !defined(BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM) |