]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/repository/home/qi/operator/detail/keywords.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / spirit / repository / home / qi / operator / detail / keywords.hpp
1 /*=============================================================================
2 Copyright (c) 2011-2012 Thomas Bernard
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(SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM)
8 #define SPIRIT_KEYWORDS_DETAIL_MARCH_13_2007_1145PM
9
10 #if defined(_MSC_VER)
11 #pragma once
12 #endif
13 #include <boost/fusion/include/nview.hpp>
14 #include <boost/spirit/home/qi/string/lit.hpp>
15 #include <boost/fusion/include/at.hpp>
16 namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
17 // Variant visitor class which handles dispatching the parsing to the selected parser
18 // This also handles passing the correct attributes and flags/counters to the subject parsers
19 template<typename T>
20 struct is_distinct : T::distinct { };
21
22 template<typename T, typename Action>
23 struct is_distinct< spirit::qi::action<T,Action> > : T::distinct { };
24
25 template<typename T>
26 struct is_distinct< spirit::qi::hold_directive<T> > : T::distinct { };
27
28
29
30 template < typename Elements, typename Iterator ,typename Context ,typename Skipper
31 ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
32 struct parse_dispatcher
33 : public boost::static_visitor<bool>
34 {
35
36 typedef Iterator iterator_type;
37 typedef Context context_type;
38 typedef Skipper skipper_type;
39 typedef Elements elements_type;
40
41 typedef typename add_reference<Attribute>::type attr_reference;
42 public:
43 parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
44 , Context& context, Skipper const& skipper
45 , Flags &flags, Counters &counters, attr_reference attr) :
46 elements(elements), first(first), last(last)
47 , context(context), skipper(skipper)
48 , flags(flags),counters(counters), attr(attr)
49 {}
50
51 template<typename T> bool operator()(T& idx) const
52 {
53 return call(idx,typename traits::not_is_unused<Attribute>::type());
54 }
55
56 template <typename Subject,typename Index>
57 bool call_subject_unused(
58 Subject const &subject, Iterator &first, Iterator const &last
59 , Context& context, Skipper const& skipper
60 , Index& idx ) const
61 {
62 Iterator save = first;
63 skipper_keyword_marker<Skipper,NoCasePass>
64 marked_skipper(skipper,flags[Index::value],counters[Index::value]);
65
66 if(subject.parse(first,last,context,marked_skipper,unused))
67 {
68 return true;
69 }
70 save = save;
71 return false;
72 }
73
74
75 template <typename Subject,typename Index>
76 bool call_subject(
77 Subject const &subject, Iterator &first, Iterator const &last
78 , Context& context, Skipper const& skipper
79 , Index& idx ) const
80 {
81
82 Iterator save = first;
83 skipper_keyword_marker<Skipper,NoCasePass>
84 marked_skipper(skipper,flags[Index::value],counters[Index::value]);
85 if(subject.parse(first,last,context,marked_skipper,fusion::at_c<Index::value>(attr)))
86 {
87 return true;
88 }
89 save = save;
90 return false;
91 }
92
93 // Handle unused attributes
94 template <typename T> bool call(T &idx, mpl::false_) const{
95
96 typedef typename mpl::at<Elements,T>::type ElementType;
97 if(
98 (!is_distinct<ElementType>::value)
99 || skipper.parse(first,last,unused,unused,unused)
100 ){
101 spirit::qi::skip_over(first, last, skipper);
102 return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
103 }
104 return false;
105 }
106 // Handle normal attributes
107 template <typename T> bool call(T &idx, mpl::true_) const{
108 typedef typename mpl::at<Elements,T>::type ElementType;
109 if(
110 (!is_distinct<ElementType>::value)
111 || skipper.parse(first,last,unused,unused,unused)
112 ){
113 return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
114 }
115 return false;
116 }
117
118 const Elements &elements;
119 Iterator &first;
120 const Iterator &last;
121 Context & context;
122 const Skipper &skipper;
123 Flags &flags;
124 Counters &counters;
125 attr_reference attr;
126 };
127 // string keyword loop handler
128 template <typename Elements, typename StringKeywords, typename IndexList, typename FlagsType, typename Modifiers>
129 struct string_keywords
130 {
131 // Create a variant type to be able to store parser indexes in the embedded symbols parser
132 typedef typename
133 spirit::detail::as_variant<
134 IndexList >::type parser_index_type;
135
136 ///////////////////////////////////////////////////////////////////////////
137 // build_char_type_sequence
138 //
139 // Build a fusion sequence from the kwd directive specified character type.
140 ///////////////////////////////////////////////////////////////////////////
141 template <typename Sequence >
142 struct build_char_type_sequence
143 {
144 struct element_char_type
145 {
146 template <typename T>
147 struct result;
148
149 template <typename F, typename Element>
150 struct result<F(Element)>
151 {
152 typedef typename Element::char_type type;
153
154 };
155 template <typename F, typename Element,typename Action>
156 struct result<F(spirit::qi::action<Element,Action>) >
157 {
158 typedef typename Element::char_type type;
159 };
160 template <typename F, typename Element>
161 struct result<F(spirit::qi::hold_directive<Element>)>
162 {
163 typedef typename Element::char_type type;
164 };
165
166 // never called, but needed for decltype-based result_of (C++0x)
167 template <typename Element>
168 typename result<element_char_type(Element)>::type
169 operator()(Element&) const;
170 };
171
172 // Compute the list of character types of the child kwd directives
173 typedef typename
174 fusion::result_of::transform<Sequence, element_char_type>::type
175 type;
176 };
177
178
179 ///////////////////////////////////////////////////////////////////////////
180 // get_keyword_char_type
181 //
182 // Collapses the character type comming from the subject kwd parsers and
183 // and checks that they are all identical (necessary in order to be able
184 // to build a tst parser to parse the keywords.
185 ///////////////////////////////////////////////////////////////////////////
186 template <typename Sequence>
187 struct get_keyword_char_type
188 {
189 // Make sure each of the types occur only once in the type list
190 typedef typename
191 mpl::fold<
192 Sequence, mpl::vector<>,
193 mpl::if_<
194 mpl::contains<mpl::_1, mpl::_2>,
195 mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
196 >
197 >::type
198 no_duplicate_char_types;
199
200 // If the compiler traps here this means you mixed
201 // character type for the keywords specified in the
202 // kwd directive sequence.
203 BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
204
205 typedef typename mpl::front<no_duplicate_char_types>::type type;
206
207 };
208
209 // Get the character type for the tst parser
210 typedef typename build_char_type_sequence< StringKeywords >::type char_types;
211 typedef typename get_keyword_char_type<
212 typename mpl::if_<
213 mpl::equal_to<
214 typename mpl::size < char_types >::type
215 , mpl::int_<0>
216 >
217 , mpl::vector< boost::spirit::standard::char_type >
218 , char_types >::type
219 >::type char_type;
220
221 // Our symbols container
222 typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
223
224 // Filter functor used for case insensitive parsing
225 template <typename CharEncoding>
226 struct no_case_filter
227 {
228 char_type operator()(char_type ch) const
229 {
230 return static_cast<char_type>(CharEncoding::tolower(ch));
231 }
232 };
233
234 ///////////////////////////////////////////////////////////////////////////
235 // build_case_type_sequence
236 //
237 // Build a fusion sequence from the kwd/ikwd directives
238 // in order to determine if case sensitive and case insensitive
239 // keywords have been mixed.
240 ///////////////////////////////////////////////////////////////////////////
241 template <typename Sequence >
242 struct build_case_type_sequence
243 {
244 struct element_case_type
245 {
246 template <typename T>
247 struct result;
248
249 template <typename F, typename Element>
250 struct result<F(Element)>
251 {
252 typedef typename Element::no_case_keyword type;
253
254 };
255 template <typename F, typename Element,typename Action>
256 struct result<F(spirit::qi::action<Element,Action>) >
257 {
258 typedef typename Element::no_case_keyword type;
259 };
260 template <typename F, typename Element>
261 struct result<F(spirit::qi::hold_directive<Element>)>
262 {
263 typedef typename Element::no_case_keyword type;
264 };
265
266 // never called, but needed for decltype-based result_of (C++0x)
267 template <typename Element>
268 typename result<element_case_type(Element)>::type
269 operator()(Element&) const;
270 };
271
272 // Compute the list of character types of the child kwd directives
273 typedef typename
274 fusion::result_of::transform<Sequence, element_case_type>::type
275 type;
276 };
277
278 ///////////////////////////////////////////////////////////////////////////
279 // get_nb_case_types
280 //
281 // Counts the number of entries in the case type sequence matching the
282 // CaseType parameter (mpl::true_ -> case insensitve
283 // , mpl::false_ -> case sensitive
284 ///////////////////////////////////////////////////////////////////////////
285 template <typename Sequence,typename CaseType>
286 struct get_nb_case_types
287 {
288 // Make sure each of the types occur only once in the type list
289 typedef typename
290 mpl::count_if<
291 Sequence, mpl::equal_to<mpl::_,CaseType>
292 >::type type;
293
294
295 };
296 // Build the case type sequence
297 typedef typename build_case_type_sequence< StringKeywords >::type case_type_sequence;
298 // Count the number of case sensitive entries and case insensitve entries
299 typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
300 typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
301 // Get the size of the original sequence
302 typedef typename mpl::size<IndexList>::type nb_elements;
303 // Determine if all the kwd directive are case sensitive/insensitive
304 typedef typename mpl::and_<
305 typename mpl::greater< nb_elements, mpl::int_<0> >::type
306 , typename mpl::equal_to< ikwd_count, nb_elements>::type
307 >::type all_ikwd;
308
309 typedef typename mpl::and_<
310 typename mpl::greater< nb_elements, mpl::int_<0> >::type
311 , typename mpl::equal_to< kwd_count, nb_elements>::type
312 >::type all_kwd;
313
314 typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
315
316 // Do we have a no case modifier
317 typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
318
319 // Should the no_case filter always be used ?
320 typedef typename mpl::or_<
321 no_case_modifier,
322 mpl::and_<
323 all_directives_of_same_type
324 ,all_ikwd
325 >
326 >::type
327 no_case;
328
329 typedef no_case_filter<
330 typename spirit::detail::get_encoding_with_case<
331 Modifiers
332 , char_encoding::standard
333 , no_case::value>::type>
334 nc_filter;
335 // Determine the standard case filter type
336 typedef typename mpl::if_<
337 no_case
338 , nc_filter
339 , spirit::qi::tst_pass_through >::type
340 first_pass_filter_type;
341
342 typedef typename mpl::or_<
343 all_directives_of_same_type
344 , no_case_modifier
345 >::type requires_one_pass;
346
347
348 // Functor which adds all the keywords/subject parser indexes
349 // collected from the subject kwd directives to the keyword tst parser
350 struct keyword_entry_adder
351 {
352 typedef int result_type;
353
354 keyword_entry_adder(shared_ptr<keywords_type> lookup,FlagsType &flags, Elements &elements) :
355 lookup(lookup)
356 ,flags(flags)
357 ,elements(elements)
358 {}
359
360 template <typename T>
361 int operator()(const T &index) const
362 {
363 return call(fusion::at_c<T::value>(elements),index);
364 }
365
366 template <typename T, typename Position, typename Action>
367 int call(const spirit::qi::action<T,Action> &parser, const Position position ) const
368 {
369
370 // Make the keyword/parse index entry in the tst parser
371 lookup->add(
372 traits::get_begin<char_type>(get_string(parser.subject.keyword)),
373 traits::get_end<char_type>(get_string(parser.subject.keyword)),
374 position
375 );
376 // Get the initial state of the flags array and store it in the flags initializer
377 flags[Position::value]=parser.subject.iter.flag_init();
378 return 0;
379 }
380
381 template <typename T, typename Position>
382 int call( const T & parser, const Position position) const
383 {
384 // Make the keyword/parse index entry in the tst parser
385 lookup->add(
386 traits::get_begin<char_type>(get_string(parser.keyword)),
387 traits::get_end<char_type>(get_string(parser.keyword)),
388 position
389 );
390 // Get the initial state of the flags array and store it in the flags initializer
391 flags[Position::value]=parser.iter.flag_init();
392 return 0;
393 }
394
395 template <typename T, typename Position>
396 int call( const spirit::qi::hold_directive<T> & parser, const Position position) const
397 {
398 // Make the keyword/parse index entry in the tst parser
399 lookup->add(
400 traits::get_begin<char_type>(get_string(parser.subject.keyword)),
401 traits::get_end<char_type>(get_string(parser.subject.keyword)),
402 position
403 );
404 // Get the initial state of the flags array and store it in the flags initializer
405 flags[Position::value]=parser.subject.iter.flag_init();
406 return 0;
407 }
408
409
410 template <typename String, bool no_attribute>
411 const String get_string(const boost::spirit::qi::literal_string<String,no_attribute> &parser) const
412 {
413 return parser.str;
414 }
415
416 template <typename String, bool no_attribute>
417 const typename boost::spirit::qi::no_case_literal_string<String,no_attribute>::string_type &
418 get_string(const boost::spirit::qi::no_case_literal_string<String,no_attribute> &parser) const
419 {
420 return parser.str_lo;
421 }
422
423
424
425 shared_ptr<keywords_type> lookup;
426 FlagsType & flags;
427 Elements &elements;
428 };
429
430 string_keywords(Elements &elements,FlagsType &flags_init) : lookup(new keywords_type())
431 {
432 // Loop through all the subject parsers to build the keyword parser symbol parser
433 IndexList indexes;
434 keyword_entry_adder f1(lookup,flags_init,elements);
435 fusion::for_each(indexes,f1);
436
437 }
438 template <typename Iterator,typename ParseVisitor, typename Skipper>
439 bool parse(
440 Iterator &first,
441 const Iterator &last,
442 const ParseVisitor &parse_visitor,
443 const Skipper &skipper) const
444 {
445 if(parser_index_type* val_ptr =
446 lookup->find(first,last,first_pass_filter_type()))
447 {
448 if(!apply_visitor(parse_visitor,*val_ptr)){
449 return false;
450 }
451 return true;
452 }
453 return false;
454 }
455
456 template <typename Iterator,typename ParseVisitor, typename NoCaseParseVisitor,typename Skipper>
457 bool parse(
458 Iterator &first,
459 const Iterator &last,
460 const ParseVisitor &parse_visitor,
461 const NoCaseParseVisitor &no_case_parse_visitor,
462 const Skipper &skipper) const
463 {
464 Iterator saved_first = first;
465 if(parser_index_type* val_ptr =
466 lookup->find(first,last,first_pass_filter_type()))
467 {
468 if(!apply_visitor(parse_visitor,*val_ptr)){
469 return false;
470 }
471 return true;
472 }
473 // Second pass case insensitive
474 else if(parser_index_type* val_ptr
475 = lookup->find(saved_first,last,nc_filter()))
476 {
477 first = saved_first;
478 if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
479 return false;
480 }
481 return true;
482 }
483 return false;
484 }
485 shared_ptr<keywords_type> lookup;
486
487
488 };
489
490 struct empty_keywords_list
491 {
492 typedef mpl::true_ requires_one_pass;
493
494 empty_keywords_list()
495 {}
496 template<typename Elements>
497 empty_keywords_list(const Elements &)
498 {}
499
500 template<typename Elements, typename FlagsInit>
501 empty_keywords_list(const Elements &, const FlagsInit &)
502 {}
503
504 template <typename Iterator,typename ParseVisitor, typename NoCaseParseVisitor,typename Skipper>
505 bool parse(
506 Iterator &first,
507 const Iterator &last,
508 const ParseVisitor &parse_visitor,
509 const NoCaseParseVisitor &no_case_parse_visitor,
510 const Skipper &skipper) const
511 {
512 return false;
513 }
514
515 template <typename Iterator,typename ParseVisitor, typename Skipper>
516 bool parse(
517 Iterator &first,
518 const Iterator &last,
519 const ParseVisitor &parse_visitor,
520 const Skipper &skipper) const
521 {
522 return false;
523 }
524
525 template <typename ParseFunction>
526 bool parse( ParseFunction &function ) const
527 {
528 return false;
529 }
530 };
531
532 template<typename ComplexKeywords>
533 struct complex_keywords
534 {
535 // Functor which performs the flag initialization for the complex keyword parsers
536 template <typename FlagsType, typename Elements>
537 struct flag_init_value_setter
538 {
539 typedef int result_type;
540
541 flag_init_value_setter(Elements &elements,FlagsType &flags)
542 :flags(flags)
543 ,elements(elements)
544 {}
545
546 template <typename T>
547 int operator()(const T &index) const
548 {
549 return call(fusion::at_c<T::value>(elements),index);
550 }
551
552 template <typename T, typename Position, typename Action>
553 int call(const spirit::qi::action<T,Action> &parser, const Position position ) const
554 {
555 // Get the initial state of the flags array and store it in the flags initializer
556 flags[Position::value]=parser.subject.iter.flag_init();
557 return 0;
558 }
559
560 template <typename T, typename Position>
561 int call( const T & parser, const Position position) const
562 {
563 // Get the initial state of the flags array and store it in the flags initializer
564 flags[Position::value]=parser.iter.flag_init();
565 return 0;
566 }
567
568 template <typename T, typename Position>
569 int call( const spirit::qi::hold_directive<T> & parser, const Position position) const
570 {
571 // Get the initial state of the flags array and store it in the flags initializer
572 flags[Position::value]=parser.subject.iter.flag_init();
573 return 0;
574 }
575
576 FlagsType & flags;
577 Elements &elements;
578 };
579
580 template <typename Elements, typename Flags>
581 complex_keywords(Elements &elements, Flags &flags)
582 {
583 flag_init_value_setter<Flags,Elements> flag_initializer(elements,flags);
584 fusion::for_each(complex_keywords_inst,flag_initializer);
585 }
586
587 template <typename ParseFunction>
588 bool parse( ParseFunction &function ) const
589 {
590 return fusion::any(complex_keywords_inst,function);
591 }
592
593 ComplexKeywords complex_keywords_inst;
594 };
595 // This helper class enables jumping over intermediate directives
596 // down the kwd parser iteration count checking policy
597 struct register_successful_parse
598 {
599 template <typename Subject>
600 static bool call(Subject const &subject,bool &flag, int &counter)
601 {
602 return subject.iter.register_successful_parse(flag,counter);
603 }
604 template <typename Subject, typename Action>
605 static bool call(spirit::qi::action<Subject, Action> const &subject,bool &flag, int &counter)
606 {
607 return subject.subject.iter.register_successful_parse(flag,counter);
608 }
609 template <typename Subject>
610 static bool call(spirit::qi::hold_directive<Subject> const &subject,bool &flag, int &counter)
611 {
612 return subject.subject.iter.register_successful_parse(flag,counter);
613 }
614 };
615
616 // This helper class enables jumping over intermediate directives
617 // down the kwd parser
618 struct extract_keyword
619 {
620 template <typename Subject>
621 static Subject const& call(Subject const &subject)
622 {
623 return subject;
624 }
625 template <typename Subject, typename Action>
626 static Subject const& call(spirit::qi::action<Subject, Action> const &subject)
627 {
628 return subject.subject;
629 }
630 template <typename Subject>
631 static Subject const& call(spirit::qi::hold_directive<Subject> const &subject)
632 {
633 return subject.subject;
634 }
635 };
636
637 template <typename ParseDispatcher>
638 struct complex_kwd_function
639 {
640 typedef typename ParseDispatcher::iterator_type Iterator;
641 typedef typename ParseDispatcher::context_type Context;
642 typedef typename ParseDispatcher::skipper_type Skipper;
643 complex_kwd_function(
644 Iterator& first, Iterator const& last
645 , Context& context, Skipper const& skipper, ParseDispatcher &dispatcher)
646 : first(first)
647 , last(last)
648 , context(context)
649 , skipper(skipper)
650 , dispatcher(dispatcher)
651 {
652 }
653
654 template <typename Component>
655 bool operator()(Component const& component)
656 {
657 Iterator save = first;
658 if(
659 extract_keyword::call(
660 fusion::at_c<
661 Component::value
662 ,typename ParseDispatcher::elements_type
663 >(dispatcher.elements)
664 )
665 .keyword.parse(
666 first
667 ,last
668 ,context
669 ,skipper
670 ,unused)
671 )
672 {
673 if(!dispatcher(component)){
674 first = save;
675 return false;
676 }
677 return true;
678 }
679 return false;
680 }
681
682 Iterator& first;
683 Iterator const& last;
684 Context& context;
685 Skipper const& skipper;
686 ParseDispatcher const& dispatcher;
687
688 private:
689 // silence MSVC warning C4512: assignment operator could not be generated
690 complex_kwd_function& operator= (complex_kwd_function const&);
691 };
692
693
694 }}}}}
695
696 #endif