Warning, file /include/boost/spirit/repository/home/qi/operator/detail/keywords.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_SPIRIT_REPOSITORY_QI_OPERATOR_DETAIL_KEYWORDS_HPP
0008 #define BOOST_SPIRIT_REPOSITORY_QI_OPERATOR_DETAIL_KEYWORDS_HPP
0009
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013 #include <boost/spirit/repository/home/qi/directive/kwd.hpp> // for skipper_keyword_marker
0014 #include <boost/spirit/home/qi/string/lit.hpp>
0015 #include <boost/fusion/include/at.hpp>
0016 #include <boost/fusion/include/any.hpp>
0017
0018 namespace boost { namespace spirit { namespace repository { namespace qi { namespace detail {
0019
0020
0021 template<typename T>
0022 struct is_distinct : T::distinct { };
0023
0024 template<typename T, typename Action>
0025 struct is_distinct< spirit::qi::action<T,Action> > : T::distinct { };
0026
0027 template<typename T>
0028 struct is_distinct< spirit::qi::hold_directive<T> > : T::distinct { };
0029
0030
0031
0032 template < typename Elements, typename Iterator ,typename Context ,typename Skipper
0033 ,typename Flags ,typename Counters ,typename Attribute, typename NoCasePass>
0034 struct parse_dispatcher
0035 : public boost::static_visitor<bool>
0036 {
0037
0038 typedef Iterator iterator_type;
0039 typedef Context context_type;
0040 typedef Skipper skipper_type;
0041 typedef Elements elements_type;
0042
0043 typedef typename add_reference<Attribute>::type attr_reference;
0044 public:
0045 parse_dispatcher(const Elements &elements,Iterator& first, Iterator const& last
0046 , Context& context, Skipper const& skipper
0047 , Flags &flags, Counters &counters, attr_reference attr) :
0048 elements(elements), first(first), last(last)
0049 , context(context), skipper(skipper)
0050 , flags(flags),counters(counters), attr(attr)
0051 {}
0052
0053 template<typename T> bool operator()(T& idx) const
0054 {
0055 return call(idx,typename traits::not_is_unused<Attribute>::type());
0056 }
0057
0058 template <typename Subject,typename Index>
0059 bool call_subject_unused(
0060 Subject const &subject, Iterator &first, Iterator const &last
0061 , Context& context, Skipper const& skipper
0062 , Index& ) const
0063 {
0064 Iterator save = first;
0065 skipper_keyword_marker<Skipper,NoCasePass>
0066 marked_skipper(skipper,flags[Index::value],counters[Index::value]);
0067
0068 if(subject.parse(first,last,context,marked_skipper,unused))
0069 {
0070 return true;
0071 }
0072 first = save;
0073 return false;
0074 }
0075
0076
0077 template <typename Subject,typename Index>
0078 bool call_subject(
0079 Subject const &subject, Iterator &first, Iterator const &last
0080 , Context& context, Skipper const& skipper
0081 , Index& ) const
0082 {
0083
0084 Iterator save = first;
0085 skipper_keyword_marker<Skipper,NoCasePass>
0086 marked_skipper(skipper,flags[Index::value],counters[Index::value]);
0087 typename fusion::result_of::at_c<typename remove_reference<Attribute>::type, Index::value>::type
0088 attr_ = fusion::at_c<Index::value>(attr);
0089 if(subject.parse(first,last,context,marked_skipper,attr_))
0090 {
0091 return true;
0092 }
0093 first = save;
0094 return false;
0095 }
0096
0097 #if defined(_MSC_VER)
0098 # pragma warning(push)
0099 # pragma warning(disable: 4127)
0100 #endif
0101
0102 template <typename T> bool call(T &idx, mpl::false_) const{
0103
0104 typedef typename mpl::at<Elements,T>::type ElementType;
0105 if(
0106 (!is_distinct<ElementType>::value)
0107 || skipper.parse(first,last,unused,unused,unused)
0108 ){
0109 spirit::qi::skip_over(first, last, skipper);
0110 return call_subject_unused(fusion::at_c<T::value>(elements), first, last, context, skipper, idx );
0111 }
0112 return false;
0113 }
0114
0115 template <typename T> bool call(T &idx, mpl::true_) const{
0116 typedef typename mpl::at<Elements,T>::type ElementType;
0117 if(
0118 (!is_distinct<ElementType>::value)
0119 || skipper.parse(first,last,unused,unused,unused)
0120 ){
0121 return call_subject(fusion::at_c<T::value>(elements), first, last, context, skipper, idx);
0122 }
0123 return false;
0124 }
0125 #if defined(_MSC_VER)
0126 # pragma warning(pop)
0127 #endif
0128
0129 const Elements &elements;
0130 Iterator &first;
0131 const Iterator &last;
0132 Context & context;
0133 const Skipper &skipper;
0134 Flags &flags;
0135 Counters &counters;
0136 attr_reference attr;
0137 };
0138
0139 template <typename Elements, typename StringKeywords, typename IndexList, typename FlagsType, typename Modifiers>
0140 struct string_keywords
0141 {
0142
0143 typedef typename
0144 spirit::detail::as_variant<
0145 IndexList >::type parser_index_type;
0146
0147
0148
0149
0150
0151
0152 template <typename Sequence >
0153 struct build_char_type_sequence
0154 {
0155 struct element_char_type
0156 {
0157 template <typename T>
0158 struct result;
0159
0160 template <typename F, typename Element>
0161 struct result<F(Element)>
0162 {
0163 typedef typename Element::char_type type;
0164
0165 };
0166 template <typename F, typename Element,typename Action>
0167 struct result<F(spirit::qi::action<Element,Action>) >
0168 {
0169 typedef typename Element::char_type type;
0170 };
0171 template <typename F, typename Element>
0172 struct result<F(spirit::qi::hold_directive<Element>)>
0173 {
0174 typedef typename Element::char_type type;
0175 };
0176
0177
0178 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0179 template <typename Element>
0180 typename result<element_char_type(Element)>::type
0181 operator()(Element&&) const;
0182 #endif
0183 };
0184
0185
0186 typedef typename
0187 fusion::result_of::transform<Sequence, element_char_type>::type
0188 type;
0189 };
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199 template <typename Sequence>
0200 struct get_keyword_char_type
0201 {
0202
0203 typedef typename
0204 mpl::fold<
0205 Sequence, mpl::vector<>,
0206 mpl::if_<
0207 mpl::contains<mpl::_1, mpl::_2>,
0208 mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
0209 >
0210 >::type
0211 no_duplicate_char_types;
0212
0213
0214
0215
0216 BOOST_MPL_ASSERT_RELATION( mpl::size<no_duplicate_char_types>::value, ==, 1 );
0217
0218 typedef typename mpl::front<no_duplicate_char_types>::type type;
0219
0220 };
0221
0222
0223 typedef typename build_char_type_sequence< StringKeywords >::type char_types;
0224 typedef typename get_keyword_char_type<
0225 typename mpl::if_<
0226 mpl::equal_to<
0227 typename mpl::size < char_types >::type
0228 , mpl::int_<0>
0229 >
0230 , mpl::vector< boost::spirit::standard::char_type >
0231 , char_types >::type
0232 >::type char_type;
0233
0234
0235 typedef spirit::qi::tst< char_type, parser_index_type> keywords_type;
0236
0237
0238 template <typename CharEncoding>
0239 struct no_case_filter
0240 {
0241 char_type operator()(char_type ch) const
0242 {
0243 return static_cast<char_type>(CharEncoding::tolower(ch));
0244 }
0245 };
0246
0247
0248
0249
0250
0251
0252
0253
0254 template <typename Sequence >
0255 struct build_case_type_sequence
0256 {
0257 struct element_case_type
0258 {
0259 template <typename T>
0260 struct result;
0261
0262 template <typename F, typename Element>
0263 struct result<F(Element)>
0264 {
0265 typedef typename Element::no_case_keyword type;
0266
0267 };
0268 template <typename F, typename Element,typename Action>
0269 struct result<F(spirit::qi::action<Element,Action>) >
0270 {
0271 typedef typename Element::no_case_keyword type;
0272 };
0273 template <typename F, typename Element>
0274 struct result<F(spirit::qi::hold_directive<Element>)>
0275 {
0276 typedef typename Element::no_case_keyword type;
0277 };
0278
0279
0280 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0281 template <typename Element>
0282 typename result<element_case_type(Element)>::type
0283 operator()(Element&&) const;
0284 #endif
0285 };
0286
0287
0288 typedef typename
0289 fusion::result_of::transform<Sequence, element_case_type>::type
0290 type;
0291 };
0292
0293
0294
0295
0296
0297
0298
0299
0300 template <typename Sequence,typename CaseType>
0301 struct get_nb_case_types
0302 {
0303
0304 typedef typename
0305 mpl::count_if<
0306 Sequence, mpl::equal_to<mpl::_,CaseType>
0307 >::type type;
0308
0309
0310 };
0311
0312 typedef typename build_case_type_sequence< StringKeywords >::type case_type_sequence;
0313
0314 typedef typename get_nb_case_types<case_type_sequence,mpl::true_>::type ikwd_count;
0315 typedef typename get_nb_case_types<case_type_sequence,mpl::false_>::type kwd_count;
0316
0317 typedef typename mpl::size<IndexList>::type nb_elements;
0318
0319 typedef typename mpl::and_<
0320 typename mpl::greater< nb_elements, mpl::int_<0> >::type
0321 , typename mpl::equal_to< ikwd_count, nb_elements>::type
0322 >::type all_ikwd;
0323
0324 typedef typename mpl::and_<
0325 typename mpl::greater< nb_elements, mpl::int_<0> >::type
0326 , typename mpl::equal_to< kwd_count, nb_elements>::type
0327 >::type all_kwd;
0328
0329 typedef typename mpl::or_< all_kwd, all_ikwd >::type all_directives_of_same_type;
0330
0331
0332 typedef has_modifier<Modifiers, spirit::tag::char_code_base<spirit::tag::no_case> > no_case_modifier;
0333
0334
0335 typedef typename mpl::or_<
0336 no_case_modifier,
0337 mpl::and_<
0338 all_directives_of_same_type
0339 ,all_ikwd
0340 >
0341 >::type
0342 no_case;
0343
0344 typedef no_case_filter<
0345 typename spirit::detail::get_encoding_with_case<
0346 Modifiers
0347 , char_encoding::standard
0348 , no_case::value>::type>
0349 nc_filter;
0350
0351 typedef typename mpl::if_<
0352 no_case
0353 , nc_filter
0354 , spirit::qi::tst_pass_through >::type
0355 first_pass_filter_type;
0356
0357 typedef typename mpl::or_<
0358 all_directives_of_same_type
0359 , no_case_modifier
0360 >::type requires_one_pass;
0361
0362
0363
0364
0365 struct keyword_entry_adder
0366 {
0367 typedef int result_type;
0368
0369 keyword_entry_adder(shared_ptr<keywords_type> lookup,FlagsType &flags, Elements &elements) :
0370 lookup(lookup)
0371 ,flags(flags)
0372 ,elements(elements)
0373 {}
0374
0375 template <typename T>
0376 int operator()(const T &index) const
0377 {
0378 return call(fusion::at_c<T::value>(elements),index);
0379 }
0380
0381 template <typename T, typename Position, typename Action>
0382 int call(const spirit::qi::action<T,Action> &parser, const Position position ) const
0383 {
0384
0385
0386 lookup->add(
0387 traits::get_begin<char_type>(get_string(parser.subject.keyword)),
0388 traits::get_end<char_type>(get_string(parser.subject.keyword)),
0389 position
0390 );
0391
0392 flags[Position::value]=parser.subject.iter.flag_init();
0393 return 0;
0394 }
0395
0396 template <typename T, typename Position>
0397 int call( const T & parser, const Position position) const
0398 {
0399
0400 lookup->add(
0401 traits::get_begin<char_type>(get_string(parser.keyword)),
0402 traits::get_end<char_type>(get_string(parser.keyword)),
0403 position
0404 );
0405
0406 flags[Position::value]=parser.iter.flag_init();
0407 return 0;
0408 }
0409
0410 template <typename T, typename Position>
0411 int call( const spirit::qi::hold_directive<T> & parser, const Position position) const
0412 {
0413
0414 lookup->add(
0415 traits::get_begin<char_type>(get_string(parser.subject.keyword)),
0416 traits::get_end<char_type>(get_string(parser.subject.keyword)),
0417 position
0418 );
0419
0420 flags[Position::value]=parser.subject.iter.flag_init();
0421 return 0;
0422 }
0423
0424
0425 template <typename String, bool no_attribute>
0426 const String get_string(const boost::spirit::qi::literal_string<String,no_attribute> &parser) const
0427 {
0428 return parser.str;
0429 }
0430
0431 template <typename String, bool no_attribute>
0432 const typename boost::spirit::qi::no_case_literal_string<String,no_attribute>::string_type &
0433 get_string(const boost::spirit::qi::no_case_literal_string<String,no_attribute> &parser) const
0434 {
0435 return parser.str_lo;
0436 }
0437
0438
0439
0440 shared_ptr<keywords_type> lookup;
0441 FlagsType & flags;
0442 Elements &elements;
0443 };
0444
0445 string_keywords(Elements &elements,FlagsType &flags_init) : lookup(new keywords_type())
0446 {
0447
0448 IndexList indexes;
0449 keyword_entry_adder f1(lookup,flags_init,elements);
0450 fusion::for_each(indexes,f1);
0451
0452 }
0453 template <typename Iterator,typename ParseVisitor, typename Skipper>
0454 bool parse(
0455 Iterator &first,
0456 const Iterator &last,
0457 const ParseVisitor &parse_visitor,
0458 const Skipper &) const
0459 {
0460 if(parser_index_type* val_ptr =
0461 lookup->find(first,last,first_pass_filter_type()))
0462 {
0463 if(!apply_visitor(parse_visitor,*val_ptr)){
0464 return false;
0465 }
0466 return true;
0467 }
0468 return false;
0469 }
0470
0471 template <typename Iterator,typename ParseVisitor, typename NoCaseParseVisitor,typename Skipper>
0472 bool parse(
0473 Iterator &first,
0474 const Iterator &last,
0475 const ParseVisitor &parse_visitor,
0476 const NoCaseParseVisitor &no_case_parse_visitor,
0477 const Skipper &) const
0478 {
0479 Iterator saved_first = first;
0480 if(parser_index_type* val_ptr =
0481 lookup->find(first,last,first_pass_filter_type()))
0482 {
0483 if(!apply_visitor(parse_visitor,*val_ptr)){
0484 return false;
0485 }
0486 return true;
0487 }
0488
0489 if(parser_index_type* val_ptr
0490 = lookup->find(saved_first,last,nc_filter()))
0491 {
0492 first = saved_first;
0493 if(!apply_visitor(no_case_parse_visitor,*val_ptr)){
0494 return false;
0495 }
0496 return true;
0497 }
0498 return false;
0499 }
0500 shared_ptr<keywords_type> lookup;
0501
0502
0503 };
0504
0505 struct empty_keywords_list
0506 {
0507 typedef mpl::true_ requires_one_pass;
0508
0509 empty_keywords_list()
0510 {}
0511 template<typename Elements>
0512 empty_keywords_list(const Elements &)
0513 {}
0514
0515 template<typename Elements, typename FlagsInit>
0516 empty_keywords_list(const Elements &, const FlagsInit &)
0517 {}
0518
0519 template <typename Iterator,typename ParseVisitor, typename NoCaseParseVisitor,typename Skipper>
0520 bool parse(
0521 Iterator &,
0522 const Iterator &,
0523 const ParseVisitor &,
0524 const NoCaseParseVisitor &,
0525 const Skipper &) const
0526 {
0527 return false;
0528 }
0529
0530 template <typename Iterator,typename ParseVisitor, typename Skipper>
0531 bool parse(
0532 Iterator &,
0533 const Iterator &,
0534 const ParseVisitor &,
0535 const Skipper &) const
0536 {
0537 return false;
0538 }
0539
0540 template <typename ParseFunction>
0541 bool parse( ParseFunction & ) const
0542 {
0543 return false;
0544 }
0545 };
0546
0547 template<typename ComplexKeywords>
0548 struct complex_keywords
0549 {
0550
0551 template <typename FlagsType, typename Elements>
0552 struct flag_init_value_setter
0553 {
0554 typedef int result_type;
0555
0556 flag_init_value_setter(Elements &elements,FlagsType &flags)
0557 :flags(flags)
0558 ,elements(elements)
0559 {}
0560
0561 template <typename T>
0562 int operator()(const T &index) const
0563 {
0564 return call(fusion::at_c<T::value>(elements),index);
0565 }
0566
0567 template <typename T, typename Position, typename Action>
0568 int call(const spirit::qi::action<T,Action> &parser, const Position ) const
0569 {
0570
0571 flags[Position::value]=parser.subject.iter.flag_init();
0572 return 0;
0573 }
0574
0575 template <typename T, typename Position>
0576 int call( const T & parser, const Position ) const
0577 {
0578
0579 flags[Position::value]=parser.iter.flag_init();
0580 return 0;
0581 }
0582
0583 template <typename T, typename Position>
0584 int call( const spirit::qi::hold_directive<T> & parser, const Position ) const
0585 {
0586
0587 flags[Position::value]=parser.subject.iter.flag_init();
0588 return 0;
0589 }
0590
0591 FlagsType & flags;
0592 Elements &elements;
0593 };
0594
0595 template <typename Elements, typename Flags>
0596 complex_keywords(Elements &elements, Flags &flags)
0597 {
0598 flag_init_value_setter<Flags,Elements> flag_initializer(elements,flags);
0599 fusion::for_each(complex_keywords_inst,flag_initializer);
0600 }
0601
0602 template <typename ParseFunction>
0603 bool parse( ParseFunction &function ) const
0604 {
0605 return fusion::any(complex_keywords_inst,function);
0606 }
0607
0608 ComplexKeywords complex_keywords_inst;
0609 };
0610
0611
0612 struct register_successful_parse
0613 {
0614 template <typename Subject>
0615 static bool call(Subject const &subject,bool &flag, int &counter)
0616 {
0617 return subject.iter.register_successful_parse(flag,counter);
0618 }
0619 template <typename Subject, typename Action>
0620 static bool call(spirit::qi::action<Subject, Action> const &subject,bool &flag, int &counter)
0621 {
0622 return subject.subject.iter.register_successful_parse(flag,counter);
0623 }
0624 template <typename Subject>
0625 static bool call(spirit::qi::hold_directive<Subject> const &subject,bool &flag, int &counter)
0626 {
0627 return subject.subject.iter.register_successful_parse(flag,counter);
0628 }
0629 };
0630
0631
0632
0633 struct extract_keyword
0634 {
0635 template <typename Subject>
0636 static Subject const& call(Subject const &subject)
0637 {
0638 return subject;
0639 }
0640 template <typename Subject, typename Action>
0641 static Subject const& call(spirit::qi::action<Subject, Action> const &subject)
0642 {
0643 return subject.subject;
0644 }
0645 template <typename Subject>
0646 static Subject const& call(spirit::qi::hold_directive<Subject> const &subject)
0647 {
0648 return subject.subject;
0649 }
0650 };
0651
0652 #ifdef _MSC_VER
0653 # pragma warning(push)
0654 # pragma warning(disable: 4512)
0655 #endif
0656 template <typename ParseDispatcher>
0657 struct complex_kwd_function
0658 {
0659 typedef typename ParseDispatcher::iterator_type Iterator;
0660 typedef typename ParseDispatcher::context_type Context;
0661 typedef typename ParseDispatcher::skipper_type Skipper;
0662 complex_kwd_function(
0663 Iterator& first, Iterator const& last
0664 , Context& context, Skipper const& skipper, ParseDispatcher &dispatcher)
0665 : first(first)
0666 , last(last)
0667 , context(context)
0668 , skipper(skipper)
0669 , dispatcher(dispatcher)
0670 {
0671 }
0672
0673 template <typename Component>
0674 bool operator()(Component const& component)
0675 {
0676 Iterator save = first;
0677 if(
0678 extract_keyword::call(
0679 fusion::at_c<
0680 Component::value
0681 ,typename ParseDispatcher::elements_type
0682 >(dispatcher.elements)
0683 )
0684 .keyword.parse(
0685 first
0686 ,last
0687 ,context
0688 ,skipper
0689 ,unused)
0690 )
0691 {
0692 if(!dispatcher(component)){
0693 first = save;
0694 return false;
0695 }
0696 return true;
0697 }
0698 return false;
0699 }
0700
0701 Iterator& first;
0702 Iterator const& last;
0703 Context& context;
0704 Skipper const& skipper;
0705 ParseDispatcher const& dispatcher;
0706 };
0707 #ifdef _MSC_VER
0708 # pragma warning(pop)
0709 #endif
0710
0711
0712 }}}}}
0713
0714 #endif