]>
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_SYMBOLS_MARCH_11_2007_1055AM) | |
8 | #define BOOST_SPIRIT_SYMBOLS_MARCH_11_2007_1055AM | |
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/skip_over.hpp> | |
16 | #include <boost/spirit/home/qi/string/tst.hpp> | |
17 | #include <boost/spirit/home/qi/reference.hpp> | |
18 | #include <boost/spirit/home/qi/meta_compiler.hpp> | |
19 | #include <boost/spirit/home/qi/detail/assign_to.hpp> | |
20 | #include <boost/spirit/home/qi/parser.hpp> | |
21 | #include <boost/spirit/home/support/detail/get_encoding.hpp> | |
22 | #include <boost/spirit/home/support/modify.hpp> | |
23 | #include <boost/spirit/home/support/info.hpp> | |
24 | #include <boost/spirit/home/support/unused.hpp> | |
25 | #include <boost/spirit/home/support/string_traits.hpp> | |
26 | ||
27 | #include <boost/fusion/include/at.hpp> | |
28 | #include <boost/range.hpp> | |
29 | #include <boost/type_traits/add_reference.hpp> | |
30 | #include <boost/shared_ptr.hpp> | |
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 qi | |
38 | { | |
39 | template < | |
40 | typename Char = char | |
41 | , typename T = unused_type | |
42 | , typename Lookup = tst<Char, T> | |
43 | , typename Filter = tst_pass_through> | |
44 | struct symbols | |
45 | : proto::extends< | |
46 | typename proto::terminal< | |
47 | reference<symbols<Char, T, Lookup, Filter> > | |
48 | >::type | |
49 | , symbols<Char, T, Lookup, Filter> | |
50 | > | |
51 | , primitive_parser<symbols<Char, T, Lookup, Filter> > | |
52 | { | |
53 | typedef Char char_type; // the character type | |
54 | typedef T value_type; // the value associated with each entry | |
55 | typedef symbols<Char, T, Lookup, Filter> this_type; | |
56 | typedef reference<this_type> reference_; | |
57 | typedef typename proto::terminal<reference_>::type terminal; | |
58 | typedef proto::extends<terminal, this_type> base_type; | |
59 | ||
60 | template <typename Context, typename Iterator> | |
61 | struct attribute | |
62 | { | |
63 | typedef value_type type; | |
64 | }; | |
65 | ||
66 | symbols(std::string const& name = "symbols") | |
67 | : base_type(terminal::make(reference_(*this))) | |
68 | , add(*this) | |
69 | , remove(*this) | |
70 | , lookup(new Lookup()) | |
71 | , name_(name) | |
72 | { | |
73 | } | |
74 | ||
75 | symbols(symbols const& syms) | |
76 | : base_type(terminal::make(reference_(*this))) | |
77 | , add(*this) | |
78 | , remove(*this) | |
79 | , lookup(syms.lookup) | |
80 | , name_(syms.name_) | |
81 | { | |
82 | } | |
83 | ||
84 | template <typename Filter_> | |
85 | symbols(symbols<Char, T, Lookup, Filter_> const& syms) | |
86 | : base_type(terminal::make(reference_(*this))) | |
87 | , add(*this) | |
88 | , remove(*this) | |
89 | , lookup(syms.lookup) | |
90 | , name_(syms.name_) | |
91 | { | |
92 | } | |
93 | ||
94 | template <typename Symbols> | |
95 | symbols(Symbols const& syms, std::string const& name = "symbols") | |
96 | : base_type(terminal::make(reference_(*this))) | |
97 | , add(*this) | |
98 | , remove(*this) | |
99 | , lookup(new Lookup()) | |
100 | , name_(name) | |
101 | { | |
102 | typename range_const_iterator<Symbols>::type si = boost::begin(syms); | |
103 | while (si != boost::end(syms)) | |
104 | add(*si++); | |
105 | } | |
106 | ||
107 | template <typename Symbols, typename Data> | |
108 | symbols(Symbols const& syms, Data const& data | |
109 | , std::string const& name = "symbols") | |
110 | : base_type(terminal::make(reference_(*this))) | |
111 | , add(*this) | |
112 | , remove(*this) | |
113 | , lookup(new Lookup()) | |
114 | , name_(name) | |
115 | { | |
116 | typename range_const_iterator<Symbols>::type si = boost::begin(syms); | |
117 | typename range_const_iterator<Data>::type di = boost::begin(data); | |
118 | while (si != boost::end(syms)) | |
119 | add(*si++, *di++); | |
120 | } | |
121 | ||
122 | symbols& | |
123 | operator=(symbols const& rhs) | |
124 | { | |
125 | name_ = rhs.name_; | |
126 | *lookup = *rhs.lookup; | |
127 | return *this; | |
128 | } | |
129 | ||
130 | template <typename Filter_> | |
131 | symbols& | |
132 | operator=(symbols<Char, T, Lookup, Filter_> const& rhs) | |
133 | { | |
134 | name_ = rhs.name_; | |
135 | *lookup = *rhs.lookup; | |
136 | return *this; | |
137 | } | |
138 | ||
139 | void clear() | |
140 | { | |
141 | lookup->clear(); | |
142 | } | |
143 | ||
144 | struct adder; | |
145 | struct remover; | |
146 | ||
147 | template <typename Str> | |
148 | adder const& | |
149 | operator=(Str const& str) | |
150 | { | |
151 | lookup->clear(); | |
152 | return add(str); | |
153 | } | |
154 | ||
155 | template <typename Str> | |
156 | friend adder const& | |
157 | operator+=(symbols& sym, Str const& str) | |
158 | { | |
159 | return sym.add(str); | |
160 | } | |
161 | ||
162 | template <typename Str> | |
163 | friend remover const& | |
164 | operator-=(symbols& sym, Str const& str) | |
165 | { | |
166 | return sym.remove(str); | |
167 | } | |
168 | ||
169 | #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
170 | // non-const version needed to suppress proto's += kicking in | |
171 | template <typename Str> | |
172 | friend adder const& | |
173 | operator+=(symbols& sym, Str& str) | |
174 | { | |
175 | return sym.add(str); | |
176 | } | |
177 | ||
178 | // non-const version needed to suppress proto's -= kicking in | |
179 | template <typename Str> | |
180 | friend remover const& | |
181 | operator-=(symbols& sym, Str& str) | |
182 | { | |
183 | return sym.remove(str); | |
184 | } | |
185 | #else | |
186 | // for rvalue references | |
187 | template <typename Str> | |
188 | friend adder const& | |
189 | operator+=(symbols& sym, Str&& str) | |
190 | { | |
191 | return sym.add(str); | |
192 | } | |
193 | ||
194 | // for rvalue references | |
195 | template <typename Str> | |
196 | friend remover const& | |
197 | operator-=(symbols& sym, Str&& str) | |
198 | { | |
199 | return sym.remove(str); | |
200 | } | |
201 | #endif | |
202 | template <typename F> | |
203 | void for_each(F f) const | |
204 | { | |
205 | lookup->for_each(f); | |
206 | } | |
207 | ||
208 | template <typename Str> | |
209 | value_type& at(Str const& str) | |
210 | { | |
211 | return *lookup->add(traits::get_begin<Char>(str) | |
212 | , traits::get_end<Char>(str), T()); | |
213 | } | |
214 | ||
215 | template <typename Iterator> | |
216 | value_type* prefix_find(Iterator& first, Iterator const& last) | |
217 | { | |
218 | return lookup->find(first, last, Filter()); | |
219 | } | |
220 | ||
221 | template <typename Iterator> | |
222 | value_type const* prefix_find(Iterator& first, Iterator const& last) const | |
223 | { | |
224 | return lookup->find(first, last, Filter()); | |
225 | } | |
226 | ||
227 | template <typename Str> | |
228 | value_type* find(Str const& str) | |
229 | { | |
230 | return find_impl(traits::get_begin<Char>(str) | |
231 | , traits::get_end<Char>(str)); | |
232 | } | |
233 | ||
234 | template <typename Str> | |
235 | value_type const* find(Str const& str) const | |
236 | { | |
237 | return find_impl(traits::get_begin<Char>(str) | |
238 | , traits::get_end<Char>(str)); | |
239 | } | |
240 | ||
241 | private: | |
242 | template <typename Iterator> | |
243 | value_type* find_impl(Iterator begin, Iterator end) | |
244 | { | |
245 | value_type* r = lookup->find(begin, end, Filter()); | |
246 | return begin == end ? r : 0; | |
247 | } | |
248 | ||
249 | template <typename Iterator> | |
250 | value_type const* find_impl(Iterator begin, Iterator end) const | |
251 | { | |
252 | value_type const* r = lookup->find(begin, end, Filter()); | |
253 | return begin == end ? r : 0; | |
254 | } | |
255 | ||
256 | public: | |
257 | template <typename Iterator, typename Context | |
258 | , typename Skipper, typename Attribute> | |
259 | bool parse(Iterator& first, Iterator const& last | |
260 | , Context& /*context*/, Skipper const& skipper, Attribute& attr_) const | |
261 | { | |
262 | qi::skip_over(first, last, skipper); | |
263 | ||
264 | if (value_type* val_ptr | |
265 | = lookup->find(first, last, Filter())) | |
266 | { | |
267 | spirit::traits::assign_to(*val_ptr, attr_); | |
268 | return true; | |
269 | } | |
270 | return false; | |
271 | } | |
272 | ||
273 | template <typename Context> | |
274 | info what(Context& /*context*/) const | |
275 | { | |
276 | return info(name_); | |
277 | } | |
278 | ||
279 | void name(std::string const &str) | |
280 | { | |
281 | name_ = str; | |
282 | } | |
283 | std::string const &name() const | |
284 | { | |
285 | return name_; | |
286 | } | |
287 | ||
288 | struct adder | |
289 | { | |
290 | template <typename, typename = unused_type, typename = unused_type> | |
291 | struct result { typedef adder const& type; }; | |
292 | ||
293 | adder(symbols& sym_) | |
294 | : sym(sym_) | |
295 | { | |
296 | } | |
297 | ||
298 | template <typename Iterator> | |
299 | adder const& | |
300 | operator()(Iterator const& first, Iterator const& last, T const& val) const | |
301 | { | |
302 | sym.lookup->add(first, last, val); | |
303 | return *this; | |
304 | } | |
305 | ||
306 | template <typename Str> | |
307 | adder const& | |
308 | operator()(Str const& s, T const& val = T()) const | |
309 | { | |
310 | sym.lookup->add(traits::get_begin<Char>(s) | |
311 | , traits::get_end<Char>(s), val); | |
312 | return *this; | |
313 | } | |
314 | ||
315 | template <typename Str> | |
316 | adder const& | |
317 | operator,(Str const& s) const | |
318 | { | |
319 | sym.lookup->add(traits::get_begin<Char>(s) | |
320 | , traits::get_end<Char>(s), T()); | |
321 | return *this; | |
322 | } | |
323 | ||
324 | symbols& sym; | |
325 | ||
326 | private: | |
327 | // silence MSVC warning C4512: assignment operator could not be generated | |
328 | adder& operator= (adder const&); | |
329 | }; | |
330 | ||
331 | struct remover | |
332 | { | |
333 | template <typename, typename = unused_type, typename = unused_type> | |
334 | struct result { typedef remover const& type; }; | |
335 | ||
336 | remover(symbols& sym_) | |
337 | : sym(sym_) | |
338 | { | |
339 | } | |
340 | ||
341 | template <typename Iterator> | |
342 | remover const& | |
343 | operator()(Iterator const& first, Iterator const& last) const | |
344 | { | |
345 | sym.lookup->remove(first, last); | |
346 | return *this; | |
347 | } | |
348 | ||
349 | template <typename Str> | |
350 | remover const& | |
351 | operator()(Str const& s) const | |
352 | { | |
353 | sym.lookup->remove(traits::get_begin<Char>(s) | |
354 | , traits::get_end<Char>(s)); | |
355 | return *this; | |
356 | } | |
357 | ||
358 | template <typename Str> | |
359 | remover const& | |
360 | operator,(Str const& s) const | |
361 | { | |
362 | sym.lookup->remove(traits::get_begin<Char>(s) | |
363 | , traits::get_end<Char>(s)); | |
364 | return *this; | |
365 | } | |
366 | ||
367 | symbols& sym; | |
368 | ||
369 | private: | |
370 | // silence MSVC warning C4512: assignment operator could not be generated | |
371 | remover& operator= (remover const&); | |
372 | }; | |
373 | ||
374 | adder add; | |
375 | remover remove; | |
376 | shared_ptr<Lookup> lookup; | |
377 | std::string name_; | |
378 | }; | |
379 | ||
380 | /////////////////////////////////////////////////////////////////////////// | |
381 | // Parser generators: make_xxx function (objects) | |
382 | /////////////////////////////////////////////////////////////////////////// | |
383 | template <typename Char, typename T, typename Lookup | |
384 | , typename Filter, typename Modifiers> | |
385 | struct make_primitive<reference<symbols<Char, T, Lookup, Filter> >, Modifiers> | |
386 | { | |
387 | template <typename CharEncoding> | |
388 | struct no_case_filter | |
389 | { | |
390 | Char operator()(Char ch) const | |
391 | { | |
392 | return static_cast<Char>(CharEncoding::tolower(ch)); | |
393 | } | |
394 | }; | |
395 | ||
396 | typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case; | |
397 | typedef reference<symbols<Char, T, Lookup, Filter> > reference_; | |
398 | typedef no_case_filter< | |
399 | typename spirit::detail::get_encoding_with_case< | |
400 | Modifiers | |
401 | , char_encoding::standard | |
402 | , no_case::value>::type> | |
403 | nc_filter; | |
404 | ||
405 | typedef typename mpl::if_< | |
406 | no_case | |
407 | , symbols<Char, T, Lookup, nc_filter> | |
408 | , reference_>::type | |
409 | result_type; | |
410 | ||
411 | result_type operator()(reference_ ref, unused_type) const | |
412 | { | |
413 | return result_type(ref.ref.get()); | |
414 | } | |
415 | }; | |
416 | }}} | |
417 | ||
418 | namespace boost { namespace spirit { namespace traits | |
419 | { | |
420 | /////////////////////////////////////////////////////////////////////////// | |
421 | template <typename Char, typename T, typename Lookup, typename Filter | |
422 | , typename Attr, typename Context, typename Iterator> | |
423 | struct handles_container<qi::symbols<Char, T, Lookup, Filter>, Attr, Context, Iterator> | |
424 | : traits::is_container<Attr> {}; | |
425 | }}} | |
426 | ||
427 | #if defined(BOOST_MSVC) | |
428 | # pragma warning(pop) | |
429 | #endif | |
430 | ||
431 | #endif |