1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
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
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>
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>
32 #if defined(BOOST_MSVC)
33 # pragma warning(push)
34 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
37 namespace boost { namespace spirit { namespace qi
41 , typename T = unused_type
42 , typename Lookup = tst<Char, T>
43 , typename Filter = tst_pass_through>
46 typename proto::terminal<
47 reference<symbols<Char, T, Lookup, Filter> >
49 , symbols<Char, T, Lookup, Filter>
51 , primitive_parser<symbols<Char, T, Lookup, Filter> >
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;
60 template <typename Context, typename Iterator>
63 typedef value_type type;
66 symbols(std::string const& name = "symbols")
67 : base_type(terminal::make(reference_(*this)))
70 , lookup(new Lookup())
75 symbols(symbols const& syms)
76 : base_type(terminal::make(reference_(*this)))
84 template <typename Filter_>
85 symbols(symbols<Char, T, Lookup, Filter_> const& syms)
86 : base_type(terminal::make(reference_(*this)))
94 template <typename Symbols>
95 symbols(Symbols const& syms, std::string const& name = "symbols")
96 : base_type(terminal::make(reference_(*this)))
99 , lookup(new Lookup())
102 typename range_const_iterator<Symbols>::type si = boost::begin(syms);
103 while (si != boost::end(syms))
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)))
113 , lookup(new Lookup())
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))
123 operator=(symbols const& rhs)
126 *lookup = *rhs.lookup;
130 template <typename Filter_>
132 operator=(symbols<Char, T, Lookup, Filter_> const& rhs)
135 *lookup = *rhs.lookup;
147 template <typename Str>
149 operator=(Str const& str)
155 template <typename Str>
157 operator+=(symbols& sym, Str const& str)
162 template <typename Str>
163 friend remover const&
164 operator-=(symbols& sym, Str const& str)
166 return sym.remove(str);
169 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
170 // non-const version needed to suppress proto's += kicking in
171 template <typename Str>
173 operator+=(symbols& sym, Str& str)
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)
183 return sym.remove(str);
186 // for rvalue references
187 template <typename Str>
189 operator+=(symbols& sym, Str&& str)
194 // for rvalue references
195 template <typename Str>
196 friend remover const&
197 operator-=(symbols& sym, Str&& str)
199 return sym.remove(str);
202 template <typename F>
203 void for_each(F f) const
208 template <typename Str>
209 value_type& at(Str const& str)
211 return *lookup->add(traits::get_begin<Char>(str)
212 , traits::get_end<Char>(str), T());
215 template <typename Iterator>
216 value_type* prefix_find(Iterator& first, Iterator const& last)
218 return lookup->find(first, last, Filter());
221 template <typename Iterator>
222 value_type const* prefix_find(Iterator& first, Iterator const& last) const
224 return lookup->find(first, last, Filter());
227 template <typename Str>
228 value_type* find(Str const& str)
230 return find_impl(traits::get_begin<Char>(str)
231 , traits::get_end<Char>(str));
234 template <typename Str>
235 value_type const* find(Str const& str) const
237 return find_impl(traits::get_begin<Char>(str)
238 , traits::get_end<Char>(str));
242 template <typename Iterator>
243 value_type* find_impl(Iterator begin, Iterator end)
245 value_type* r = lookup->find(begin, end, Filter());
246 return begin == end ? r : 0;
249 template <typename Iterator>
250 value_type const* find_impl(Iterator begin, Iterator end) const
252 value_type const* r = lookup->find(begin, end, Filter());
253 return begin == end ? r : 0;
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
262 qi::skip_over(first, last, skipper);
264 if (value_type* val_ptr
265 = lookup->find(first, last, Filter()))
267 spirit::traits::assign_to(*val_ptr, attr_);
273 template <typename Context>
274 info what(Context& /*context*/) const
279 void name(std::string const &str)
283 std::string const &name() const
290 template <typename, typename = unused_type, typename = unused_type>
291 struct result { typedef adder const& type; };
298 template <typename Iterator>
300 operator()(Iterator const& first, Iterator const& last, T const& val) const
302 sym.lookup->add(first, last, val);
306 template <typename Str>
308 operator()(Str const& s, T const& val = T()) const
310 sym.lookup->add(traits::get_begin<Char>(s)
311 , traits::get_end<Char>(s), val);
315 template <typename Str>
317 operator,(Str const& s) const
319 sym.lookup->add(traits::get_begin<Char>(s)
320 , traits::get_end<Char>(s), T());
327 // silence MSVC warning C4512: assignment operator could not be generated
328 adder& operator= (adder const&);
333 template <typename, typename = unused_type, typename = unused_type>
334 struct result { typedef remover const& type; };
336 remover(symbols& sym_)
341 template <typename Iterator>
343 operator()(Iterator const& first, Iterator const& last) const
345 sym.lookup->remove(first, last);
349 template <typename Str>
351 operator()(Str const& s) const
353 sym.lookup->remove(traits::get_begin<Char>(s)
354 , traits::get_end<Char>(s));
358 template <typename Str>
360 operator,(Str const& s) const
362 sym.lookup->remove(traits::get_begin<Char>(s)
363 , traits::get_end<Char>(s));
370 // silence MSVC warning C4512: assignment operator could not be generated
371 remover& operator= (remover const&);
376 shared_ptr<Lookup> lookup;
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>
387 template <typename CharEncoding>
388 struct no_case_filter
390 Char operator()(Char ch) const
392 return static_cast<Char>(CharEncoding::tolower(ch));
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<
401 , char_encoding::standard
402 , no_case::value>::type>
405 typedef typename mpl::if_<
407 , symbols<Char, T, Lookup, nc_filter>
411 result_type operator()(reference_ ref, unused_type) const
413 return result_type(ref.ref.get());
418 namespace boost { namespace spirit { namespace traits
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> {};
427 #if defined(BOOST_MSVC)
428 # pragma warning(pop)