]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | |
11fdf7f2 | 60 | , Index& /*idx*/ ) const |
7c673cae FG |
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 | } | |
92f5a8d4 | 70 | first = save; |
7c673cae FG |
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 | |
11fdf7f2 | 79 | , Index& /*idx*/ ) const |
7c673cae FG |
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 | } | |
92f5a8d4 | 89 | first = save; |
7c673cae FG |
90 | return false; |
91 | } | |
92 | ||
92f5a8d4 TL |
93 | #if defined(_MSC_VER) |
94 | # pragma warning(push) | |
95 | # pragma warning(disable: 4127) // conditional expression is constant | |
96 | #endif | |
7c673cae FG |
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 | } | |
92f5a8d4 TL |
121 | #if defined(_MSC_VER) |
122 | # pragma warning(pop) | |
123 | #endif | |
7c673cae FG |
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) | |
11fdf7f2 | 174 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
7c673cae FG |
175 | template <typename Element> |
176 | typename result<element_char_type(Element)>::type | |
11fdf7f2 TL |
177 | operator()(Element&&) const; |
178 | #endif | |
7c673cae FG |
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) | |
11fdf7f2 | 276 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
7c673cae FG |
277 | template <typename Element> |
278 | typename result<element_case_type(Element)>::type | |
11fdf7f2 TL |
279 | operator()(Element&&) const; |
280 | #endif | |
7c673cae FG |
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, | |
11fdf7f2 | 454 | const Skipper &/*skipper*/) const |
7c673cae FG |
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, | |
11fdf7f2 | 473 | const Skipper &/*skipper*/) const |
7c673cae FG |
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( | |
11fdf7f2 TL |
517 | Iterator &/*first*/, |
518 | const Iterator &/*last*/, | |
519 | const ParseVisitor &/*parse_visitor*/, | |
520 | const NoCaseParseVisitor &/*no_case_parse_visitor*/, | |
521 | const Skipper &/*skipper*/) const | |
7c673cae FG |
522 | { |
523 | return false; | |
524 | } | |
525 | ||
526 | template <typename Iterator,typename ParseVisitor, typename Skipper> | |
527 | bool parse( | |
11fdf7f2 TL |
528 | Iterator &/*first*/, |
529 | const Iterator &/*last*/, | |
530 | const ParseVisitor &/*parse_visitor*/, | |
531 | const Skipper &/*skipper*/) const | |
7c673cae FG |
532 | { |
533 | return false; | |
534 | } | |
535 | ||
536 | template <typename ParseFunction> | |
11fdf7f2 | 537 | bool parse( ParseFunction &/*function*/ ) const |
7c673cae FG |
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> | |
11fdf7f2 | 564 | int call(const spirit::qi::action<T,Action> &parser, const Position /*position*/ ) const |
7c673cae FG |
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> | |
11fdf7f2 | 572 | int call( const T & parser, const Position /*position*/) const |
7c673cae FG |
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> | |
11fdf7f2 | 580 | int call( const spirit::qi::hold_directive<T> & parser, const Position /*position*/) const |
7c673cae FG |
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 | ||
7c673cae | 699 | // silence MSVC warning C4512: assignment operator could not be generated |
92f5a8d4 | 700 | BOOST_DELETED_FUNCTION(complex_kwd_function& operator= (complex_kwd_function const&)) |
7c673cae FG |
701 | }; |
702 | ||
703 | ||
704 | }}}}} | |
705 | ||
706 | #endif |