Chris@16
|
1 // Copyright (c) 2001-2011 Hartmut Kaiser
|
Chris@16
|
2 //
|
Chris@16
|
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 #if !defined(BOOST_SPIRIT_KARMA_SYMBOLS_NOV_23_2009_1251PM)
|
Chris@16
|
7 #define BOOST_SPIRIT_KARMA_SYMBOLS_NOV_23_2009_1251PM
|
Chris@16
|
8
|
Chris@16
|
9 #include <boost/spirit/home/support/common_terminals.hpp>
|
Chris@16
|
10 #include <boost/spirit/home/support/info.hpp>
|
Chris@16
|
11 #include <boost/spirit/home/support/unused.hpp>
|
Chris@16
|
12 #include <boost/spirit/home/support/attributes_fwd.hpp>
|
Chris@16
|
13 #include <boost/spirit/home/support/detail/get_encoding.hpp>
|
Chris@16
|
14 #include <boost/spirit/home/karma/detail/attributes.hpp>
|
Chris@16
|
15 #include <boost/spirit/home/karma/detail/extract_from.hpp>
|
Chris@16
|
16 #include <boost/spirit/home/karma/domain.hpp>
|
Chris@16
|
17 #include <boost/spirit/home/karma/meta_compiler.hpp>
|
Chris@16
|
18 #include <boost/spirit/home/karma/reference.hpp>
|
Chris@16
|
19 #include <boost/spirit/home/karma/generate.hpp>
|
Chris@16
|
20 #include <boost/spirit/home/karma/delimit_out.hpp>
|
Chris@16
|
21 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
|
Chris@16
|
22 #include <boost/spirit/home/karma/detail/string_generate.hpp>
|
Chris@16
|
23 #include <boost/config.hpp>
|
Chris@16
|
24 #include <boost/shared_ptr.hpp>
|
Chris@16
|
25 #include <boost/mpl/if.hpp>
|
Chris@16
|
26 #include <map>
|
Chris@16
|
27 #include <set>
|
Chris@16
|
28
|
Chris@16
|
29 #if defined(BOOST_MSVC)
|
Chris@16
|
30 # pragma warning(push)
|
Chris@16
|
31 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
|
Chris@16
|
32 #endif
|
Chris@16
|
33
|
Chris@16
|
34 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
35 namespace boost { namespace spirit { namespace traits
|
Chris@16
|
36 {
|
Chris@16
|
37 template <typename T, typename Attribute, typename Enable>
|
Chris@16
|
38 struct symbols_lookup
|
Chris@16
|
39 {
|
Chris@16
|
40 typedef
|
Chris@16
|
41 mpl::eval_if<fusion::traits::is_sequence<T>
|
Chris@16
|
42 , traits::detail::value_at_c<T, 0>
|
Chris@16
|
43 , detail::add_const_ref<T> > sequence_type;
|
Chris@16
|
44 typedef typename
|
Chris@16
|
45 mpl::eval_if<traits::is_container<T>
|
Chris@16
|
46 , traits::container_value<T>
|
Chris@16
|
47 , sequence_type>::type type;
|
Chris@16
|
48
|
Chris@16
|
49 // fusion sequence
|
Chris@16
|
50 template <typename T_>
|
Chris@16
|
51 static type call(T_ const& t, mpl::false_, mpl::true_)
|
Chris@16
|
52 {
|
Chris@16
|
53 return fusion::at_c<0>(t);
|
Chris@16
|
54 }
|
Chris@16
|
55
|
Chris@16
|
56 // container
|
Chris@16
|
57 template <typename T_, typename IsSequence>
|
Chris@16
|
58 static type call(T_ const& t, mpl::true_, IsSequence)
|
Chris@16
|
59 {
|
Chris@16
|
60 return t[0];
|
Chris@16
|
61 }
|
Chris@16
|
62
|
Chris@16
|
63 // not a container and not a fusion sequence
|
Chris@16
|
64 template <typename T_>
|
Chris@16
|
65 static type call(T_ const& t, mpl::false_, mpl::false_)
|
Chris@16
|
66 {
|
Chris@16
|
67 return t;
|
Chris@16
|
68 }
|
Chris@16
|
69
|
Chris@16
|
70 static type call(T const& t)
|
Chris@16
|
71 {
|
Chris@16
|
72 typedef typename traits::is_container<T>::type is_container;
|
Chris@16
|
73 typedef typename fusion::traits::is_sequence<T>::type is_sequence;
|
Chris@16
|
74
|
Chris@16
|
75 return call(t, is_container(), is_sequence());
|
Chris@16
|
76 }
|
Chris@16
|
77 };
|
Chris@16
|
78
|
Chris@16
|
79 template <typename Attribute>
|
Chris@16
|
80 struct symbols_lookup<Attribute, Attribute>
|
Chris@16
|
81 {
|
Chris@16
|
82 typedef Attribute const& type;
|
Chris@16
|
83
|
Chris@16
|
84 static type call(Attribute const& t)
|
Chris@16
|
85 {
|
Chris@16
|
86 return t;
|
Chris@16
|
87 }
|
Chris@16
|
88 };
|
Chris@16
|
89
|
Chris@16
|
90 template <typename Attribute, typename T, typename Enable>
|
Chris@16
|
91 struct symbols_value
|
Chris@16
|
92 {
|
Chris@16
|
93 typedef
|
Chris@16
|
94 mpl::eval_if<fusion::traits::is_sequence<T>
|
Chris@16
|
95 , traits::detail::value_at_c<T, 1>
|
Chris@16
|
96 , mpl::identity<unused_type> > sequence_type;
|
Chris@16
|
97 typedef typename
|
Chris@16
|
98 mpl::eval_if<traits::is_container<T>
|
Chris@16
|
99 , traits::container_value<T>
|
Chris@16
|
100 , sequence_type>::type type;
|
Chris@16
|
101
|
Chris@16
|
102 // fusion sequence
|
Chris@16
|
103 template <typename T_>
|
Chris@16
|
104 static type call(T_ const& t, mpl::false_, mpl::true_)
|
Chris@16
|
105 {
|
Chris@16
|
106 return fusion::at_c<1>(t);
|
Chris@16
|
107 }
|
Chris@16
|
108
|
Chris@16
|
109 // container
|
Chris@16
|
110 template <typename T_, typename IsSequence>
|
Chris@16
|
111 static type call(T_ const& t, mpl::true_, IsSequence)
|
Chris@16
|
112 {
|
Chris@16
|
113 return t[1];
|
Chris@16
|
114 }
|
Chris@16
|
115
|
Chris@16
|
116 // not a container nor a fusion sequence
|
Chris@16
|
117 template <typename T_>
|
Chris@16
|
118 static type call(T_ const&, mpl::false_, mpl::false_)
|
Chris@16
|
119 {
|
Chris@16
|
120 return unused;
|
Chris@16
|
121 }
|
Chris@16
|
122
|
Chris@16
|
123 static type call(T const& t)
|
Chris@16
|
124 {
|
Chris@16
|
125 typedef typename traits::is_container<T>::type is_container;
|
Chris@16
|
126 typedef typename fusion::traits::is_sequence<T>::type is_sequence;
|
Chris@16
|
127
|
Chris@16
|
128 return call(t, is_container(), is_sequence());
|
Chris@16
|
129 }
|
Chris@16
|
130 };
|
Chris@16
|
131
|
Chris@16
|
132 template <typename Attribute>
|
Chris@16
|
133 struct symbols_value<Attribute, Attribute>
|
Chris@16
|
134 {
|
Chris@16
|
135 typedef unused_type type;
|
Chris@16
|
136
|
Chris@16
|
137 static type call(Attribute const&)
|
Chris@16
|
138 {
|
Chris@16
|
139 return unused;
|
Chris@16
|
140 }
|
Chris@16
|
141 };
|
Chris@16
|
142 }}}
|
Chris@16
|
143
|
Chris@16
|
144 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
145 namespace boost { namespace spirit { namespace karma
|
Chris@16
|
146 {
|
Chris@16
|
147 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
148 template <typename T, typename Attribute>
|
Chris@16
|
149 struct symbols_lookup
|
Chris@16
|
150 : mpl::if_<
|
Chris@16
|
151 traits::not_is_unused<T>
|
Chris@16
|
152 , std::map<Attribute, T>
|
Chris@16
|
153 , std::set<Attribute>
|
Chris@16
|
154 >
|
Chris@16
|
155 {};
|
Chris@16
|
156
|
Chris@16
|
157 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
158 namespace detail
|
Chris@16
|
159 {
|
Chris@16
|
160 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
161 template <typename CharEncoding, typename Tag>
|
Chris@16
|
162 struct generate_encoded
|
Chris@16
|
163 {
|
Chris@16
|
164 typedef typename
|
Chris@16
|
165 proto::terminal<tag::char_code<Tag, CharEncoding> >::type
|
Chris@16
|
166 encoding_type;
|
Chris@16
|
167
|
Chris@16
|
168 template <typename OutputIterator, typename Expr, typename Attribute>
|
Chris@16
|
169 static bool call(OutputIterator& sink, Expr const& expr
|
Chris@16
|
170 , Attribute const& attr)
|
Chris@16
|
171 {
|
Chris@16
|
172 encoding_type const encoding = encoding_type();
|
Chris@16
|
173 return karma::generate(sink, encoding[expr], attr);
|
Chris@16
|
174 }
|
Chris@16
|
175 };
|
Chris@16
|
176
|
Chris@16
|
177 template <>
|
Chris@16
|
178 struct generate_encoded<unused_type, unused_type>
|
Chris@16
|
179 {
|
Chris@16
|
180 template <typename OutputIterator, typename Expr, typename Attribute>
|
Chris@16
|
181 static bool call(OutputIterator& sink, Expr const& expr
|
Chris@16
|
182 , Attribute const& attr)
|
Chris@16
|
183 {
|
Chris@16
|
184 return karma::generate(sink, expr, attr);
|
Chris@16
|
185 }
|
Chris@16
|
186 };
|
Chris@16
|
187 }
|
Chris@16
|
188
|
Chris@16
|
189 template <
|
Chris@16
|
190 typename Attribute = char, typename T = unused_type
|
Chris@16
|
191 , typename Lookup = typename symbols_lookup<T, Attribute>::type
|
Chris@16
|
192 , typename CharEncoding = unused_type, typename Tag = unused_type>
|
Chris@16
|
193 struct symbols
|
Chris@16
|
194 : proto::extends<
|
Chris@16
|
195 typename proto::terminal<
|
Chris@16
|
196 reference<symbols<Attribute, T, Lookup, CharEncoding, Tag> >
|
Chris@16
|
197 >::type
|
Chris@16
|
198 , symbols<Attribute, T, Lookup, CharEncoding, Tag> >
|
Chris@16
|
199 , primitive_generator<
|
Chris@16
|
200 symbols<Attribute, T, Lookup, CharEncoding, Tag> >
|
Chris@16
|
201 {
|
Chris@16
|
202 typedef T value_type; // the value associated with each entry
|
Chris@16
|
203
|
Chris@16
|
204 typedef reference<symbols> reference_;
|
Chris@16
|
205 typedef typename proto::terminal<reference_>::type terminal;
|
Chris@16
|
206 typedef proto::extends<terminal, symbols> base_type;
|
Chris@16
|
207
|
Chris@16
|
208 template <typename Context, typename Unused>
|
Chris@16
|
209 struct attribute
|
Chris@16
|
210 {
|
Chris@16
|
211 typedef Attribute type;
|
Chris@16
|
212 };
|
Chris@16
|
213
|
Chris@16
|
214 symbols(std::string const& name = "symbols")
|
Chris@16
|
215 : base_type(terminal::make(reference_(*this)))
|
Chris@16
|
216 , add(*this)
|
Chris@16
|
217 , remove(*this)
|
Chris@16
|
218 , lookup(new Lookup())
|
Chris@16
|
219 , name_(name)
|
Chris@16
|
220 {}
|
Chris@16
|
221
|
Chris@16
|
222 symbols(symbols const& syms)
|
Chris@16
|
223 : base_type(terminal::make(reference_(*this)))
|
Chris@16
|
224 , add(*this)
|
Chris@16
|
225 , remove(*this)
|
Chris@16
|
226 , lookup(syms.lookup)
|
Chris@16
|
227 , name_(syms.name_)
|
Chris@16
|
228 {}
|
Chris@16
|
229
|
Chris@16
|
230 template <typename CharEncoding_, typename Tag_>
|
Chris@16
|
231 symbols(symbols<Attribute, T, Lookup, CharEncoding_, Tag_> const& syms)
|
Chris@16
|
232 : base_type(terminal::make(reference_(*this)))
|
Chris@16
|
233 , add(*this)
|
Chris@16
|
234 , remove(*this)
|
Chris@16
|
235 , lookup(syms.lookup)
|
Chris@16
|
236 , name_(syms.name_)
|
Chris@16
|
237 {}
|
Chris@16
|
238
|
Chris@16
|
239 template <typename Symbols, typename Data>
|
Chris@16
|
240 symbols(Symbols const& syms, Data const& data
|
Chris@16
|
241 , std::string const& name = "symbols")
|
Chris@16
|
242 : base_type(terminal::make(reference_(*this)))
|
Chris@16
|
243 , add(*this)
|
Chris@16
|
244 , remove(*this)
|
Chris@16
|
245 , lookup(new Lookup())
|
Chris@16
|
246 , name_(name)
|
Chris@16
|
247 {
|
Chris@16
|
248 typename range_const_iterator<Symbols>::type si = boost::begin(syms);
|
Chris@16
|
249 typename range_const_iterator<Data>::type di = boost::begin(data);
|
Chris@16
|
250 while (si != boost::end(syms))
|
Chris@16
|
251 add(*si++, *di++);
|
Chris@16
|
252 }
|
Chris@16
|
253
|
Chris@16
|
254 symbols&
|
Chris@16
|
255 operator=(symbols const& rhs)
|
Chris@16
|
256 {
|
Chris@16
|
257 *lookup = *rhs.lookup;
|
Chris@16
|
258 name_ = rhs.name_;
|
Chris@16
|
259 return *this;
|
Chris@16
|
260 }
|
Chris@16
|
261
|
Chris@16
|
262 template <typename CharEncoding_, typename Tag_>
|
Chris@16
|
263 symbols&
|
Chris@16
|
264 operator=(symbols<Attribute, T, Lookup, CharEncoding_, Tag_> const& rhs)
|
Chris@16
|
265 {
|
Chris@16
|
266 *lookup = *rhs.lookup;
|
Chris@16
|
267 name_ = rhs.name_;
|
Chris@16
|
268 return *this;
|
Chris@16
|
269 }
|
Chris@16
|
270
|
Chris@16
|
271 void clear()
|
Chris@16
|
272 {
|
Chris@16
|
273 lookup->clear();
|
Chris@16
|
274 }
|
Chris@16
|
275
|
Chris@16
|
276 struct adder;
|
Chris@16
|
277 struct remover;
|
Chris@16
|
278
|
Chris@16
|
279 template <typename Attr, typename T_>
|
Chris@16
|
280 adder const&
|
Chris@16
|
281 operator=(std::pair<Attr, T_> const& p)
|
Chris@16
|
282 {
|
Chris@16
|
283 lookup->clear();
|
Chris@16
|
284 return add(p.first, p.second);
|
Chris@16
|
285 }
|
Chris@16
|
286
|
Chris@16
|
287 template <typename Attr, typename T_>
|
Chris@16
|
288 friend adder const&
|
Chris@16
|
289 operator+= (symbols& sym, std::pair<Attr, T_> const& p)
|
Chris@16
|
290 {
|
Chris@16
|
291 return sym.add(p.first, p.second);
|
Chris@16
|
292 }
|
Chris@16
|
293
|
Chris@16
|
294 template <typename Attr>
|
Chris@16
|
295 friend remover const&
|
Chris@16
|
296 operator-= (symbols& sym, Attr const& attr)
|
Chris@16
|
297 {
|
Chris@16
|
298 return sym.remove(attr);
|
Chris@16
|
299 }
|
Chris@16
|
300
|
Chris@16
|
301 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@16
|
302 // non-const version needed to suppress proto's += kicking in
|
Chris@16
|
303 template <typename Attr, typename T_>
|
Chris@16
|
304 friend adder const&
|
Chris@16
|
305 operator+= (symbols& sym, std::pair<Attr, T_>& p)
|
Chris@16
|
306 {
|
Chris@16
|
307 return sym.add(p.first, p.second);
|
Chris@16
|
308 }
|
Chris@16
|
309
|
Chris@16
|
310 // non-const version needed to suppress proto's -= kicking in
|
Chris@16
|
311 template <typename Attr>
|
Chris@16
|
312 friend remover const&
|
Chris@16
|
313 operator-= (symbols& sym, Attr& attr)
|
Chris@16
|
314 {
|
Chris@16
|
315 return sym.remove(attr);
|
Chris@16
|
316 }
|
Chris@16
|
317 #else
|
Chris@16
|
318 // for rvalue references
|
Chris@16
|
319 template <typename Attr, typename T_>
|
Chris@16
|
320 friend adder const&
|
Chris@16
|
321 operator+= (symbols& sym, std::pair<Attr, T_>&& p)
|
Chris@16
|
322 {
|
Chris@16
|
323 return sym.add(p.first, p.second);
|
Chris@16
|
324 }
|
Chris@16
|
325
|
Chris@16
|
326 // for rvalue references
|
Chris@16
|
327 template <typename Attr>
|
Chris@16
|
328 friend remover const&
|
Chris@16
|
329 operator-= (symbols& sym, Attr&& attr)
|
Chris@16
|
330 {
|
Chris@16
|
331 return sym.remove(attr);
|
Chris@16
|
332 }
|
Chris@16
|
333 #endif
|
Chris@16
|
334 template <typename F>
|
Chris@16
|
335 void for_each(F f) const
|
Chris@16
|
336 {
|
Chris@16
|
337 std::for_each(lookup->begin(), lookup->end(), f);
|
Chris@16
|
338 }
|
Chris@16
|
339
|
Chris@16
|
340 template <typename Attr>
|
Chris@16
|
341 value_type* find(Attr const& attr)
|
Chris@16
|
342 {
|
Chris@16
|
343 typename Lookup::iterator it = lookup->find(attr);
|
Chris@16
|
344 return (it != lookup->end()) ? &(*it).second : 0;
|
Chris@16
|
345 }
|
Chris@16
|
346
|
Chris@16
|
347 template <typename Attr>
|
Chris@16
|
348 value_type& at(Attr const& attr)
|
Chris@16
|
349 {
|
Chris@16
|
350 return (*lookup)[attr];
|
Chris@16
|
351 }
|
Chris@16
|
352
|
Chris@16
|
353 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
354 template <typename OutputIterator, typename Context, typename Delimiter
|
Chris@16
|
355 , typename Attr>
|
Chris@16
|
356 bool generate(OutputIterator& sink, Context&, Delimiter const& d
|
Chris@16
|
357 , Attr const& attr) const
|
Chris@16
|
358 {
|
Chris@16
|
359 typename Lookup::iterator it = lookup->find(
|
Chris@16
|
360 traits::symbols_lookup<Attr, Attribute>::call(attr));
|
Chris@16
|
361 if (it == lookup->end())
|
Chris@16
|
362 return false;
|
Chris@16
|
363
|
Chris@16
|
364 return karma::detail::generate_encoded<CharEncoding, Tag>::call(
|
Chris@16
|
365 sink, (*it).second
|
Chris@16
|
366 , traits::symbols_value<Attribute, Attr>::call(attr)) &&
|
Chris@16
|
367 karma::delimit_out(sink, d);
|
Chris@16
|
368 }
|
Chris@16
|
369
|
Chris@16
|
370 template <typename Context>
|
Chris@16
|
371 info what(Context&) const
|
Chris@16
|
372 {
|
Chris@16
|
373 return info(name_);
|
Chris@16
|
374 }
|
Chris@16
|
375
|
Chris@16
|
376 void name(std::string const &str)
|
Chris@16
|
377 {
|
Chris@16
|
378 name_ = str;
|
Chris@16
|
379 }
|
Chris@16
|
380 std::string const &name() const
|
Chris@16
|
381 {
|
Chris@16
|
382 return name_;
|
Chris@16
|
383 }
|
Chris@16
|
384
|
Chris@16
|
385 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
386 struct adder
|
Chris@16
|
387 {
|
Chris@16
|
388 template <typename, typename = unused_type>
|
Chris@16
|
389 struct result { typedef adder const& type; };
|
Chris@16
|
390
|
Chris@16
|
391 adder(symbols& sym)
|
Chris@16
|
392 : sym(sym)
|
Chris@16
|
393 {
|
Chris@16
|
394 }
|
Chris@16
|
395
|
Chris@16
|
396 template <typename Attr>
|
Chris@16
|
397 adder const&
|
Chris@16
|
398 operator()(Attr const& attr, T const& val = T()) const
|
Chris@16
|
399 {
|
Chris@16
|
400 sym.lookup->insert(typename Lookup::value_type(attr, val));
|
Chris@16
|
401 return *this;
|
Chris@16
|
402 }
|
Chris@16
|
403
|
Chris@16
|
404 template <typename Attr>
|
Chris@16
|
405 adder const&
|
Chris@16
|
406 operator, (Attr const& attr) const
|
Chris@16
|
407 {
|
Chris@16
|
408 sym.lookup->insert(typename Lookup::value_type(attr, T()));
|
Chris@16
|
409 return *this;
|
Chris@16
|
410 }
|
Chris@16
|
411
|
Chris@16
|
412 symbols& sym;
|
Chris@16
|
413
|
Chris@16
|
414 private:
|
Chris@16
|
415 // silence MSVC warning C4512: assignment operator could not be generated
|
Chris@16
|
416 adder& operator= (adder const&);
|
Chris@16
|
417 };
|
Chris@16
|
418
|
Chris@16
|
419 struct remover
|
Chris@16
|
420 {
|
Chris@16
|
421 template <typename>
|
Chris@16
|
422 struct result { typedef remover const& type; };
|
Chris@16
|
423
|
Chris@16
|
424 remover(symbols& sym)
|
Chris@16
|
425 : sym(sym)
|
Chris@16
|
426 {
|
Chris@16
|
427 }
|
Chris@16
|
428
|
Chris@16
|
429 template <typename Attr>
|
Chris@16
|
430 remover const&
|
Chris@16
|
431 operator()(Attr const& attr) const
|
Chris@16
|
432 {
|
Chris@16
|
433 sym.lookup->erase(attr);
|
Chris@16
|
434 return *this;
|
Chris@16
|
435 }
|
Chris@16
|
436
|
Chris@16
|
437 template <typename Attr>
|
Chris@16
|
438 remover const&
|
Chris@16
|
439 operator, (Attr const& attr) const
|
Chris@16
|
440 {
|
Chris@16
|
441 sym.lookup->erase(attr);
|
Chris@16
|
442 return *this;
|
Chris@16
|
443 }
|
Chris@16
|
444
|
Chris@16
|
445 symbols& sym;
|
Chris@16
|
446
|
Chris@16
|
447 private:
|
Chris@16
|
448 // silence MSVC warning C4512: assignment operator could not be generated
|
Chris@16
|
449 remover& operator= (remover const&);
|
Chris@16
|
450 };
|
Chris@16
|
451
|
Chris@16
|
452 adder add;
|
Chris@16
|
453 remover remove;
|
Chris@16
|
454 shared_ptr<Lookup> lookup;
|
Chris@16
|
455 std::string name_;
|
Chris@16
|
456 };
|
Chris@16
|
457
|
Chris@16
|
458 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
459 // specialization for unused stored type
|
Chris@16
|
460 template <
|
Chris@16
|
461 typename Attribute, typename Lookup
|
Chris@16
|
462 , typename CharEncoding, typename Tag>
|
Chris@16
|
463 struct symbols<Attribute, unused_type, Lookup, CharEncoding, Tag>
|
Chris@16
|
464 : proto::extends<
|
Chris@16
|
465 typename proto::terminal<
|
Chris@16
|
466 spirit::karma::reference<
|
Chris@16
|
467 symbols<Attribute, unused_type, Lookup, CharEncoding, Tag> >
|
Chris@16
|
468 >::type
|
Chris@16
|
469 , symbols<Attribute, unused_type, Lookup, CharEncoding, Tag>
|
Chris@16
|
470 >
|
Chris@16
|
471 , spirit::karma::generator<
|
Chris@16
|
472 symbols<Attribute, unused_type, Lookup, CharEncoding, Tag> >
|
Chris@16
|
473 {
|
Chris@16
|
474 typedef unused_type value_type; // the value associated with each entry
|
Chris@16
|
475
|
Chris@16
|
476 typedef spirit::karma::reference<symbols> reference_;
|
Chris@16
|
477 typedef typename proto::terminal<reference_>::type terminal;
|
Chris@16
|
478 typedef proto::extends<terminal, symbols> base_type;
|
Chris@16
|
479
|
Chris@16
|
480 template <typename Context, typename Unused>
|
Chris@16
|
481 struct attribute
|
Chris@16
|
482 {
|
Chris@16
|
483 typedef Attribute type;
|
Chris@16
|
484 };
|
Chris@16
|
485
|
Chris@16
|
486 symbols(std::string const& name = "symbols")
|
Chris@16
|
487 : base_type(terminal::make(reference_(*this)))
|
Chris@16
|
488 , add(*this)
|
Chris@16
|
489 , remove(*this)
|
Chris@16
|
490 , lookup(new Lookup())
|
Chris@16
|
491 , name_(name)
|
Chris@16
|
492 {}
|
Chris@16
|
493
|
Chris@16
|
494 symbols(symbols const& syms)
|
Chris@16
|
495 : base_type(terminal::make(reference_(*this)))
|
Chris@16
|
496 , add(*this)
|
Chris@16
|
497 , remove(*this)
|
Chris@16
|
498 , lookup(syms.lookup)
|
Chris@16
|
499 , name_(syms.name_)
|
Chris@16
|
500 {}
|
Chris@16
|
501
|
Chris@16
|
502 template <typename CharEncoding_, typename Tag_>
|
Chris@16
|
503 symbols(symbols<Attribute, unused_type, Lookup, CharEncoding_, Tag_> const& syms)
|
Chris@16
|
504 : base_type(terminal::make(reference_(*this)))
|
Chris@16
|
505 , add(*this)
|
Chris@16
|
506 , remove(*this)
|
Chris@16
|
507 , lookup(syms.lookup)
|
Chris@16
|
508 , name_(syms.name_)
|
Chris@16
|
509 {}
|
Chris@16
|
510
|
Chris@16
|
511 template <typename Symbols, typename Data>
|
Chris@16
|
512 symbols(Symbols const& syms, Data const& data
|
Chris@16
|
513 , std::string const& name = "symbols")
|
Chris@16
|
514 : base_type(terminal::make(reference_(*this)))
|
Chris@16
|
515 , add(*this)
|
Chris@16
|
516 , remove(*this)
|
Chris@16
|
517 , lookup(new Lookup())
|
Chris@16
|
518 , name_(name)
|
Chris@16
|
519 {
|
Chris@16
|
520 typename range_const_iterator<Symbols>::type si = boost::begin(syms);
|
Chris@16
|
521 typename range_const_iterator<Data>::type di = boost::begin(data);
|
Chris@16
|
522 while (si != boost::end(syms))
|
Chris@16
|
523 add(*si++, *di++);
|
Chris@16
|
524 }
|
Chris@16
|
525
|
Chris@16
|
526 symbols&
|
Chris@16
|
527 operator=(symbols const& rhs)
|
Chris@16
|
528 {
|
Chris@16
|
529 *lookup = *rhs.lookup;
|
Chris@16
|
530 name_ = rhs.name_;
|
Chris@16
|
531 return *this;
|
Chris@16
|
532 }
|
Chris@16
|
533
|
Chris@16
|
534 template <typename CharEncoding_, typename Tag_>
|
Chris@16
|
535 symbols&
|
Chris@16
|
536 operator=(symbols<Attribute, unused_type, Lookup, CharEncoding_, Tag_> const& rhs)
|
Chris@16
|
537 {
|
Chris@16
|
538 *lookup = *rhs.lookup;
|
Chris@16
|
539 name_ = rhs.name_;
|
Chris@16
|
540 return *this;
|
Chris@16
|
541 }
|
Chris@16
|
542
|
Chris@16
|
543 void clear()
|
Chris@16
|
544 {
|
Chris@16
|
545 lookup->clear();
|
Chris@16
|
546 }
|
Chris@16
|
547
|
Chris@16
|
548 struct adder;
|
Chris@16
|
549 struct remover;
|
Chris@16
|
550
|
Chris@16
|
551 template <typename Attr>
|
Chris@16
|
552 adder const&
|
Chris@16
|
553 operator=(Attr const& attr)
|
Chris@16
|
554 {
|
Chris@16
|
555 lookup->clear();
|
Chris@16
|
556 return add(attr);
|
Chris@16
|
557 }
|
Chris@16
|
558
|
Chris@16
|
559 template <typename Attr>
|
Chris@16
|
560 friend adder const&
|
Chris@16
|
561 operator+= (symbols& sym, Attr const& attr)
|
Chris@16
|
562 {
|
Chris@16
|
563 return sym.add(attr);
|
Chris@16
|
564 }
|
Chris@16
|
565
|
Chris@16
|
566 template <typename Attr>
|
Chris@16
|
567 friend remover const&
|
Chris@16
|
568 operator-= (symbols& sym, Attr const& attr)
|
Chris@16
|
569 {
|
Chris@16
|
570 return sym.remove(attr);
|
Chris@16
|
571 }
|
Chris@16
|
572
|
Chris@16
|
573 // non-const version needed to suppress proto's += kicking in
|
Chris@16
|
574 template <typename Attr>
|
Chris@16
|
575 friend adder const&
|
Chris@16
|
576 operator+= (symbols& sym, Attr& attr)
|
Chris@16
|
577 {
|
Chris@16
|
578 return sym.add(attr);
|
Chris@16
|
579 }
|
Chris@16
|
580
|
Chris@16
|
581 // non-const version needed to suppress proto's -= kicking in
|
Chris@16
|
582 template <typename Attr>
|
Chris@16
|
583 friend remover const&
|
Chris@16
|
584 operator-= (symbols& sym, Attr& attr)
|
Chris@16
|
585 {
|
Chris@16
|
586 return sym.remove(attr);
|
Chris@16
|
587 }
|
Chris@16
|
588
|
Chris@16
|
589 template <typename F>
|
Chris@16
|
590 void for_each(F f) const
|
Chris@16
|
591 {
|
Chris@16
|
592 std::for_each(lookup->begin(), lookup->end(), f);
|
Chris@16
|
593 }
|
Chris@16
|
594
|
Chris@16
|
595 template <typename Attr>
|
Chris@16
|
596 value_type const* find(Attr const& attr)
|
Chris@16
|
597 {
|
Chris@16
|
598 typename Lookup::iterator it = lookup->find(attr);
|
Chris@16
|
599 return (it != lookup->end()) ? &unused : 0;
|
Chris@16
|
600 }
|
Chris@16
|
601
|
Chris@16
|
602 template <typename Attr>
|
Chris@16
|
603 value_type at(Attr const& attr)
|
Chris@16
|
604 {
|
Chris@16
|
605 typename Lookup::iterator it = lookup->find(attr);
|
Chris@16
|
606 if (it == lookup->end())
|
Chris@16
|
607 add(attr);
|
Chris@16
|
608 return unused;
|
Chris@16
|
609 }
|
Chris@16
|
610
|
Chris@16
|
611 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
612 template <typename OutputIterator, typename Context, typename Delimiter
|
Chris@16
|
613 , typename Attr>
|
Chris@16
|
614 bool generate(OutputIterator& sink, Context&, Delimiter const& d
|
Chris@16
|
615 , Attr const& attr) const
|
Chris@16
|
616 {
|
Chris@16
|
617 typename Lookup::iterator it = lookup->find(
|
Chris@16
|
618 traits::symbols_lookup<Attr, Attribute>::call(attr));
|
Chris@16
|
619 if (it == lookup->end())
|
Chris@16
|
620 return false;
|
Chris@16
|
621
|
Chris@16
|
622 return karma::detail::generate_encoded<CharEncoding, Tag>::
|
Chris@16
|
623 call(sink
|
Chris@16
|
624 , traits::symbols_lookup<Attr, Attribute>::call(attr)
|
Chris@16
|
625 , unused) &&
|
Chris@16
|
626 karma::delimit_out(sink, d);
|
Chris@16
|
627 }
|
Chris@16
|
628
|
Chris@16
|
629 template <typename Context>
|
Chris@16
|
630 info what(Context&) const
|
Chris@16
|
631 {
|
Chris@16
|
632 return info(name_);
|
Chris@16
|
633 }
|
Chris@16
|
634
|
Chris@16
|
635 void name(std::string const &str)
|
Chris@16
|
636 {
|
Chris@16
|
637 name_ = str;
|
Chris@16
|
638 }
|
Chris@16
|
639 std::string const &name() const
|
Chris@16
|
640 {
|
Chris@16
|
641 return name_;
|
Chris@16
|
642 }
|
Chris@16
|
643
|
Chris@16
|
644 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
645 struct adder
|
Chris@16
|
646 {
|
Chris@16
|
647 template <typename, typename = unused_type>
|
Chris@16
|
648 struct result { typedef adder const& type; };
|
Chris@16
|
649
|
Chris@16
|
650 adder(symbols& sym)
|
Chris@16
|
651 : sym(sym)
|
Chris@16
|
652 {
|
Chris@16
|
653 }
|
Chris@16
|
654
|
Chris@16
|
655 template <typename Attr>
|
Chris@16
|
656 adder const&
|
Chris@16
|
657 operator()(Attr const& attr) const
|
Chris@16
|
658 {
|
Chris@16
|
659 sym.lookup->insert(attr);
|
Chris@16
|
660 return *this;
|
Chris@16
|
661 }
|
Chris@16
|
662
|
Chris@16
|
663 template <typename Attr>
|
Chris@16
|
664 adder const&
|
Chris@16
|
665 operator, (Attr const& attr) const
|
Chris@16
|
666 {
|
Chris@16
|
667 sym.lookup->insert(attr);
|
Chris@16
|
668 return *this;
|
Chris@16
|
669 }
|
Chris@16
|
670
|
Chris@16
|
671 symbols& sym;
|
Chris@16
|
672
|
Chris@16
|
673 private:
|
Chris@16
|
674 // silence MSVC warning C4512: assignment operator could not be generated
|
Chris@16
|
675 adder& operator= (adder const&);
|
Chris@16
|
676 };
|
Chris@16
|
677
|
Chris@16
|
678 struct remover
|
Chris@16
|
679 {
|
Chris@16
|
680 template <typename>
|
Chris@16
|
681 struct result { typedef remover const& type; };
|
Chris@16
|
682
|
Chris@16
|
683 remover(symbols& sym)
|
Chris@16
|
684 : sym(sym)
|
Chris@16
|
685 {
|
Chris@16
|
686 }
|
Chris@16
|
687
|
Chris@16
|
688 template <typename Attr>
|
Chris@16
|
689 remover const&
|
Chris@16
|
690 operator()(Attr const& attr) const
|
Chris@16
|
691 {
|
Chris@16
|
692 sym.lookup->erase(attr);
|
Chris@16
|
693 return *this;
|
Chris@16
|
694 }
|
Chris@16
|
695
|
Chris@16
|
696 template <typename Attr>
|
Chris@16
|
697 remover const&
|
Chris@16
|
698 operator, (Attr const& attr) const
|
Chris@16
|
699 {
|
Chris@16
|
700 sym.lookup->erase(attr);
|
Chris@16
|
701 return *this;
|
Chris@16
|
702 }
|
Chris@16
|
703
|
Chris@16
|
704 symbols& sym;
|
Chris@16
|
705
|
Chris@16
|
706 private:
|
Chris@16
|
707 // silence MSVC warning C4512: assignment operator could not be generated
|
Chris@16
|
708 remover& operator= (remover const&);
|
Chris@16
|
709 };
|
Chris@16
|
710
|
Chris@16
|
711 adder add;
|
Chris@16
|
712 remover remove;
|
Chris@16
|
713 shared_ptr<Lookup> lookup;
|
Chris@16
|
714 std::string name_;
|
Chris@16
|
715 };
|
Chris@16
|
716
|
Chris@16
|
717 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
718 // Generator generators: make_xxx function (objects)
|
Chris@16
|
719 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
720 template <typename Attribute, typename T, typename Lookup
|
Chris@16
|
721 , typename CharEnconding, typename Tag, typename Modifiers>
|
Chris@16
|
722 struct make_primitive<
|
Chris@16
|
723 reference<symbols<Attribute, T, Lookup, CharEnconding, Tag> >
|
Chris@16
|
724 , Modifiers>
|
Chris@16
|
725 {
|
Chris@16
|
726 static bool const lower =
|
Chris@16
|
727 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
|
Chris@16
|
728 static bool const upper =
|
Chris@16
|
729 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
|
Chris@16
|
730
|
Chris@16
|
731 typedef reference<
|
Chris@16
|
732 symbols<Attribute, T, Lookup, CharEnconding, Tag>
|
Chris@16
|
733 > reference_;
|
Chris@16
|
734
|
Chris@16
|
735 typedef typename mpl::if_c<
|
Chris@16
|
736 lower || upper
|
Chris@16
|
737 , symbols<
|
Chris@16
|
738 Attribute, T, Lookup
|
Chris@16
|
739 , typename spirit::detail::get_encoding_with_case<
|
Chris@16
|
740 Modifiers, unused_type, lower || upper>::type
|
Chris@16
|
741 , typename detail::get_casetag<Modifiers, lower || upper>::type>
|
Chris@16
|
742 , reference_>::type
|
Chris@16
|
743 result_type;
|
Chris@16
|
744
|
Chris@16
|
745 result_type operator()(reference_ ref, unused_type) const
|
Chris@16
|
746 {
|
Chris@16
|
747 return result_type(ref.ref.get());
|
Chris@16
|
748 }
|
Chris@16
|
749 };
|
Chris@16
|
750 }}}
|
Chris@16
|
751
|
Chris@16
|
752 namespace boost { namespace spirit { namespace traits
|
Chris@16
|
753 {
|
Chris@16
|
754 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
755 template <typename Attribute, typename T, typename Lookup
|
Chris@16
|
756 , typename CharEncoding, typename Tag
|
Chris@16
|
757 , typename Attr, typename Context, typename Iterator>
|
Chris@16
|
758 struct handles_container<karma::symbols<Attribute, T, Lookup, CharEncoding, Tag>
|
Chris@16
|
759 , Attr, Context, Iterator>
|
Chris@16
|
760 : traits::is_container<Attr> {};
|
Chris@16
|
761 }}}
|
Chris@16
|
762
|
Chris@16
|
763 #if defined(BOOST_MSVC)
|
Chris@16
|
764 # pragma warning(pop)
|
Chris@16
|
765 #endif
|
Chris@16
|
766
|
Chris@16
|
767 #endif
|
Chris@16
|
768
|