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