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