]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2014 Joel de Guzman | |
3 | Copyright (c) 2013 Carl Barron | |
4 | ||
5 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
6 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ==============================================================================*/ | |
8 | #if !defined(BOOST_SPIRIT_X3_SYMBOLS_MARCH_11_2007_1055AM) | |
9 | #define BOOST_SPIRIT_X3_SYMBOLS_MARCH_11_2007_1055AM | |
10 | ||
11 | #include <boost/spirit/home/x3/core/skip_over.hpp> | |
12 | #include <boost/spirit/home/x3/core/parser.hpp> | |
13 | #include <boost/spirit/home/x3/string/tst.hpp> | |
14 | #include <boost/spirit/home/x3/support/unused.hpp> | |
15 | #include <boost/spirit/home/x3/support/traits/string_traits.hpp> | |
16 | #include <boost/spirit/home/x3/support/traits/move_to.hpp> | |
17 | #include <boost/spirit/home/x3/support/no_case.hpp> | |
18 | ||
19 | #include <boost/spirit/home/support/char_encoding/ascii.hpp> | |
20 | #include <boost/spirit/home/support/char_encoding/iso8859_1.hpp> | |
21 | #include <boost/spirit/home/support/char_encoding/standard.hpp> | |
22 | #include <boost/spirit/home/support/char_encoding/standard_wide.hpp> | |
23 | ||
24 | #include <boost/fusion/include/at.hpp> | |
25 | #include <boost/range.hpp> | |
26 | #include <boost/type_traits/add_reference.hpp> | |
27 | #include <boost/type_traits/is_same.hpp> | |
28 | #include <boost/shared_ptr.hpp> | |
29 | ||
30 | #include <initializer_list> | |
31 | ||
32 | #if defined(BOOST_MSVC) | |
33 | # pragma warning(push) | |
34 | # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning | |
35 | #endif | |
36 | ||
37 | namespace boost { namespace spirit { namespace x3 | |
38 | { | |
39 | template < | |
40 | typename Encoding | |
41 | , typename T = unused_type | |
42 | , typename Lookup = tst<typename Encoding::char_type, T> > | |
43 | struct symbols_parser : parser<symbols_parser<Encoding, T, Lookup>> | |
44 | { | |
45 | typedef typename Encoding::char_type char_type; // the character type | |
46 | typedef Encoding encoding; | |
47 | typedef T value_type; // the value associated with each entry | |
48 | typedef value_type attribute_type; | |
49 | ||
50 | static bool const has_attribute = | |
51 | !is_same<unused_type, attribute_type>::value; | |
52 | static bool const handles_container = | |
53 | traits::is_container<attribute_type>::value; | |
54 | ||
55 | symbols_parser(std::string const& name = "symbols") | |
56 | : add(*this) | |
57 | , remove(*this) | |
58 | , lookup(new Lookup()) | |
59 | , name_(name) | |
60 | { | |
61 | } | |
62 | ||
63 | symbols_parser(symbols_parser const& syms) | |
64 | : add(*this) | |
65 | , remove(*this) | |
66 | , lookup(syms.lookup) | |
67 | , name_(syms.name_) | |
68 | { | |
69 | } | |
70 | ||
71 | template <typename Symbols> | |
72 | symbols_parser(Symbols const& syms, std::string const& name = "symbols") | |
73 | : add(*this) | |
74 | , remove(*this) | |
75 | , lookup(new Lookup()) | |
76 | , name_(name) | |
77 | { | |
78 | typename range_const_iterator<Symbols>::type si = boost::begin(syms); | |
79 | while (si != boost::end(syms)) | |
80 | add(*si++); | |
81 | } | |
82 | ||
83 | template <typename Symbols, typename Data> | |
84 | symbols_parser(Symbols const& syms, Data const& data | |
85 | , std::string const& name = "symbols") | |
86 | : add(*this) | |
87 | , remove(*this) | |
88 | , lookup(new Lookup()) | |
89 | , name_(name) | |
90 | { | |
91 | typename range_const_iterator<Symbols>::type si = boost::begin(syms); | |
92 | typename range_const_iterator<Data>::type di = boost::begin(data); | |
93 | while (si != boost::end(syms)) | |
94 | add(*si++, *di++); | |
95 | } | |
96 | ||
97 | symbols_parser(std::initializer_list<std::pair<char_type const*, T>> syms | |
98 | , std::string const & name="symbols") | |
99 | : add(*this) | |
100 | , remove(*this) | |
101 | , lookup(new Lookup()) | |
102 | , name_(name) | |
103 | { | |
104 | typedef std::initializer_list<std::pair<char_type const*, T>> symbols_t; | |
105 | typename range_const_iterator<symbols_t>::type si = boost::begin(syms); | |
106 | for (;si != boost::end(syms); ++si) | |
107 | add(si->first, si->second); | |
108 | } | |
109 | ||
110 | symbols_parser(std::initializer_list<char_type const*> syms | |
111 | , std::string const &name="symbols") | |
112 | : add(*this) | |
113 | , remove(*this) | |
114 | , lookup(new Lookup()) | |
115 | , name_(name) | |
116 | { | |
117 | typedef std::initializer_list<char_type const*> symbols_t; | |
118 | typename range_const_iterator<symbols_t>::type si = boost::begin(syms); | |
119 | while (si != boost::end(syms)) | |
120 | add(*si++); | |
121 | } | |
122 | ||
123 | symbols_parser& | |
124 | operator=(symbols_parser const& rhs) | |
125 | { | |
126 | name_ = rhs.name_; | |
127 | lookup = rhs.lookup; | |
128 | return *this; | |
129 | } | |
130 | ||
131 | void clear() | |
132 | { | |
133 | lookup->clear(); | |
134 | } | |
135 | ||
136 | struct adder; | |
137 | struct remover; | |
138 | ||
139 | template <typename Str> | |
140 | adder const& | |
141 | operator=(Str const& str) | |
142 | { | |
143 | lookup->clear(); | |
144 | return add(str); | |
145 | } | |
146 | ||
147 | template <typename Str> | |
148 | friend adder const& | |
149 | operator+=(symbols_parser& sym, Str const& str) | |
150 | { | |
151 | return sym.add(str); | |
152 | } | |
153 | ||
154 | template <typename Str> | |
155 | friend remover const& | |
156 | operator-=(symbols_parser& sym, Str const& str) | |
157 | { | |
158 | return sym.remove(str); | |
159 | } | |
160 | ||
161 | template <typename F> | |
162 | void for_each(F f) const | |
163 | { | |
164 | lookup->for_each(f); | |
165 | } | |
166 | ||
167 | template <typename Str> | |
168 | value_type& at(Str const& str) | |
169 | { | |
170 | return *lookup->add(traits::get_string_begin<char_type>(str) | |
171 | , traits::get_string_end<char_type>(str), T()); | |
172 | } | |
173 | ||
174 | template <typename Iterator> | |
175 | value_type* prefix_find(Iterator& first, Iterator const& last) | |
176 | { | |
177 | return lookup->find(first, last, case_compare<Encoding>()); | |
178 | } | |
179 | ||
180 | template <typename Iterator> | |
181 | value_type const* prefix_find(Iterator& first, Iterator const& last) const | |
182 | { | |
183 | return lookup->find(first, last, case_compare<Encoding>()); | |
184 | } | |
185 | ||
186 | template <typename Str> | |
187 | value_type* find(Str const& str) | |
188 | { | |
189 | return find_impl(traits::get_string_begin<char_type>(str) | |
190 | , traits::get_string_end<char_type>(str)); | |
191 | } | |
192 | ||
193 | template <typename Str> | |
194 | value_type const* find(Str const& str) const | |
195 | { | |
196 | return find_impl(traits::get_string_begin<char_type>(str) | |
197 | , traits::get_string_end<char_type>(str)); | |
198 | } | |
199 | ||
200 | private: | |
201 | ||
202 | template <typename Iterator> | |
203 | value_type* find_impl(Iterator begin, Iterator end) | |
204 | { | |
205 | value_type* r = lookup->find(begin, end, case_compare<Encoding>()); | |
206 | return begin == end ? r : 0; | |
207 | } | |
208 | ||
209 | template <typename Iterator> | |
210 | value_type const* find_impl(Iterator begin, Iterator end) const | |
211 | { | |
212 | value_type const* r = lookup->find(begin, end, case_compare<Encoding>()); | |
213 | return begin == end ? r : 0; | |
214 | } | |
215 | ||
216 | public: | |
217 | ||
218 | template <typename Iterator, typename Context, typename Attribute> | |
219 | bool parse(Iterator& first, Iterator const& last | |
220 | , Context const& context, unused_type, Attribute& attr) const | |
221 | { | |
222 | x3::skip_over(first, last, context); | |
223 | ||
224 | if (value_type const* val_ptr | |
225 | = lookup->find(first, last, get_case_compare<Encoding>(context))) | |
226 | { | |
227 | x3::traits::move_to(*val_ptr, attr); | |
228 | return true; | |
229 | } | |
230 | return false; | |
231 | } | |
232 | ||
233 | void name(std::string const &str) | |
234 | { | |
235 | name_ = str; | |
236 | } | |
237 | std::string const &name() const | |
238 | { | |
239 | return name_; | |
240 | } | |
241 | ||
242 | struct adder | |
243 | { | |
244 | template <typename, typename = unused_type, typename = unused_type> | |
245 | struct result { typedef adder const& type; }; | |
246 | ||
247 | adder(symbols_parser& sym) | |
248 | : sym(sym) | |
249 | { | |
250 | } | |
251 | ||
252 | template <typename Iterator> | |
253 | adder const& | |
254 | operator()(Iterator first, Iterator last, T const& val) const | |
255 | { | |
256 | sym.lookup->add(first, last, val); | |
257 | return *this; | |
258 | } | |
259 | ||
260 | template <typename Str> | |
261 | adder const& | |
262 | operator()(Str const& s, T const& val = T()) const | |
263 | { | |
264 | sym.lookup->add(traits::get_string_begin<char_type>(s) | |
265 | , traits::get_string_end<char_type>(s), val); | |
266 | return *this; | |
267 | } | |
268 | ||
269 | template <typename Str> | |
270 | adder const& | |
271 | operator,(Str const& s) const | |
272 | { | |
273 | sym.lookup->add(traits::get_string_begin<char_type>(s) | |
274 | , traits::get_string_end<char_type>(s), T()); | |
275 | return *this; | |
276 | } | |
277 | ||
278 | symbols_parser& sym; | |
279 | }; | |
280 | ||
281 | struct remover | |
282 | { | |
283 | template <typename, typename = unused_type, typename = unused_type> | |
284 | struct result { typedef remover const& type; }; | |
285 | ||
286 | remover(symbols_parser& sym) | |
287 | : sym(sym) | |
288 | { | |
289 | } | |
290 | ||
291 | template <typename Iterator> | |
292 | remover const& | |
293 | operator()(Iterator const& first, Iterator const& last) const | |
294 | { | |
295 | sym.lookup->remove(first, last); | |
296 | return *this; | |
297 | } | |
298 | ||
299 | template <typename Str> | |
300 | remover const& | |
301 | operator()(Str const& s) const | |
302 | { | |
303 | sym.lookup->remove(traits::get_string_begin<char_type>(s) | |
304 | , traits::get_string_end<char_type>(s)); | |
305 | return *this; | |
306 | } | |
307 | ||
308 | template <typename Str> | |
309 | remover const& | |
310 | operator,(Str const& s) const | |
311 | { | |
312 | sym.lookup->remove(traits::get_string_begin<char_type>(s) | |
313 | , traits::get_string_end<char_type>(s)); | |
314 | return *this; | |
315 | } | |
316 | ||
317 | symbols_parser& sym; | |
318 | }; | |
319 | ||
320 | adder add; | |
321 | remover remove; | |
322 | shared_ptr<Lookup> lookup; | |
323 | std::string name_; | |
324 | }; | |
325 | ||
326 | template <typename Encoding, typename T, typename Lookup> | |
327 | struct get_info<symbols_parser<Encoding, T, Lookup>> | |
328 | { | |
329 | typedef std::string result_type; | |
330 | result_type operator()(symbols_parser< Encoding, T | |
331 | , Lookup | |
332 | > const& symbols) const | |
333 | { | |
334 | return symbols.name(); | |
335 | } | |
336 | }; | |
337 | ||
338 | namespace standard | |
339 | { | |
340 | template <typename T = unused_type> | |
341 | using symbols = symbols_parser<char_encoding::standard, T>; | |
342 | } | |
343 | ||
344 | using standard::symbols; | |
345 | ||
346 | namespace standard_wide | |
347 | { | |
348 | template <typename T = unused_type> | |
349 | using symbols = symbols_parser<char_encoding::standard_wide, T>; | |
350 | } | |
351 | ||
352 | namespace ascii | |
353 | { | |
354 | template <typename T = unused_type> | |
355 | using symbols = symbols_parser<char_encoding::ascii, T>; | |
356 | } | |
357 | ||
358 | namespace iso8859_1 | |
359 | { | |
360 | template <typename T = unused_type> | |
361 | using symbols = symbols_parser<char_encoding::iso8859_1, T>; | |
362 | } | |
363 | ||
364 | }}} | |
365 | ||
366 | #if defined(BOOST_MSVC) | |
367 | # pragma warning(pop) | |
368 | #endif | |
369 | ||
370 | #endif |