Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / spirit / home / qi / string / symbols.hpp
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