]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/spirit/include/boost/spirit/home/qi/char/char.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / qi / char / char.hpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 Copyright (c) 2010 Bryce Lelbach
5
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8==============================================================================*/
9#if !defined(BOOST_SPIRIT_CHAR_APRIL_16_2006_1051AM)
10#define BOOST_SPIRIT_CHAR_APRIL_16_2006_1051AM
11
12#if defined(_MSC_VER)
13#pragma once
14#endif
15
16#include <boost/spirit/home/support/common_terminals.hpp>
17#include <boost/spirit/home/support/string_traits.hpp>
18#include <boost/spirit/home/support/info.hpp>
19#include <boost/spirit/home/support/detail/get_encoding.hpp>
20#include <boost/spirit/home/support/char_set/basic_chset.hpp>
21#include <boost/spirit/home/qi/char/char_parser.hpp>
22#include <boost/spirit/home/qi/char/char_class.hpp>
23#include <boost/spirit/home/qi/meta_compiler.hpp>
24#include <boost/spirit/home/qi/auxiliary/lazy.hpp>
25#include <boost/spirit/home/qi/detail/enable_lit.hpp>
26#include <boost/fusion/include/at.hpp>
27#include <boost/mpl/if.hpp>
28#include <boost/mpl/assert.hpp>
29#include <boost/mpl/identity.hpp>
30#include <boost/utility/enable_if.hpp>
31#include <boost/type_traits/remove_const.hpp>
32#include <string>
33
34#if defined(_MSC_VER)
35#pragma once
36#endif
37
38namespace boost { namespace spirit
39{
40 ///////////////////////////////////////////////////////////////////////////
41 // Enablers
42 ///////////////////////////////////////////////////////////////////////////
43 template <typename CharEncoding>
44 struct use_terminal<qi::domain
45 , terminal<
46 tag::char_code<tag::char_, CharEncoding> // enables char_
47 >
48 > : mpl::true_ {};
49
50 template <typename CharEncoding, typename A0>
51 struct use_terminal<qi::domain
52 , terminal_ex<
53 tag::char_code<tag::char_, CharEncoding> // enables char_('x'), char_("x")
54 , fusion::vector1<A0> // and char_("a-z0-9")
55 >
56 > : mpl::true_ {};
57
58 template <typename CharEncoding, typename A0, typename A1>
59 struct use_terminal<qi::domain
60 , terminal_ex<
61 tag::char_code<tag::char_, CharEncoding> // enables char_('a','z')
62 , fusion::vector2<A0, A1>
63 >
64 > : mpl::true_ {};
65
66 template <typename CharEncoding> // enables *lazy* char_('x'), char_("x")
67 struct use_lazy_terminal< // and char_("a-z0-9")
68 qi::domain
69 , tag::char_code<tag::char_, CharEncoding>
70 , 1 // arity
71 > : mpl::true_ {};
72
73 template <typename CharEncoding> // enables *lazy* char_('a','z')
74 struct use_lazy_terminal<
75 qi::domain
76 , tag::char_code<tag::char_, CharEncoding>
77 , 2 // arity
78 > : mpl::true_ {};
79
80 template <>
81 struct use_terminal<qi::domain, char> // enables 'x'
82 : mpl::true_ {};
83
84 template <>
85 struct use_terminal<qi::domain, char[2]> // enables "x"
86 : mpl::true_ {};
87
88 template <>
89 struct use_terminal<qi::domain, wchar_t> // enables wchar_t
90 : mpl::true_ {};
91
92 template <>
93 struct use_terminal<qi::domain, wchar_t[2]> // enables L"x"
94 : mpl::true_ {};
95
96 // enables lit(...)
97 template <typename A0>
98 struct use_terminal<qi::domain
99 , terminal_ex<tag::lit, fusion::vector1<A0> >
100 , typename enable_if<traits::is_char<A0> >::type>
101 : mpl::true_ {};
102}}
103
104namespace boost { namespace spirit { namespace qi
105{
106#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
107 using spirit::lit; // lit('x') is equivalent to 'x'
108#endif
109 using spirit::lit_type;
110
111 ///////////////////////////////////////////////////////////////////////////
112 // Parser for a single character
113 ///////////////////////////////////////////////////////////////////////////
114 template <typename CharEncoding, bool no_attribute, bool no_case = false>
115 struct literal_char
116 : char_parser<
117 literal_char<CharEncoding, no_attribute, false>
118 , typename CharEncoding::char_type
119 , typename mpl::if_c<no_attribute, unused_type
120 , typename CharEncoding::char_type>::type>
121 {
122 typedef typename CharEncoding::char_type char_type;
123 typedef CharEncoding char_encoding;
124
125 template <typename Char>
126 literal_char(Char ch_)
127 : ch(static_cast<char_type>(ch_)) {}
128
129 template <typename Context, typename Iterator>
130 struct attribute
131 {
132 typedef typename mpl::if_c<
133 no_attribute, unused_type, char_type>::type
134 type;
135 };
136
137 template <typename CharParam, typename Context>
138 bool test(CharParam ch_, Context&) const
139 {
140 return traits::ischar<CharParam, char_encoding>::call(ch_) &&
141 ch == char_type(ch_);
142 }
143
144 template <typename Context>
145 info what(Context& /*context*/) const
146 {
147 return info("literal-char", char_encoding::toucs4(ch));
148 }
149
150 char_type ch;
151 };
152
153 template <typename CharEncoding, bool no_attribute>
154 struct literal_char<CharEncoding, no_attribute, true> // case insensitive
155 : char_parser<
156 literal_char<CharEncoding, no_attribute, true>
157 , typename mpl::if_c<no_attribute, unused_type
158 , typename CharEncoding::char_type>::type>
159 {
160 typedef typename CharEncoding::char_type char_type;
161 typedef CharEncoding char_encoding;
162
163 literal_char(char_type ch)
164 : lo(static_cast<char_type>(char_encoding::tolower(ch)))
165 , hi(static_cast<char_type>(char_encoding::toupper(ch))) {}
166
167 template <typename Context, typename Iterator>
168 struct attribute
169 {
170 typedef typename mpl::if_c<
171 no_attribute, unused_type, char_type>::type
172 type;
173 };
174
175 template <typename CharParam, typename Context>
176 bool test(CharParam ch_, Context&) const
177 {
178 if (!traits::ischar<CharParam, char_encoding>::call(ch_))
179 return false;
180
181 char_type ch = char_type(ch_); // optimize for token based parsing
182 return this->lo == ch || this->hi == ch;
183 }
184
185 template <typename Context>
186 info what(Context& /*context*/) const
187 {
188 return info("no-case-literal-char", char_encoding::toucs4(lo));
189 }
190
191 char_type lo, hi;
192 };
193
194 ///////////////////////////////////////////////////////////////////////////
195 // Parser for a character range
196 ///////////////////////////////////////////////////////////////////////////
197 template <typename CharEncoding, bool no_case = false>
198 struct char_range
199 : char_parser<char_range<CharEncoding, false>, typename CharEncoding::char_type>
200 {
201 typedef typename CharEncoding::char_type char_type;
202 typedef CharEncoding char_encoding;
203
204 char_range(char_type from_, char_type to_)
205 : from(from_), to(to_) {}
206
207 template <typename CharParam, typename Context>
208 bool test(CharParam ch_, Context&) const
209 {
210 if (!traits::ischar<CharParam, char_encoding>::call(ch_))
211 return false;
212
213 char_type ch = char_type(ch_); // optimize for token based parsing
214 return !(ch < from) && !(to < ch);
215 }
216
217 template <typename Context>
218 info what(Context& /*context*/) const
219 {
220 info result("char-range", char_encoding::toucs4(from));
221 boost::get<std::string>(result.value) += '-';
222 boost::get<std::string>(result.value) += to_utf8(char_encoding::toucs4(to));
223 return result;
224 }
225
226 char_type from, to;
227 };
228
229 template <typename CharEncoding>
230 struct char_range<CharEncoding, true> // case insensitive
231 : char_parser<char_range<CharEncoding, true>, typename CharEncoding::char_type>
232 {
233 typedef typename CharEncoding::char_type char_type;
234 typedef CharEncoding char_encoding;
235
236 char_range(char_type from, char_type to)
237 : from_lo(static_cast<char_type>(char_encoding::tolower(from)))
238 , to_lo(static_cast<char_type>(char_encoding::tolower(to)))
239 , from_hi(static_cast<char_type>(char_encoding::toupper(from)))
240 , to_hi(static_cast<char_type>(char_encoding::toupper(to)))
241 {}
242
243 template <typename CharParam, typename Context>
244 bool test(CharParam ch_, Context&) const
245 {
246 if (!traits::ischar<CharParam, char_encoding>::call(ch_))
247 return false;
248
249 char_type ch = char_type(ch_); // optimize for token based parsing
250 return (!(ch < from_lo) && !(to_lo < ch))
251 || (!(ch < from_hi) && !(to_hi < ch))
252 ;
253 }
254
255 template <typename Context>
256 info what(Context& /*context*/) const
257 {
258 info result("no-case-char-range", char_encoding::toucs4(from_lo));
259 boost::get<std::string>(result.value) += '-';
260 boost::get<std::string>(result.value) += to_utf8(char_encoding::toucs4(to_lo));
261 return result;
262 }
263
264 char_type from_lo, to_lo, from_hi, to_hi;
265 };
266
267 ///////////////////////////////////////////////////////////////////////////
268 // Parser for a character set
269 ///////////////////////////////////////////////////////////////////////////
270 template <typename CharEncoding, bool no_attribute, bool no_case = false>
271 struct char_set
272 : char_parser<char_set<CharEncoding, no_attribute, false>
273 , typename mpl::if_c<no_attribute, unused_type
274 , typename CharEncoding::char_type>::type>
275 {
276 typedef typename CharEncoding::char_type char_type;
277 typedef CharEncoding char_encoding;
278
279 template <typename String>
280 char_set(String const& str)
281 {
282 using spirit::detail::cast_char;
283
284 typedef typename
285 remove_const<
286 typename traits::char_type_of<String>::type
287 >::type
288 in_type;
289
290 BOOST_SPIRIT_ASSERT_MSG((
291 (sizeof(char_type) >= sizeof(in_type))
292 ), cannot_convert_string, (String));
293
294 in_type const* definition =
295 (in_type const*)traits::get_c_string(str);
296 in_type ch = *definition++;
297 while (ch)
298 {
299 in_type next = *definition++;
300 if (next == '-')
301 {
302 next = *definition++;
303 if (next == 0)
304 {
305 chset.set(cast_char<char_type>(ch));
306 chset.set('-');
307 break;
308 }
309 chset.set(
310 cast_char<char_type>(ch),
311 cast_char<char_type>(next)
312 );
313 }
314 else
315 {
316 chset.set(cast_char<char_type>(ch));
317 }
318 ch = next;
319 }
320 }
321
322 template <typename CharParam, typename Context>
323 bool test(CharParam ch, Context&) const
324 {
325 return traits::ischar<CharParam, char_encoding>::call(ch) &&
326 chset.test(char_type(ch));
327 }
328
329 template <typename Context>
330 info what(Context& /*context*/) const
331 {
332 return info("char-set");
333 }
334
335 support::detail::basic_chset<char_type> chset;
336 };
337
338 template <typename CharEncoding, bool no_attribute>
339 struct char_set<CharEncoding, no_attribute, true> // case insensitive
340 : char_parser<char_set<CharEncoding, no_attribute, true>
341 , typename mpl::if_c<no_attribute, unused_type
342 , typename CharEncoding::char_type>::type>
343 {
344 typedef typename CharEncoding::char_type char_type;
345 typedef CharEncoding char_encoding;
346
347 template <typename String>
348 char_set(String const& str)
349 {
350 typedef typename traits::char_type_of<String>::type in_type;
351
352 BOOST_SPIRIT_ASSERT_MSG((
353 (sizeof(char_type) == sizeof(in_type))
354 ), cannot_convert_string, (String));
355
356 char_type const* definition =
357 (char_type const*)traits::get_c_string(str);
358 char_type ch = *definition++;
359 while (ch)
360 {
361 char_type next = *definition++;
362 if (next == '-')
363 {
364 next = *definition++;
365 if (next == 0)
366 {
367 chset.set(static_cast<char_type>(CharEncoding::tolower(ch)));
368 chset.set(static_cast<char_type>(CharEncoding::toupper(ch)));
369 chset.set('-');
370 break;
371 }
372 chset.set(static_cast<char_type>(CharEncoding::tolower(ch))
373 , static_cast<char_type>(CharEncoding::tolower(next)));
374 chset.set(static_cast<char_type>(CharEncoding::toupper(ch))
375 , static_cast<char_type>(CharEncoding::toupper(next)));
376 }
377 else
378 {
379 chset.set(static_cast<char_type>(CharEncoding::tolower(ch)));
380 chset.set(static_cast<char_type>(CharEncoding::toupper(ch)));
381 }
382 ch = next;
383 }
384 }
385
386 template <typename CharParam, typename Context>
387 bool test(CharParam ch, Context&) const
388 {
389 return traits::ischar<CharParam, char_encoding>::call(ch) &&
390 chset.test(char_type(ch));
391 }
392
393 template <typename Context>
394 info what(Context& /*context*/) const
395 {
396 return info("no-case-char-set");
397 }
398
399 support::detail::basic_chset<char_type> chset;
400 };
401
402 ///////////////////////////////////////////////////////////////////////////
403 // Parser generators: make_xxx function (objects)
404 ///////////////////////////////////////////////////////////////////////////
405 namespace detail
406 {
407 template <typename Modifiers, typename Encoding>
408 struct basic_literal
409 {
410 static bool const no_case =
411 has_modifier<
412 Modifiers
413 , tag::char_code_base<tag::no_case>
414 >::value;
415
416 static bool const no_attr =
417 !has_modifier<
418 Modifiers
419 , tag::lazy_eval
420 >::value;
421
422 typedef literal_char<
423 typename spirit::detail::get_encoding_with_case<
424 Modifiers, Encoding, no_case>::type
425 , no_attr
426 , no_case>
427 result_type;
428
429 template <typename Char>
430 result_type operator()(Char ch, unused_type) const
431 {
432 return result_type(ch);
433 }
434
435 template <typename Char>
436 result_type operator()(Char const* str, unused_type) const
437 {
438 return result_type(str[0]);
439 }
440 };
441 }
442
443 template <typename Modifiers>
444 struct make_primitive<char, Modifiers>
445 : detail::basic_literal<Modifiers, char_encoding::standard> {};
446
447 template <typename Modifiers>
448 struct make_primitive<char const(&)[2], Modifiers>
449 : detail::basic_literal<Modifiers, char_encoding::standard> {};
450
451 template <typename Modifiers>
452 struct make_primitive<wchar_t, Modifiers>
453 : detail::basic_literal<Modifiers, char_encoding::standard_wide> {};
454
455 template <typename Modifiers>
456 struct make_primitive<wchar_t const(&)[2], Modifiers>
457 : detail::basic_literal<Modifiers, char_encoding::standard_wide> {};
458
459 template <typename CharEncoding, typename Modifiers>
460 struct make_primitive<
461 terminal<tag::char_code<tag::char_, CharEncoding> >, Modifiers>
462 {
463 typedef typename
464 spirit::detail::get_encoding<Modifiers, CharEncoding>::type
465 char_encoding;
466
467 typedef tag::char_code<tag::char_, char_encoding> tag;
468 typedef char_class<tag> result_type;
469 result_type operator()(unused_type, unused_type) const
470 {
471 return result_type();
472 }
473 };
474
475 ///////////////////////////////////////////////////////////////////////////
476 // char_('x')
477 template <typename CharEncoding, typename Modifiers, typename A0>
478 struct make_primitive<
479 terminal_ex<
480 tag::char_code<tag::char_, CharEncoding>
481 , fusion::vector1<A0> >
482 , Modifiers>
483 {
484 static bool const no_case =
485 has_modifier<Modifiers, tag::char_code_base<tag::no_case> >::value;
486
487 typedef typename
488 spirit::detail::get_encoding<Modifiers, CharEncoding>::type
489 char_encoding;
490
491 typedef typename
492 mpl::if_<
493 traits::is_string<A0>
494 , char_set<char_encoding, false, no_case>
495 , literal_char<char_encoding, false, no_case>
496 >::type
497 result_type;
498
499 template <typename Terminal>
500 result_type operator()(Terminal const& term, unused_type) const
501 {
502 return result_type(fusion::at_c<0>(term.args));
503 }
504 };
505
506 // lit('x')
507 template <typename Modifiers, typename A0>
508 struct make_primitive<
509 terminal_ex<tag::lit, fusion::vector1<A0> >
510 , Modifiers
511 , typename enable_if<traits::is_char<A0> >::type>
512 {
513 static bool const no_case =
514 has_modifier<
515 Modifiers
516 , tag::char_code_base<tag::no_case>
517 >::value;
518
519 typedef typename traits::char_encoding_from_char<
520 typename traits::char_type_of<A0>::type>::type encoding;
521
522 typedef literal_char<
523 typename spirit::detail::get_encoding_with_case<
524 Modifiers, encoding, no_case>::type
525 , true, no_case>
526 result_type;
527
528 template <typename Terminal>
529 result_type operator()(Terminal const& term, unused_type) const
530 {
531 return result_type(fusion::at_c<0>(term.args));
532 }
533 };
534
535 ///////////////////////////////////////////////////////////////////////////
536 template <typename CharEncoding, typename Modifiers, typename Char>
537 struct make_primitive<
538 terminal_ex<
539 tag::char_code<tag::char_, CharEncoding>
540 , fusion::vector1<Char(&)[2]> // For single char strings
541 >
542 , Modifiers>
543 {
544 static bool const no_case =
545 has_modifier<Modifiers, tag::char_code_base<tag::no_case> >::value;
546
547 typedef typename
548 spirit::detail::get_encoding<Modifiers, CharEncoding>::type
549 char_encoding;
550
551 typedef literal_char<char_encoding, false, no_case> result_type;
552
553 template <typename Terminal>
554 result_type operator()(Terminal const& term, unused_type) const
555 {
556 return result_type(fusion::at_c<0>(term.args)[0]);
557 }
558 };
559
560 template <typename CharEncoding, typename Modifiers, typename A0, typename A1>
561 struct make_primitive<
562 terminal_ex<
563 tag::char_code<tag::char_, CharEncoding>
564 , fusion::vector2<A0, A1>
565 >
566 , Modifiers>
567 {
568 static bool const no_case =
569 has_modifier<Modifiers, tag::char_code_base<tag::no_case> >::value;
570
571 typedef typename
572 spirit::detail::get_encoding<Modifiers, CharEncoding>::type
573 char_encoding;
574
575 typedef char_range<char_encoding, no_case> result_type;
576
577 template <typename Terminal>
578 result_type operator()(Terminal const& term, unused_type) const
579 {
580 return result_type(
581 fusion::at_c<0>(term.args)
582 , fusion::at_c<1>(term.args)
583 );
584 }
585 };
586
587 template <typename CharEncoding, typename Modifiers, typename Char>
588 struct make_primitive<
589 terminal_ex<
590 tag::char_code<tag::char_, CharEncoding>
591 , fusion::vector2<Char(&)[2], Char(&)[2]> // For single char strings
592 >
593 , Modifiers>
594 {
595 static bool const no_case =
596 has_modifier<Modifiers, tag::char_code_base<tag::no_case> >::value;
597
598 typedef typename
599 spirit::detail::get_encoding<Modifiers, CharEncoding>::type
600 char_encoding;
601
602 typedef char_range<char_encoding, no_case> result_type;
603
604 template <typename Terminal>
605 result_type operator()(Terminal const& term, unused_type) const
606 {
607 return result_type(
608 fusion::at_c<0>(term.args)[0]
609 , fusion::at_c<1>(term.args)[0]
610 );
611 }
612 };
613}}}
614
615#endif