1 /*============================================================================= 2 Copyright (c) 2001-2011 Joel de Guzman 3 Copyright (c) 2011 Thomas Bernard 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 =============================================================================*/ 8 #ifndef BOOST_SPIRIT_REPOSITORY_QI_DIRECTIVE_KWD_HPP 9 #define BOOST_SPIRIT_REPOSITORY_QI_DIRECTIVE_KWD_HPP 10 11 #if defined(_MSC_VER) 12 #pragma once 13 #endif 14 15 #include <boost/spirit/home/qi/meta_compiler.hpp> 16 #include <boost/spirit/home/qi/parser.hpp> 17 #include <boost/spirit/home/qi/auxiliary/lazy.hpp> 18 #include <boost/spirit/home/qi/operator/kleene.hpp> 19 #include <boost/spirit/home/qi/string/lit.hpp> 20 #include <boost/spirit/home/support/container.hpp> 21 #include <boost/spirit/home/qi/detail/attributes.hpp> 22 #include <boost/spirit/home/qi/detail/fail_function.hpp> 23 #include <boost/spirit/home/support/info.hpp> 24 #include <boost/spirit/repository/home/support/kwd.hpp> 25 #include <boost/fusion/include/at.hpp> 26 #include <vector> 27 28 #if defined(_MSC_VER) 29 # pragma warning(push) 30 # pragma warning(disable: 4127) // conditional expression is constant 31 #endif 32 33 namespace boost { namespace spirit 34 { 35 /////////////////////////////////////////////////////////////////////////// 36 // Enablers 37 /////////////////////////////////////////////////////////////////////////// 38 39 template < typename T> 40 struct use_directive<qi::domain 41 , terminal_ex<repository::tag::kwd // enables kwd(key)[p] 42 , fusion::vector1<T > > 43 > : mpl::true_ {}; 44 45 template < typename T> 46 struct use_directive<qi::domain 47 , terminal_ex<repository::tag::ikwd // enables ikwd(key)[p] 48 , fusion::vector1<T > > 49 > : mpl::true_ {}; 50 51 template < typename T> 52 struct use_directive<qi::domain 53 , terminal_ex<repository::tag::dkwd // enables dkwd(key)[p] 54 , fusion::vector1<T > > 55 > : mpl::true_ {}; 56 57 template < typename T> 58 struct use_directive<qi::domain 59 , terminal_ex<repository::tag::idkwd // enables idkwd(key)[p] 60 , fusion::vector1<T > > 61 > : mpl::true_ {}; 62 63 64 template < typename T1, typename T2> 65 struct use_directive<qi::domain 66 , terminal_ex<repository::tag::kwd // enables kwd(key,exact)[p] 67 , fusion::vector2< T1, T2 > > 68 > : mpl::true_ {}; 69 70 template < typename T1, typename T2> 71 struct use_directive<qi::domain 72 , terminal_ex<repository::tag::ikwd // enables ikwd(key,exact)[p] 73 , fusion::vector2< T1, T2 > > 74 > : mpl::true_ {}; 75 76 template < typename T1, typename T2> 77 struct use_directive<qi::domain 78 , terminal_ex<repository::tag::dkwd // enables dkwd(key,exact)[p] 79 , fusion::vector2< T1, T2 > > 80 > : mpl::true_ {}; 81 82 template < typename T1, typename T2> 83 struct use_directive<qi::domain 84 , terminal_ex<repository::tag::idkwd // enables idkwd(key,exact)[p] 85 , fusion::vector2< T1, T2 > > 86 > : mpl::true_ {}; 87 88 template < typename T1, typename T2> 89 struct use_directive<qi::domain 90 , terminal_ex<repository::tag::kwd // enables kwd(min, max)[p] 91 , fusion::vector3< T1, T2, T2 > > 92 > : mpl::true_ {}; 93 94 template < typename T1, typename T2> 95 struct use_directive<qi::domain 96 , terminal_ex<repository::tag::ikwd // enables ikwd(min, max)[p] 97 , fusion::vector3< T1, T2, T2 > > 98 > : mpl::true_ {}; 99 100 template < typename T1, typename T2> 101 struct use_directive<qi::domain 102 , terminal_ex<repository::tag::dkwd // enables dkwd(min, max)[p] 103 , fusion::vector3< T1, T2, T2 > > 104 > : mpl::true_ {}; 105 106 template < typename T1, typename T2> 107 struct use_directive<qi::domain 108 , terminal_ex<repository::tag::idkwd // enables idkwd(min, max)[p] 109 , fusion::vector3< T1, T2, T2 > > 110 > : mpl::true_ {}; 111 112 template < typename T1, typename T2> 113 struct use_directive<qi::domain 114 , terminal_ex<repository::tag::kwd // enables kwd(min, inf)[p] 115 , fusion::vector3<T1, T2, inf_type > > 116 > : mpl::true_ {}; 117 118 template < typename T1, typename T2> 119 struct use_directive<qi::domain 120 , terminal_ex<repository::tag::ikwd // enables ikwd(min, inf)[p] 121 , fusion::vector3<T1, T2, inf_type > > 122 > : mpl::true_ {}; 123 124 template < typename T1, typename T2> 125 struct use_directive<qi::domain 126 , terminal_ex<repository::tag::dkwd // enables dkwd(min, inf)[p] 127 , fusion::vector3<T1, T2, inf_type > > 128 > : mpl::true_ {}; 129 130 template < typename T1, typename T2> 131 struct use_directive<qi::domain 132 , terminal_ex<repository::tag::idkwd // enables idkwd(min, inf)[p] 133 , fusion::vector3<T1, T2, inf_type > > 134 > : mpl::true_ {}; 135 136 137 /* template <> // enables *lazy* kwd(exact)[p] 138 struct use_lazy_directive< 139 qi::domain 140 , tag::kwd 141 , 1 // arity 142 > : mpl::true_ {}; 143 144 template <> // enables *lazy* kwd(min, max)[p] 145 struct use_lazy_directive< // and kwd(min, inf)[p] 146 qi::domain 147 , tag::kwd 148 , 2 // arity 149 > : mpl::true_ {}; 150 */ 151 152 }} 153 154 namespace boost { namespace spirit { namespace repository { namespace qi 155 { 156 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 157 using repository::kwd; 158 using repository::ikwd; 159 using repository::dkwd; 160 using repository::idkwd; 161 using spirit::inf; 162 #endif 163 using repository::kwd_type; 164 using repository::ikwd_type; 165 using repository::dkwd_type; 166 using repository::idkwd_type; 167 using spirit::inf_type; 168 169 template <typename T> 170 struct kwd_pass_iterator // handles kwd(exact)[p] 171 { kwd_pass_iteratorboost::spirit::repository::qi::kwd_pass_iterator172 kwd_pass_iterator() {} flag_initboost::spirit::repository::qi::kwd_pass_iterator173 bool flag_init() const { return true; } register_successful_parseboost::spirit::repository::qi::kwd_pass_iterator174 bool register_successful_parse(bool &flag,T &/*i*/) const { 175 flag=true; 176 return true; 177 } 178 179 180 // silence MSVC warning C4512: assignment operator could not be generated 181 BOOST_DELETED_FUNCTION(kwd_pass_iterator& operator= (kwd_pass_iterator const&)) 182 }; 183 184 template <typename T> 185 struct kwd_exact_iterator // handles kwd(exact)[p] 186 { kwd_exact_iteratorboost::spirit::repository::qi::kwd_exact_iterator187 kwd_exact_iterator(T const exact) 188 : exact(exact){} 189 190 typedef T type; flag_initboost::spirit::repository::qi::kwd_exact_iterator191 bool flag_init() const { return false; } register_successful_parseboost::spirit::repository::qi::kwd_exact_iterator192 bool register_successful_parse(bool &flag,T &i) const { 193 i++; 194 if(i<exact) 195 { 196 flag=false; 197 return true; 198 } 199 else if(i==exact) 200 { 201 flag=true; 202 return true; 203 } 204 else 205 return flag=false; 206 207 } 208 T const exact; 209 210 // silence MSVC warning C4512: assignment operator could not be generated 211 BOOST_DELETED_FUNCTION(kwd_exact_iterator& operator= (kwd_exact_iterator const&)) 212 }; 213 214 template <typename T> 215 struct kwd_finite_iterator // handles kwd(min, max)[p] 216 { kwd_finite_iteratorboost::spirit::repository::qi::kwd_finite_iterator217 kwd_finite_iterator(T const min, T const max) 218 : min BOOST_PREVENT_MACRO_SUBSTITUTION (min) 219 , max BOOST_PREVENT_MACRO_SUBSTITUTION (max) 220 {} 221 222 typedef T type; flag_initboost::spirit::repository::qi::kwd_finite_iterator223 bool flag_init() const { return min==0; } register_successful_parseboost::spirit::repository::qi::kwd_finite_iterator224 bool register_successful_parse(bool &flag,T &i) const { 225 i++; 226 if(i<min) 227 { 228 flag=false; 229 return true; 230 } 231 else if(i>=min && i<=max) 232 { 233 return flag=true; 234 } 235 else 236 return flag=false; 237 } 238 T const min; 239 T const max; 240 241 // silence MSVC warning C4512: assignment operator could not be generated 242 BOOST_DELETED_FUNCTION(kwd_finite_iterator& operator= (kwd_finite_iterator const&)) 243 }; 244 245 template <typename T> 246 struct kwd_infinite_iterator // handles kwd(min, inf)[p] 247 { kwd_infinite_iteratorboost::spirit::repository::qi::kwd_infinite_iterator248 kwd_infinite_iterator(T const min) 249 : min BOOST_PREVENT_MACRO_SUBSTITUTION (min) {} 250 251 typedef T type; flag_initboost::spirit::repository::qi::kwd_infinite_iterator252 bool flag_init() const { return min==0; } register_successful_parseboost::spirit::repository::qi::kwd_infinite_iterator253 bool register_successful_parse(bool &flag,T &i) const { 254 i++; 255 flag = i>=min; 256 return true; 257 } 258 T const min; 259 260 // silence MSVC warning C4512: assignment operator could not be generated 261 BOOST_DELETED_FUNCTION(kwd_infinite_iterator& operator= (kwd_infinite_iterator const&)) 262 }; 263 264 // This class enables the transportation of parameters needed to call 265 // the occurrence constraint checker from higher level calls 266 // It also serves to select the correct parse function call 267 // of the keyword parser. The implementation changes depending if it is 268 // called form a keyword parsing loop or not. 269 template <typename Skipper, typename NoCasePass> 270 struct skipper_keyword_marker 271 { 272 typedef NoCasePass no_case_pass; 273 skipper_keyword_markerboost::spirit::repository::qi::skipper_keyword_marker274 skipper_keyword_marker(Skipper const &skipper,bool &flag,int &counter) : 275 skipper(skipper) 276 , flag(flag) 277 , counter(counter) 278 {} 279 280 const Skipper &skipper; 281 bool &flag; 282 int &counter; 283 }; 284 285 template <typename Subject, typename KeywordType, typename LoopIter , typename NoCase, typename Distinct > 286 struct kwd_parser : spirit::qi::unary_parser<kwd_parser<Subject, KeywordType, LoopIter , NoCase, Distinct > > 287 { 288 struct kwd_parser_id; 289 290 typedef Subject subject_type; 291 typedef NoCase no_case_keyword; 292 typedef Distinct distinct; 293 294 typedef typename 295 remove_const<typename traits::char_type_of<KeywordType>::type>::type 296 char_type; 297 298 typedef std::basic_string<char_type> keyword_type; 299 300 template <typename Context, typename Iterator> 301 struct attribute 302 { 303 typedef typename 304 traits::build_std_vector< 305 typename traits::attribute_of< 306 Subject, Context, Iterator>::type 307 >::type 308 type; 309 }; 310 311 kwd_parserboost::spirit::repository::qi::kwd_parser312 kwd_parser(Subject const& subject 313 , typename add_reference<KeywordType>::type keyword 314 , LoopIter const& iter) 315 : subject(subject), iter(iter), keyword(keyword) {} 316 317 template<typename CharEncoding> kwd_parserboost::spirit::repository::qi::kwd_parser318 kwd_parser(Subject const& subject 319 , typename add_reference<KeywordType>::type keyword 320 , LoopIter const& iter, CharEncoding encoding) 321 : subject(subject), iter(iter), keyword(keyword,encoding) {} 322 323 324 // Call the subject parser on a non container attribute 325 template <typename Iterator, typename Context 326 , typename Skipper, typename Attribute> parse_implboost::spirit::repository::qi::kwd_parser327 bool parse_impl(Iterator& first, Iterator const& last 328 , Context& context, Skipper const& skipper 329 , Attribute& attr,mpl::false_) const 330 { 331 return subject.parse(first,last,context,skipper,attr); 332 } 333 334 // Call the subject parser on a container attribute 335 template <typename Iterator, typename Context 336 , typename Skipper, typename Attribute> parse_implboost::spirit::repository::qi::kwd_parser337 bool parse_impl(Iterator& first, Iterator const& last 338 , Context& context, Skipper const& skipper 339 , Attribute& attr,mpl::true_) const 340 { 341 342 // synthesized attribute needs to be default constructed 343 typename traits::container_value<Attribute>::type val = 344 typename traits::container_value<Attribute>::type(); 345 346 Iterator save = first; 347 bool r = subject.parse(first,last,context,skipper, val); 348 if (r) 349 { 350 // push the parsed value into our attribute 351 r = traits::push_back(attr, val); 352 if (!r) 353 first = save; 354 } 355 return r; 356 } 357 358 template <typename Iterator, typename Context 359 , typename Skipper, typename Attribute,typename NoCasePass> parseboost::spirit::repository::qi::kwd_parser360 bool parse(Iterator& first, Iterator const& last 361 , Context& context, skipper_keyword_marker<Skipper,NoCasePass> const& skipper 362 , Attribute &attr) const 363 { 364 365 typedef typename traits::attribute_of< 366 Subject, Context, Iterator>::type 367 subject_attribute; 368 369 typedef typename mpl::and_< 370 traits::is_container<Attribute> 371 , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > > 372 >::type predicate; 373 374 if((no_case_keyword::value && NoCasePass::value) || !NoCasePass::value) 375 { 376 if(parse_impl(first,last,context,skipper.skipper,attr, predicate())) 377 return iter.register_successful_parse(skipper.flag,skipper.counter); 378 } 379 return false; 380 } 381 382 template <typename Iterator, typename Context 383 , typename Skipper, typename Attribute> parseboost::spirit::repository::qi::kwd_parser384 bool parse(Iterator& first, Iterator const& last 385 , Context& context, Skipper const& skipper 386 , Attribute& attr) const 387 { 388 typedef typename traits::attribute_of< 389 Subject, Context, Iterator>::type 390 subject_attribute; 391 392 typedef typename mpl::and_< 393 traits::is_container<Attribute> 394 , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > > 395 >::type predicate; 396 397 398 // Parse the keyword 399 bool flag = iter.flag_init(); 400 int counter = 0; 401 Iterator save = first; 402 spirit::qi::skip_over(first, last, skipper); 403 if(keyword.parse(first,last,context,skipper,unused)){ 404 if((!distinct::value) || skipper.parse(first,last,unused,unused,unused)){ 405 // Followed by the subject parser 406 spirit::qi::skip_over(first, last, skipper); 407 if(parse_impl(first,last,context,skipper,attr, predicate())) 408 { 409 return iter.register_successful_parse(flag,counter); 410 } 411 } 412 } 413 first = save; 414 return flag; 415 } 416 417 418 template <typename Context> whatboost::spirit::repository::qi::kwd_parser419 info what(Context& context) const 420 { 421 if(distinct::value){ 422 if(no_case_keyword::value) 423 return info("idkwd", subject.what(context)); 424 else 425 return info("dkwd", subject.what(context)); 426 } 427 else 428 { 429 if(no_case_keyword::value) 430 return info("ikwd", subject.what(context)); 431 else 432 return info("kwd", subject.what(context)); 433 } 434 } 435 436 Subject subject; 437 LoopIter iter; 438 439 typedef typename mpl::if_< 440 no_case_keyword, 441 spirit::qi::no_case_literal_string< KeywordType, true>, 442 spirit::qi::literal_string<KeywordType, true> >::type keyword_string_type; 443 keyword_string_type keyword; 444 445 // silence MSVC warning C4512: assignment operator could not be generated 446 BOOST_DELETED_FUNCTION(kwd_parser& operator= (kwd_parser const&)) 447 448 private: 449 template <typename Iterator, typename Context, typename Skipper> 450 static spirit::qi::detail::fail_function<Iterator, Context, Skipper> fail_functionboost::spirit::repository::qi::kwd_parser451 fail_function( 452 Iterator& first, Iterator const& last 453 , Context& context, Skipper const& skipper) 454 { 455 return spirit::qi::detail::fail_function<Iterator, Context, Skipper> 456 (first, last, context, skipper); 457 } 458 459 460 }; 461 462 template <typename Subject, typename KeywordType, typename LoopIter, typename Distinct> 463 struct complex_kwd_parser : spirit::qi::unary_parser<complex_kwd_parser<Subject, KeywordType, LoopIter, Distinct > > 464 { 465 struct complex_kwd_parser_id; 466 typedef Subject subject_type; 467 typedef Distinct distinct; 468 469 template <typename Context, typename Iterator> 470 struct attribute 471 { 472 typedef typename 473 traits::build_std_vector< 474 typename traits::attribute_of< 475 Subject, Context, Iterator>::type 476 >::type 477 type; 478 }; 479 480 complex_kwd_parserboost::spirit::repository::qi::complex_kwd_parser481 complex_kwd_parser(Subject const& subject 482 , typename add_reference<KeywordType>::type keyword 483 , LoopIter const& iter) 484 : subject(subject), iter(iter), keyword(keyword) {} 485 486 // Call the subject parser on a non container attribute 487 template <typename Iterator, typename Context 488 , typename Skipper, typename Attribute> parse_implboost::spirit::repository::qi::complex_kwd_parser489 bool parse_impl(Iterator& first, Iterator const& last 490 , Context& context, Skipper const& skipper 491 , Attribute& attr,mpl::false_) const 492 { 493 return subject.parse(first,last,context,skipper,attr); 494 } 495 496 // Call the subject parser on a container attribute 497 template <typename Iterator, typename Context 498 , typename Skipper, typename Attribute> parse_implboost::spirit::repository::qi::complex_kwd_parser499 bool parse_impl(Iterator& first, Iterator const& last 500 , Context& context, Skipper const& skipper 501 , Attribute& attr,mpl::true_) const 502 { 503 504 // synthesized attribute needs to be default constructed 505 typename traits::container_value<Attribute>::type val = 506 typename traits::container_value<Attribute>::type(); 507 508 Iterator save = first; 509 bool r = subject.parse(first,last,context,skipper, val); 510 if (r) 511 { 512 // push the parsed value into our attribute 513 r = traits::push_back(attr, val); 514 if (!r) 515 first = save; 516 } 517 return r; 518 } 519 520 template <typename Iterator, typename Context 521 , typename Skipper, typename Attribute,typename NoCasePass> parseboost::spirit::repository::qi::complex_kwd_parser522 bool parse(Iterator& first, Iterator const& last 523 , Context& context, skipper_keyword_marker<Skipper,NoCasePass> const& skipper 524 , Attribute &attr) const 525 { 526 527 typedef typename traits::attribute_of< 528 Subject, Context, Iterator>::type 529 subject_attribute; 530 531 typedef typename mpl::and_< 532 traits::is_container<Attribute> 533 , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > > 534 >::type predicate; 535 536 if(parse_impl(first,last,context,skipper.skipper,attr, predicate())) 537 return iter.register_successful_parse(skipper.flag,skipper.counter); 538 return false; 539 } 540 541 template <typename Iterator, typename Context 542 , typename Skipper, typename Attribute> parseboost::spirit::repository::qi::complex_kwd_parser543 bool parse(Iterator& first, Iterator const& last 544 , Context& context, Skipper const& skipper 545 , Attribute& attr) const 546 { 547 typedef typename traits::attribute_of< 548 Subject, Context, Iterator>::type 549 subject_attribute; 550 551 typedef typename mpl::and_< 552 traits::is_container<Attribute> 553 , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > > 554 >::type predicate; 555 556 557 // Parse the keyword 558 bool flag = iter.flag_init(); 559 int counter = 0; 560 Iterator save = first; 561 spirit::qi::skip_over(first, last, skipper); 562 if(keyword.parse(first,last,context,skipper,unused)){ 563 if( !distinct::value || skipper.parse(first,last,unused,unused,unused)){ 564 // Followed by the subject parser 565 spirit::qi::skip_over(first, last, skipper); 566 if(parse_impl(first,last,context,skipper,attr, predicate())) 567 { 568 return iter.register_successful_parse(flag,counter); 569 } 570 } 571 } 572 first = save; 573 return flag; 574 } 575 576 577 template <typename Context> whatboost::spirit::repository::qi::complex_kwd_parser578 info what(Context& context) const 579 { 580 if(distinct::value) 581 return info("dkwd", subject.what(context)); 582 else 583 return info("kwd", subject.what(context)); 584 } 585 586 Subject subject; 587 LoopIter iter; 588 589 KeywordType keyword; 590 591 // silence MSVC warning C4512: assignment operator could not be generated 592 BOOST_DELETED_FUNCTION(complex_kwd_parser& operator= (complex_kwd_parser const&)) 593 594 private: 595 template <typename Iterator, typename Context, typename Skipper> 596 static spirit::qi::detail::fail_function<Iterator, Context, Skipper> fail_functionboost::spirit::repository::qi::complex_kwd_parser597 fail_function( 598 Iterator& first, Iterator const& last 599 , Context& context, Skipper const& skipper) 600 { 601 return spirit::qi::detail::fail_function<Iterator, Context, Skipper> 602 (first, last, context, skipper); 603 } 604 605 }; 606 607 }}}} 608 609 /////////////////////////////////////////////////////////////////////////////// 610 namespace boost { namespace spirit { namespace qi 611 { 612 613 /////////////////////////////////////////////////////////////////////////// 614 // Parser generators: make_xxx function (objects) 615 /////////////////////////////////////////////////////////////////////////// 616 617 template <typename T1, typename T2, typename Subject, typename Modifiers, typename Distinct, typename MakeDirectiveHelper> 618 struct make_directive_internal_2_args 619 { 620 621 // is the keyword a string keyword ? 622 typedef typename traits::is_string<T1> is_string_kwd_type; 623 // make the keyword type 624 typedef typename mpl::if_< is_string_kwd_type , 625 T1 , 626 typename result_of::compile<qi::domain, T1>::type 627 >::type keyword_type; 628 629 typedef typename add_const<keyword_type>::type const_keyword; 630 // select the pass iterator type 631 typedef typename MakeDirectiveHelper::iterator_type iterator_type; 632 // determine if a no case modifier applies to the context 633 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case; 634 // Determine the full type of the kwd / complex_kwd directive 635 typedef typename 636 mpl::if_< 637 is_string_kwd_type, 638 repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case, Distinct >, 639 repository::qi::complex_kwd_parser<Subject, const_keyword, iterator_type, Distinct > 640 >::type result_type; 641 642 // Return a kwd parser object 643 template <typename Terminal> create_kwd_stringboost::spirit::qi::make_directive_internal_2_args644 result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::true_ ) const 645 { 646 typename spirit::detail::get_encoding<Modifiers, 647 spirit::char_encoding::standard>::type encoding; 648 return result_type(subject 649 ,MakeDirectiveHelper::make_iterator(term.args) 650 ,encoding 651 ); 652 } 653 template <typename Terminal> create_kwd_stringboost::spirit::qi::make_directive_internal_2_args654 result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::false_ ) const 655 { 656 return result_type(subject 657 ,fusion::at_c<0>(term.args) 658 ,MakeDirectiveHelper::make_iterator(term.args) 659 ); 660 } 661 template <typename Terminal> create_kwdboost::spirit::qi::make_directive_internal_2_args662 result_type create_kwd(Terminal const &term, Subject const & subject, Modifiers const& /*modifiers*/, boost::mpl::true_ ) const 663 { 664 return create_kwd_string(term,subject,no_case()); 665 } 666 // Return a complex_kwd parser object 667 template <typename Terminal> create_kwdboost::spirit::qi::make_directive_internal_2_args668 result_type create_kwd(Terminal const &term , Subject const & subject, Modifiers const& modifiers, boost::mpl::false_ ) const 669 { 670 return result_type(subject 671 ,compile<qi::domain>(fusion::at_c<0>(term.args),modifiers) 672 ,MakeDirectiveHelper::make_iterator(term.args) 673 ); 674 } 675 // Select which object type to return 676 template <typename Terminal> operator ()boost::spirit::qi::make_directive_internal_2_args677 result_type operator()( 678 Terminal const& term, Subject const& subject, Modifiers const& modifiers) const 679 { 680 return create_kwd(term, subject, modifiers, is_string_kwd_type()); 681 } 682 683 }; 684 685 // Directive kwd(key)[p] 686 template <typename T1, typename Subject, typename Modifiers, typename Distinct> 687 struct make_directive_internal 688 { 689 // is the keyword a string keyword ? 690 typedef typename traits::is_string<T1> is_string_kwd_type; 691 // make the keyword type 692 typedef typename mpl::if_< is_string_kwd_type , 693 T1 , 694 typename result_of::compile<qi::domain, T1, Modifiers>::type 695 >::type keyword_type; 696 697 typedef typename add_const<keyword_type>::type const_keyword; 698 // select the pass iterator type 699 typedef repository::qi::kwd_pass_iterator<int> iterator_type; 700 // determine if a no case modifier applies to the context 701 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case; 702 // Determine the full type of the kwd / complex_kwd directive 703 typedef typename 704 mpl::if_< 705 is_string_kwd_type, 706 repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case, Distinct >, 707 repository::qi::complex_kwd_parser<Subject, const_keyword, iterator_type, Distinct> 708 >::type result_type; 709 710 // Return a kwd parser object 711 template <typename Terminal> create_kwd_stringboost::spirit::qi::make_directive_internal712 result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::true_) const 713 { 714 typename spirit::detail::get_encoding<Modifiers, 715 spirit::char_encoding::standard>::type encoding; 716 717 return result_type(subject 718 ,fusion::at_c<0>(term.args) 719 ,iterator_type() 720 ,encoding 721 ); 722 723 } 724 template <typename Terminal> create_kwd_stringboost::spirit::qi::make_directive_internal725 result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::false_) const 726 { 727 return result_type(subject 728 ,fusion::at_c<0>(term.args) 729 ,iterator_type() 730 ); 731 } 732 template <typename Terminal> create_kwdboost::spirit::qi::make_directive_internal733 result_type create_kwd(Terminal const &term, Subject const & subject, Modifiers const& /*modifiers*/, boost::mpl::true_ ) const 734 { 735 return create_kwd_string(term,subject,no_case()); 736 } 737 // Return a complex_kwd parser object 738 template <typename Terminal> create_kwdboost::spirit::qi::make_directive_internal739 result_type create_kwd(Terminal const &term , Subject const & subject, Modifiers const& modifiers, boost::mpl::false_ ) const 740 { 741 return result_type(subject 742 ,compile<qi::domain>(fusion::at_c<0>(term.args),modifiers) 743 ,iterator_type() 744 ); 745 } 746 // Select which object type to return 747 template <typename Terminal> operator ()boost::spirit::qi::make_directive_internal748 result_type operator()( 749 Terminal const& term, Subject const& subject, Modifiers const& modifiers ) const 750 { 751 return create_kwd(term, subject, modifiers, is_string_kwd_type()); 752 } 753 }; 754 755 template <typename T1, typename Subject, typename Modifiers> 756 struct make_directive< 757 terminal_ex<repository::tag::kwd, fusion::vector1<T1> >, Subject, Modifiers> 758 { 759 typedef make_directive_internal<T1, Subject, Modifiers, mpl::false_> make_directive_type; 760 typedef typename make_directive_type::result_type result_type; 761 template <typename Terminal> operator ()boost::spirit::qi::make_directive762 result_type operator()( 763 Terminal const& term, Subject const& subject, Modifiers const& modifiers) const 764 { 765 766 return make_directive_type()(term, subject, modifiers); 767 } 768 769 }; 770 771 template <typename T1, typename Subject, typename Modifiers> 772 struct make_directive< 773 terminal_ex<repository::tag::dkwd, fusion::vector1<T1> >, Subject, Modifiers> 774 { 775 typedef make_directive_internal<T1, Subject, Modifiers, mpl::true_> make_directive_type; 776 typedef typename make_directive_type::result_type result_type; 777 template <typename Terminal> operator ()boost::spirit::qi::make_directive778 result_type operator()( 779 Terminal const& term, Subject const& subject, Modifiers const& modifiers) const 780 { 781 782 return make_directive_type()(term, subject, modifiers); 783 } 784 785 }; 786 787 788 789 // Directive ikwd(key)[p] 790 template <typename T1, typename Subject, typename Modifiers> 791 struct make_directive< 792 terminal_ex<repository::tag::ikwd, fusion::vector1<T1> >, Subject, Modifiers> 793 { 794 typedef typename add_const<T1>::type const_keyword; 795 typedef repository::qi::kwd_pass_iterator<int> iterator_type; 796 797 typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type; 798 799 template <typename Terminal> operator ()boost::spirit::qi::make_directive800 result_type operator()( 801 Terminal const& term, Subject const& subject, unused_type) const 802 { 803 typename spirit::detail::get_encoding<Modifiers, 804 spirit::char_encoding::standard>::type encoding; 805 806 return result_type(subject 807 ,fusion::at_c<0>(term.args) 808 ,iterator_type() 809 ,encoding 810 ); 811 } 812 }; 813 814 template <typename T1, typename Subject, typename Modifiers> 815 struct make_directive< 816 terminal_ex<repository::tag::idkwd, fusion::vector1<T1> >, Subject, Modifiers> 817 { 818 typedef typename add_const<T1>::type const_keyword; 819 typedef repository::qi::kwd_pass_iterator<int> iterator_type; 820 821 typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type; 822 823 template <typename Terminal> operator ()boost::spirit::qi::make_directive824 result_type operator()( 825 Terminal const& term, Subject const& subject, unused_type) const 826 { 827 typename spirit::detail::get_encoding<Modifiers, 828 spirit::char_encoding::standard>::type encoding; 829 830 return result_type(subject 831 ,fusion::at_c<0>(term.args) 832 ,iterator_type() 833 ,encoding 834 ); 835 } 836 }; 837 838 // Directive kwd(key,exact)[p] 839 template <typename T> 840 struct make_exact_helper 841 { 842 typedef repository::qi::kwd_exact_iterator<T> iterator_type; 843 template<typename Args> make_iteratorboost::spirit::qi::make_exact_helper844 static iterator_type make_iterator(Args const& args) 845 { 846 return iterator_type(fusion::at_c<1>(args)); 847 } 848 }; 849 850 template <typename T1, typename T2, typename Subject, typename Modifiers> 851 struct make_directive< 852 terminal_ex<repository::tag::kwd, fusion::vector2<T1,T2> >, Subject, Modifiers> 853 { 854 typedef make_directive_internal_2_args< T1 855 , T2 856 , Subject 857 , Modifiers 858 , mpl::false_ 859 , make_exact_helper<T2> 860 > make_directive_type; 861 typedef typename make_directive_type::result_type result_type; 862 template <typename Terminal> operator ()boost::spirit::qi::make_directive863 result_type operator()( 864 Terminal const& term, Subject const& subject, Modifiers const& modifiers) const 865 { 866 867 return make_directive_type()(term,subject, modifiers); 868 } 869 870 }; 871 872 template <typename T1, typename T2, typename Subject, typename Modifiers> 873 struct make_directive< 874 terminal_ex<repository::tag::dkwd, fusion::vector2<T1,T2> >, Subject, Modifiers> 875 { 876 typedef make_directive_internal_2_args< T1 877 , T2 878 , Subject 879 , Modifiers 880 , mpl::true_ 881 , make_exact_helper<T2> 882 > make_directive_type; 883 884 typedef typename make_directive_type::result_type result_type; 885 template <typename Terminal> operator ()boost::spirit::qi::make_directive886 result_type operator()( 887 Terminal const& term, Subject const& subject, Modifiers const& modifiers) const 888 { 889 890 return make_directive_type()(term, subject, modifiers); 891 } 892 893 }; 894 895 896 // Directive ikwd(key,exact)[p] 897 template <typename T1, typename T2, typename Subject, typename Modifiers> 898 struct make_directive< 899 terminal_ex<repository::tag::ikwd, fusion::vector2<T1,T2> >, Subject, Modifiers> 900 { 901 typedef typename add_const<T1>::type const_keyword; 902 typedef repository::qi::kwd_exact_iterator<T2> iterator_type; 903 904 typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type; 905 906 template <typename Terminal> operator ()boost::spirit::qi::make_directive907 result_type operator()( 908 Terminal const& term, Subject const& subject, Modifiers const& /*modifiers*/) const 909 { 910 typename spirit::detail::get_encoding<Modifiers, 911 spirit::char_encoding::standard>::type encoding; 912 return result_type(subject 913 , fusion::at_c<0>(term.args) 914 , fusion::at_c<1>(term.args) 915 , encoding 916 ); 917 } 918 }; 919 920 template <typename T1, typename T2, typename Subject, typename Modifiers> 921 struct make_directive< 922 terminal_ex<repository::tag::idkwd, fusion::vector2<T1,T2> >, Subject, Modifiers> 923 { 924 typedef typename add_const<T1>::type const_keyword; 925 typedef repository::qi::kwd_exact_iterator<T2> iterator_type; 926 927 typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type; 928 929 template <typename Terminal> operator ()boost::spirit::qi::make_directive930 result_type operator()( 931 Terminal const& term, Subject const& subject, Modifiers const& /*modifiers*/) const 932 { 933 typename spirit::detail::get_encoding<Modifiers, 934 spirit::char_encoding::standard>::type encoding; 935 return result_type(subject 936 , fusion::at_c<0>(term.args) 937 , fusion::at_c<1>(term.args) 938 , encoding 939 ); 940 } 941 }; 942 943 944 // Directive kwd(min, max)[p] 945 946 template <typename T> 947 struct make_finite_helper 948 { 949 typedef repository::qi::kwd_finite_iterator<T> iterator_type; 950 template<typename Args> make_iteratorboost::spirit::qi::make_finite_helper951 static iterator_type make_iterator(Args const& args) 952 { 953 return iterator_type(fusion::at_c<1>(args),fusion::at_c<2>(args)); 954 } 955 956 }; 957 958 template <typename T1, typename T2, typename Subject, typename Modifiers> 959 struct make_directive< 960 terminal_ex<repository::tag::kwd, fusion::vector3<T1,T2,T2> >, Subject, Modifiers> 961 { 962 typedef make_directive_internal_2_args< T1 963 , T2 964 , Subject 965 , Modifiers 966 , mpl::false_ 967 , make_finite_helper<T2> 968 > make_directive_type; 969 970 971 typedef typename make_directive_type::result_type result_type; 972 template <typename Terminal> operator ()boost::spirit::qi::make_directive973 result_type operator()( 974 Terminal const& term, Subject const& subject, Modifiers const& modifiers) const 975 { 976 977 return make_directive_type()(term,subject, modifiers); 978 } 979 980 }; 981 982 template <typename T1, typename T2, typename Subject, typename Modifiers> 983 struct make_directive< 984 terminal_ex<repository::tag::dkwd, fusion::vector3<T1,T2,T2> >, Subject, Modifiers> 985 { 986 987 typedef make_directive_internal_2_args< T1 988 , T2 989 , Subject 990 , Modifiers 991 , mpl::true_ 992 , make_finite_helper<T2> 993 > make_directive_type; 994 995 typedef typename make_directive_type::result_type result_type; 996 template <typename Terminal> operator ()boost::spirit::qi::make_directive997 result_type operator()( 998 Terminal const& term, Subject const& subject, Modifiers const& modifiers) const 999 { 1000 1001 return make_directive_type()(term,subject, modifiers); 1002 } 1003 1004 }; 1005 1006 // Directive ikwd(min, max)[p] 1007 template <typename T1, typename T2, typename Subject, typename Modifiers> 1008 struct make_directive< 1009 terminal_ex<repository::tag::ikwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers> 1010 { 1011 typedef typename add_const<T1>::type const_keyword; 1012 typedef repository::qi::kwd_finite_iterator<T2> iterator_type; 1013 1014 typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type; 1015 1016 template <typename Terminal> operator ()boost::spirit::qi::make_directive1017 result_type operator()( 1018 Terminal const& term, Subject const& subject, unused_type) const 1019 { 1020 1021 typename spirit::detail::get_encoding<Modifiers, 1022 spirit::char_encoding::standard>::type encoding; 1023 return result_type(subject, fusion::at_c<0>(term.args), 1024 iterator_type( 1025 fusion::at_c<1>(term.args) 1026 , fusion::at_c<2>(term.args) 1027 , encoding 1028 ) 1029 ); 1030 } 1031 }; 1032 1033 template <typename T1, typename T2, typename Subject, typename Modifiers> 1034 struct make_directive< 1035 terminal_ex<repository::tag::idkwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers> 1036 { 1037 typedef typename add_const<T1>::type const_keyword; 1038 typedef repository::qi::kwd_finite_iterator<T2> iterator_type; 1039 1040 typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type; 1041 1042 template <typename Terminal> operator ()boost::spirit::qi::make_directive1043 result_type operator()( 1044 Terminal const& term, Subject const& subject, unused_type) const 1045 { 1046 1047 typename spirit::detail::get_encoding<Modifiers, 1048 spirit::char_encoding::standard>::type encoding; 1049 return result_type(subject, fusion::at_c<0>(term.args), 1050 iterator_type( 1051 fusion::at_c<1>(term.args) 1052 , fusion::at_c<2>(term.args) 1053 , encoding 1054 ) 1055 ); 1056 } 1057 }; 1058 1059 1060 // Directive kwd(min, inf)[p] 1061 1062 template <typename T> 1063 struct make_infinite_helper 1064 { 1065 typedef repository::qi::kwd_infinite_iterator<T> iterator_type; 1066 template<typename Args> make_iteratorboost::spirit::qi::make_infinite_helper1067 static iterator_type make_iterator(Args const& args) 1068 { 1069 return iterator_type(fusion::at_c<1>(args)); 1070 } 1071 1072 }; 1073 1074 1075 template <typename T1, typename T2, typename Subject, typename Modifiers> 1076 struct make_directive< 1077 terminal_ex<repository::tag::kwd, fusion::vector3<T1,T2,inf_type> >, Subject, Modifiers> 1078 { 1079 typedef make_directive_internal_2_args< T1 1080 , T2 1081 , Subject 1082 , Modifiers 1083 , mpl::false_ 1084 , make_infinite_helper<T2> 1085 > make_directive_type; 1086 1087 typedef typename make_directive_type::result_type result_type; 1088 template <typename Terminal> operator ()boost::spirit::qi::make_directive1089 result_type operator()( 1090 Terminal const& term, Subject const& subject, unused_type) const 1091 { 1092 1093 return make_directive_type()(term,subject, unused_type()); 1094 } 1095 1096 }; 1097 1098 template <typename T1, typename T2, typename Subject, typename Modifiers> 1099 struct make_directive< 1100 terminal_ex<repository::tag::dkwd, fusion::vector3<T1,T2,inf_type> >, Subject, Modifiers> 1101 { 1102 typedef make_directive_internal_2_args< T1 1103 , T2 1104 , Subject 1105 , Modifiers 1106 , mpl::false_ 1107 , make_infinite_helper<T2> 1108 > make_directive_type; 1109 1110 typedef typename make_directive_type::result_type result_type; 1111 template <typename Terminal> operator ()boost::spirit::qi::make_directive1112 result_type operator()( 1113 Terminal const& term, Subject const& subject, unused_type) const 1114 { 1115 1116 return make_directive_type()(term,subject, unused_type()); 1117 } 1118 1119 }; 1120 1121 1122 // Directive ikwd(min, inf)[p] 1123 template <typename T1, typename T2, typename Subject, typename Modifiers> 1124 struct make_directive< 1125 terminal_ex<repository::tag::ikwd 1126 , fusion::vector3<T1, T2, inf_type> >, Subject, Modifiers> 1127 { 1128 typedef typename add_const<T1>::type const_keyword; 1129 typedef repository::qi::kwd_infinite_iterator<T2> iterator_type; 1130 1131 typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type; 1132 1133 template <typename Terminal> operator ()boost::spirit::qi::make_directive1134 result_type operator()( 1135 Terminal const& term, Subject const& subject, unused_type) const 1136 { 1137 typename spirit::detail::get_encoding<Modifiers, 1138 spirit::char_encoding::standard>::type encoding; 1139 1140 return result_type(subject 1141 , fusion::at_c<0>(term.args) 1142 , fusion::at_c<1>(term.args) 1143 , encoding 1144 ); 1145 } 1146 }; 1147 1148 template <typename T1, typename T2, typename Subject, typename Modifiers> 1149 struct make_directive< 1150 terminal_ex<repository::tag::idkwd 1151 , fusion::vector3<T1, T2, inf_type> >, Subject, Modifiers> 1152 { 1153 typedef typename add_const<T1>::type const_keyword; 1154 typedef repository::qi::kwd_infinite_iterator<T2> iterator_type; 1155 1156 typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type; 1157 1158 template <typename Terminal> operator ()boost::spirit::qi::make_directive1159 result_type operator()( 1160 Terminal const& term, Subject const& subject, unused_type) const 1161 { 1162 typename spirit::detail::get_encoding<Modifiers, 1163 spirit::char_encoding::standard>::type encoding; 1164 1165 return result_type(subject 1166 , fusion::at_c<0>(term.args) 1167 , fusion::at_c<1>(term.args) 1168 , encoding 1169 ); 1170 } 1171 }; 1172 1173 1174 }}} 1175 1176 namespace boost { namespace spirit { namespace traits 1177 { 1178 template <typename Subject, typename KeywordType 1179 , typename LoopIter, typename NoCase , typename Distinct> 1180 struct has_semantic_action< 1181 repository::qi::kwd_parser< Subject, KeywordType, LoopIter, NoCase, Distinct > > 1182 : unary_has_semantic_action<Subject> {}; 1183 1184 template <typename Subject, typename KeywordType 1185 , typename LoopIter, typename Distinct > 1186 struct has_semantic_action< 1187 repository::qi::complex_kwd_parser< Subject, KeywordType, LoopIter, Distinct > > 1188 : unary_has_semantic_action<Subject> {}; 1189 1190 template <typename Subject, typename KeywordType 1191 , typename LoopIter, typename NoCase, typename Attribute, typename Context 1192 , typename Iterator, typename Distinct> 1193 struct handles_container<repository::qi::kwd_parser<Subject, KeywordType, LoopIter, NoCase, Distinct>, Attribute 1194 , Context, Iterator> 1195 : unary_handles_container<Subject, Attribute, Context, Iterator> {}; 1196 1197 template <typename Subject, typename KeywordType 1198 , typename LoopIter 1199 , typename Attribute, typename Context 1200 , typename Iterator, typename Distinct> 1201 struct handles_container<repository::qi::complex_kwd_parser<Subject, KeywordType, LoopIter, Distinct>, Attribute 1202 , Context, Iterator> 1203 : unary_handles_container<Subject, Attribute, Context, Iterator> {}; 1204 1205 }}} 1206 1207 #if defined(_MSC_VER) 1208 # pragma warning(pop) 1209 #endif 1210 1211 #endif 1212 1213