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:
parse_dispatcherboost::spirit::repository::qi::detail::parse_dispatcher43             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 
operator ()boost::spirit::repository::qi::detail::parse_dispatcher51             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>
call_subject_unusedboost::spirit::repository::qi::detail::parse_dispatcher57                 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>
call_subjectboost::spirit::repository::qi::detail::parse_dispatcher76                 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
callboost::spirit::repository::qi::detail::parse_dispatcher94             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
callboost::spirit::repository::qi::detail::parse_dispatcher107             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                 {
operator ()boost::spirit::repository::qi::detail::string_keywords::no_case_filter228                     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 
keyword_entry_adderboost::spirit::repository::qi::detail::string_keywords::keyword_entry_adder354                 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>
operator ()boost::spirit::repository::qi::detail::string_keywords::keyword_entry_adder361                     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>
callboost::spirit::repository::qi::detail::string_keywords::keyword_entry_adder367                     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>
callboost::spirit::repository::qi::detail::string_keywords::keyword_entry_adder382                     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>
callboost::spirit::repository::qi::detail::string_keywords::keyword_entry_adder396                     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>
get_stringboost::spirit::repository::qi::detail::string_keywords::keyword_entry_adder411                 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 &
get_stringboost::spirit::repository::qi::detail::string_keywords::keyword_entry_adder418                         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 
string_keywordsboost::spirit::repository::qi::detail::string_keywords430             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>
parseboost::spirit::repository::qi::detail::string_keywords439                 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>
parseboost::spirit::repository::qi::detail::string_keywords457                 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 
empty_keywords_listboost::spirit::repository::qi::detail::empty_keywords_list494         empty_keywords_list()
495         {}
496         template<typename Elements>
empty_keywords_listboost::spirit::repository::qi::detail::empty_keywords_list497         empty_keywords_list(const Elements &)
498         {}
499 
500        template<typename Elements, typename FlagsInit>
empty_keywords_listboost::spirit::repository::qi::detail::empty_keywords_list501         empty_keywords_list(const Elements &, const FlagsInit &)
502         {}
503 
504         template <typename Iterator,typename ParseVisitor, typename NoCaseParseVisitor,typename Skipper>
parseboost::spirit::repository::qi::detail::empty_keywords_list505         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>
parseboost::spirit::repository::qi::detail::empty_keywords_list516                 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>
parseboost::spirit::repository::qi::detail::empty_keywords_list526         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 
flag_init_value_setterboost::spirit::repository::qi::detail::complex_keywords::flag_init_value_setter541                 flag_init_value_setter(Elements &elements,FlagsType &flags)
542           :flags(flags)
543                     ,elements(elements)
544                 {}
545 
546                 template <typename T>
operator ()boost::spirit::repository::qi::detail::complex_keywords::flag_init_value_setter547                     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>
callboost::spirit::repository::qi::detail::complex_keywords::flag_init_value_setter553                     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>
callboost::spirit::repository::qi::detail::complex_keywords::flag_init_value_setter561                     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>
callboost::spirit::repository::qi::detail::complex_keywords::flag_init_value_setter569                     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>
complex_keywordsboost::spirit::repository::qi::detail::complex_keywords581         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>
parseboost::spirit::repository::qi::detail::complex_keywords588         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>
callboost::spirit::repository::qi::detail::register_successful_parse600             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>
callboost::spirit::repository::qi::detail::register_successful_parse605             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>
callboost::spirit::repository::qi::detail::register_successful_parse610             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>
callboost::spirit::repository::qi::detail::extract_keyword621             static Subject const& call(Subject const &subject)
622             {
623                 return subject;
624             }
625         template <typename Subject, typename Action>
callboost::spirit::repository::qi::detail::extract_keyword626             static Subject const& call(spirit::qi::action<Subject, Action> const &subject)
627             {
628                 return subject.subject;
629             }
630         template <typename Subject>
callboost::spirit::repository::qi::detail::extract_keyword631             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;
complex_kwd_functionboost::spirit::repository::qi::detail::complex_kwd_function643             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>
operator ()boost::spirit::repository::qi::detail::complex_kwd_function655                 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
697