kwd.hpp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2011 Thomas Bernard
  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. #ifndef BOOST_SPIRIT_REPOSITORY_QI_DIRECTIVE_KWD_HPP
  8. #define BOOST_SPIRIT_REPOSITORY_QI_DIRECTIVE_KWD_HPP
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/spirit/home/qi/meta_compiler.hpp>
  13. #include <boost/spirit/home/qi/parser.hpp>
  14. #include <boost/spirit/home/qi/auxiliary/lazy.hpp>
  15. #include <boost/spirit/home/qi/operator/kleene.hpp>
  16. #include <boost/spirit/home/qi/string/lit.hpp>
  17. #include <boost/spirit/home/support/container.hpp>
  18. #include <boost/spirit/home/qi/detail/attributes.hpp>
  19. #include <boost/spirit/home/qi/detail/fail_function.hpp>
  20. #include <boost/spirit/home/support/info.hpp>
  21. #include <boost/spirit/repository/home/support/kwd.hpp>
  22. #include <boost/fusion/include/at.hpp>
  23. #include <vector>
  24. #if defined(_MSC_VER)
  25. # pragma warning(push)
  26. # pragma warning(disable: 4127) // conditional expression is constant
  27. # pragma warning(disable: 4512) // assignment operator could not be generated.
  28. #endif
  29. namespace boost { namespace spirit
  30. {
  31. ///////////////////////////////////////////////////////////////////////////
  32. // Enablers
  33. ///////////////////////////////////////////////////////////////////////////
  34. template < typename T>
  35. struct use_directive<qi::domain
  36. , terminal_ex<repository::tag::kwd // enables kwd(key)[p]
  37. , fusion::vector1<T > >
  38. > : mpl::true_ {};
  39. template < typename T>
  40. struct use_directive<qi::domain
  41. , terminal_ex<repository::tag::ikwd // enables ikwd(key)[p]
  42. , fusion::vector1<T > >
  43. > : mpl::true_ {};
  44. template < typename T>
  45. struct use_directive<qi::domain
  46. , terminal_ex<repository::tag::dkwd // enables dkwd(key)[p]
  47. , fusion::vector1<T > >
  48. > : mpl::true_ {};
  49. template < typename T>
  50. struct use_directive<qi::domain
  51. , terminal_ex<repository::tag::idkwd // enables idkwd(key)[p]
  52. , fusion::vector1<T > >
  53. > : mpl::true_ {};
  54. template < typename T1, typename T2>
  55. struct use_directive<qi::domain
  56. , terminal_ex<repository::tag::kwd // enables kwd(key,exact)[p]
  57. , fusion::vector2< T1, T2 > >
  58. > : mpl::true_ {};
  59. template < typename T1, typename T2>
  60. struct use_directive<qi::domain
  61. , terminal_ex<repository::tag::ikwd // enables ikwd(key,exact)[p]
  62. , fusion::vector2< T1, T2 > >
  63. > : mpl::true_ {};
  64. template < typename T1, typename T2>
  65. struct use_directive<qi::domain
  66. , terminal_ex<repository::tag::dkwd // enables dkwd(key,exact)[p]
  67. , fusion::vector2< T1, T2 > >
  68. > : mpl::true_ {};
  69. template < typename T1, typename T2>
  70. struct use_directive<qi::domain
  71. , terminal_ex<repository::tag::idkwd // enables idkwd(key,exact)[p]
  72. , fusion::vector2< T1, T2 > >
  73. > : mpl::true_ {};
  74. template < typename T1, typename T2>
  75. struct use_directive<qi::domain
  76. , terminal_ex<repository::tag::kwd // enables kwd(min, max)[p]
  77. , fusion::vector3< T1, T2, T2 > >
  78. > : mpl::true_ {};
  79. template < typename T1, typename T2>
  80. struct use_directive<qi::domain
  81. , terminal_ex<repository::tag::ikwd // enables ikwd(min, max)[p]
  82. , fusion::vector3< T1, T2, T2 > >
  83. > : mpl::true_ {};
  84. template < typename T1, typename T2>
  85. struct use_directive<qi::domain
  86. , terminal_ex<repository::tag::dkwd // enables dkwd(min, max)[p]
  87. , fusion::vector3< T1, T2, T2 > >
  88. > : mpl::true_ {};
  89. template < typename T1, typename T2>
  90. struct use_directive<qi::domain
  91. , terminal_ex<repository::tag::idkwd // enables idkwd(min, max)[p]
  92. , fusion::vector3< T1, T2, T2 > >
  93. > : mpl::true_ {};
  94. template < typename T1, typename T2>
  95. struct use_directive<qi::domain
  96. , terminal_ex<repository::tag::kwd // enables kwd(min, inf)[p]
  97. , fusion::vector3<T1, T2, inf_type > >
  98. > : mpl::true_ {};
  99. template < typename T1, typename T2>
  100. struct use_directive<qi::domain
  101. , terminal_ex<repository::tag::ikwd // enables ikwd(min, inf)[p]
  102. , fusion::vector3<T1, T2, inf_type > >
  103. > : mpl::true_ {};
  104. template < typename T1, typename T2>
  105. struct use_directive<qi::domain
  106. , terminal_ex<repository::tag::dkwd // enables dkwd(min, inf)[p]
  107. , fusion::vector3<T1, T2, inf_type > >
  108. > : mpl::true_ {};
  109. template < typename T1, typename T2>
  110. struct use_directive<qi::domain
  111. , terminal_ex<repository::tag::idkwd // enables idkwd(min, inf)[p]
  112. , fusion::vector3<T1, T2, inf_type > >
  113. > : mpl::true_ {};
  114. /* template <> // enables *lazy* kwd(exact)[p]
  115. struct use_lazy_directive<
  116. qi::domain
  117. , tag::kwd
  118. , 1 // arity
  119. > : mpl::true_ {};
  120. template <> // enables *lazy* kwd(min, max)[p]
  121. struct use_lazy_directive< // and kwd(min, inf)[p]
  122. qi::domain
  123. , tag::kwd
  124. , 2 // arity
  125. > : mpl::true_ {};
  126. */
  127. }}
  128. namespace boost { namespace spirit { namespace repository { namespace qi
  129. {
  130. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  131. using repository::kwd;
  132. using repository::ikwd;
  133. using repository::dkwd;
  134. using repository::idkwd;
  135. using spirit::inf;
  136. #endif
  137. using repository::kwd_type;
  138. using repository::ikwd_type;
  139. using repository::dkwd_type;
  140. using repository::idkwd_type;
  141. using spirit::inf_type;
  142. template <typename T>
  143. struct kwd_pass_iterator // handles kwd(exact)[p]
  144. {
  145. kwd_pass_iterator() {}
  146. bool flag_init() const { return true; }
  147. bool register_successful_parse(bool &flag,T &/*i*/) const {
  148. flag=true;
  149. return true;
  150. }
  151. };
  152. template <typename T>
  153. struct kwd_exact_iterator // handles kwd(exact)[p]
  154. {
  155. kwd_exact_iterator(T const exact)
  156. : exact(exact){}
  157. typedef T type;
  158. bool flag_init() const { return false; }
  159. bool register_successful_parse(bool &flag,T &i) const {
  160. i++;
  161. if(i<exact)
  162. {
  163. flag=false;
  164. return true;
  165. }
  166. else if(i==exact)
  167. {
  168. flag=true;
  169. return true;
  170. }
  171. else
  172. return flag=false;
  173. }
  174. T const exact;
  175. };
  176. template <typename T>
  177. struct kwd_finite_iterator // handles kwd(min, max)[p]
  178. {
  179. kwd_finite_iterator(T const min, T const max)
  180. : min BOOST_PREVENT_MACRO_SUBSTITUTION (min)
  181. , max BOOST_PREVENT_MACRO_SUBSTITUTION (max)
  182. {}
  183. typedef T type;
  184. bool flag_init() const { return min==0; }
  185. bool register_successful_parse(bool &flag,T &i) const {
  186. i++;
  187. if(i<min)
  188. {
  189. flag=false;
  190. return true;
  191. }
  192. else if(i>=min && i<=max)
  193. {
  194. return flag=true;
  195. }
  196. else
  197. return flag=false;
  198. }
  199. T const min;
  200. T const max;
  201. };
  202. template <typename T>
  203. struct kwd_infinite_iterator // handles kwd(min, inf)[p]
  204. {
  205. kwd_infinite_iterator(T const min)
  206. : min BOOST_PREVENT_MACRO_SUBSTITUTION (min) {}
  207. typedef T type;
  208. bool flag_init() const { return min==0; }
  209. bool register_successful_parse(bool &flag,T &i) const {
  210. i++;
  211. flag = i>=min;
  212. return true;
  213. }
  214. T const min;
  215. };
  216. // This class enables the transportation of parameters needed to call
  217. // the occurrence constraint checker from higher level calls
  218. // It also serves to select the correct parse function call
  219. // of the keyword parser. The implementation changes depending if it is
  220. // called form a keyword parsing loop or not.
  221. template <typename Skipper, typename NoCasePass>
  222. struct skipper_keyword_marker
  223. {
  224. typedef NoCasePass no_case_pass;
  225. skipper_keyword_marker(Skipper const &skipper,bool &flag,int &counter) :
  226. skipper(skipper)
  227. , flag(flag)
  228. , counter(counter)
  229. {}
  230. const Skipper &skipper;
  231. bool &flag;
  232. int &counter;
  233. };
  234. template <typename Subject, typename KeywordType, typename LoopIter , typename NoCase, typename Distinct >
  235. struct kwd_parser : spirit::qi::unary_parser<kwd_parser<Subject, KeywordType, LoopIter , NoCase, Distinct > >
  236. {
  237. struct kwd_parser_id;
  238. typedef Subject subject_type;
  239. typedef NoCase no_case_keyword;
  240. typedef Distinct distinct;
  241. typedef typename
  242. remove_const<typename traits::char_type_of<KeywordType>::type>::type
  243. char_type;
  244. typedef std::basic_string<char_type> keyword_type;
  245. template <typename Context, typename Iterator>
  246. struct attribute
  247. {
  248. typedef typename
  249. traits::build_std_vector<
  250. typename traits::attribute_of<
  251. Subject, Context, Iterator>::type
  252. >::type
  253. type;
  254. };
  255. kwd_parser(Subject const& subject
  256. , typename add_reference<KeywordType>::type keyword
  257. , LoopIter const& iter)
  258. : subject(subject), iter(iter), keyword(keyword) {}
  259. template<typename CharEncoding>
  260. kwd_parser(Subject const& subject
  261. , typename add_reference<KeywordType>::type keyword
  262. , LoopIter const& iter, CharEncoding encoding)
  263. : subject(subject), iter(iter), keyword(keyword,encoding) {}
  264. // Call the subject parser on a non container attribute
  265. template <typename Iterator, typename Context
  266. , typename Skipper, typename Attribute>
  267. bool parse_impl(Iterator& first, Iterator const& last
  268. , Context& context, Skipper const& skipper
  269. , Attribute& attr,mpl::false_) const
  270. {
  271. return subject.parse(first,last,context,skipper,attr);
  272. }
  273. // Call the subject parser on a container attribute
  274. template <typename Iterator, typename Context
  275. , typename Skipper, typename Attribute>
  276. bool parse_impl(Iterator& first, Iterator const& last
  277. , Context& context, Skipper const& skipper
  278. , Attribute& attr,mpl::true_) const
  279. {
  280. // synthesized attribute needs to be default constructed
  281. typename traits::container_value<Attribute>::type val =
  282. typename traits::container_value<Attribute>::type();
  283. Iterator save = first;
  284. bool r = subject.parse(first,last,context,skipper, val);
  285. if (r)
  286. {
  287. // push the parsed value into our attribute
  288. r = traits::push_back(attr, val);
  289. if (!r)
  290. first = save;
  291. }
  292. return r;
  293. }
  294. template <typename Iterator, typename Context
  295. , typename Skipper, typename Attribute,typename NoCasePass>
  296. bool parse(Iterator& first, Iterator const& last
  297. , Context& context, skipper_keyword_marker<Skipper,NoCasePass> const& skipper
  298. , Attribute &attr) const
  299. {
  300. typedef typename traits::attribute_of<
  301. Subject, Context, Iterator>::type
  302. subject_attribute;
  303. typedef typename mpl::and_<
  304. traits::is_container<Attribute>
  305. , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > >
  306. >::type predicate;
  307. if((no_case_keyword::value && NoCasePass::value) || !NoCasePass::value)
  308. {
  309. if(parse_impl(first,last,context,skipper.skipper,attr, predicate()))
  310. return iter.register_successful_parse(skipper.flag,skipper.counter);
  311. }
  312. return false;
  313. }
  314. template <typename Iterator, typename Context
  315. , typename Skipper, typename Attribute>
  316. bool parse(Iterator& first, Iterator const& last
  317. , Context& context, Skipper const& skipper
  318. , Attribute& attr) const
  319. {
  320. typedef typename traits::attribute_of<
  321. Subject, Context, Iterator>::type
  322. subject_attribute;
  323. typedef typename mpl::and_<
  324. traits::is_container<Attribute>
  325. , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > >
  326. >::type predicate;
  327. // Parse the keyword
  328. bool flag = iter.flag_init();
  329. int counter = 0;
  330. Iterator save = first;
  331. spirit::qi::skip_over(first, last, skipper);
  332. if(keyword.parse(first,last,context,skipper,unused)){
  333. if((!distinct::value) || skipper.parse(first,last,unused,unused,unused)){
  334. // Followed by the subject parser
  335. spirit::qi::skip_over(first, last, skipper);
  336. if(parse_impl(first,last,context,skipper,attr, predicate()))
  337. {
  338. return iter.register_successful_parse(flag,counter);
  339. }
  340. }
  341. }
  342. first = save;
  343. return flag;
  344. }
  345. template <typename Context>
  346. info what(Context& context) const
  347. {
  348. if(distinct::value){
  349. if(no_case_keyword::value)
  350. return info("idkwd", subject.what(context));
  351. else
  352. return info("dkwd", subject.what(context));
  353. }
  354. else
  355. {
  356. if(no_case_keyword::value)
  357. return info("ikwd", subject.what(context));
  358. else
  359. return info("kwd", subject.what(context));
  360. }
  361. }
  362. Subject subject;
  363. LoopIter iter;
  364. typedef typename mpl::if_<
  365. no_case_keyword,
  366. spirit::qi::no_case_literal_string< KeywordType, true>,
  367. spirit::qi::literal_string<KeywordType, true> >::type keyword_string_type;
  368. keyword_string_type keyword;
  369. private:
  370. template <typename Iterator, typename Context, typename Skipper>
  371. static spirit::qi::detail::fail_function<Iterator, Context, Skipper>
  372. fail_function(
  373. Iterator& first, Iterator const& last
  374. , Context& context, Skipper const& skipper)
  375. {
  376. return spirit::qi::detail::fail_function<Iterator, Context, Skipper>
  377. (first, last, context, skipper);
  378. }
  379. };
  380. template <typename Subject, typename KeywordType, typename LoopIter, typename Distinct>
  381. struct complex_kwd_parser : spirit::qi::unary_parser<complex_kwd_parser<Subject, KeywordType, LoopIter, Distinct > >
  382. {
  383. struct complex_kwd_parser_id;
  384. typedef Subject subject_type;
  385. typedef Distinct distinct;
  386. template <typename Context, typename Iterator>
  387. struct attribute
  388. {
  389. typedef typename
  390. traits::build_std_vector<
  391. typename traits::attribute_of<
  392. Subject, Context, Iterator>::type
  393. >::type
  394. type;
  395. };
  396. complex_kwd_parser(Subject const& subject
  397. , typename add_reference<KeywordType>::type keyword
  398. , LoopIter const& iter)
  399. : subject(subject), iter(iter), keyword(keyword) {}
  400. // Call the subject parser on a non container attribute
  401. template <typename Iterator, typename Context
  402. , typename Skipper, typename Attribute>
  403. bool parse_impl(Iterator& first, Iterator const& last
  404. , Context& context, Skipper const& skipper
  405. , Attribute& attr,mpl::false_) const
  406. {
  407. return subject.parse(first,last,context,skipper,attr);
  408. }
  409. // Call the subject parser on a container attribute
  410. template <typename Iterator, typename Context
  411. , typename Skipper, typename Attribute>
  412. bool parse_impl(Iterator& first, Iterator const& last
  413. , Context& context, Skipper const& skipper
  414. , Attribute& attr,mpl::true_) const
  415. {
  416. // synthesized attribute needs to be default constructed
  417. typename traits::container_value<Attribute>::type val =
  418. typename traits::container_value<Attribute>::type();
  419. Iterator save = first;
  420. bool r = subject.parse(first,last,context,skipper, val);
  421. if (r)
  422. {
  423. // push the parsed value into our attribute
  424. r = traits::push_back(attr, val);
  425. if (!r)
  426. first = save;
  427. }
  428. return r;
  429. }
  430. template <typename Iterator, typename Context
  431. , typename Skipper, typename Attribute,typename NoCasePass>
  432. bool parse(Iterator& first, Iterator const& last
  433. , Context& context, skipper_keyword_marker<Skipper,NoCasePass> const& skipper
  434. , Attribute &attr) const
  435. {
  436. typedef typename traits::attribute_of<
  437. Subject, Context, Iterator>::type
  438. subject_attribute;
  439. typedef typename mpl::and_<
  440. traits::is_container<Attribute>
  441. , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > >
  442. >::type predicate;
  443. if(parse_impl(first,last,context,skipper.skipper,attr, predicate()))
  444. return iter.register_successful_parse(skipper.flag,skipper.counter);
  445. return false;
  446. }
  447. template <typename Iterator, typename Context
  448. , typename Skipper, typename Attribute>
  449. bool parse(Iterator& first, Iterator const& last
  450. , Context& context, Skipper const& skipper
  451. , Attribute& attr) const
  452. {
  453. typedef typename traits::attribute_of<
  454. Subject, Context, Iterator>::type
  455. subject_attribute;
  456. typedef typename mpl::and_<
  457. traits::is_container<Attribute>
  458. , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > >
  459. >::type predicate;
  460. // Parse the keyword
  461. bool flag = iter.flag_init();
  462. int counter = 0;
  463. Iterator save = first;
  464. spirit::qi::skip_over(first, last, skipper);
  465. if(keyword.parse(first,last,context,skipper,unused)){
  466. if( !distinct::value || skipper.parse(first,last,unused,unused,unused)){
  467. // Followed by the subject parser
  468. spirit::qi::skip_over(first, last, skipper);
  469. if(parse_impl(first,last,context,skipper,attr, predicate()))
  470. {
  471. return iter.register_successful_parse(flag,counter);
  472. }
  473. }
  474. }
  475. first = save;
  476. return flag;
  477. }
  478. template <typename Context>
  479. info what(Context& context) const
  480. {
  481. if(distinct::value)
  482. return info("dkwd", subject.what(context));
  483. else
  484. return info("kwd", subject.what(context));
  485. }
  486. Subject subject;
  487. LoopIter iter;
  488. KeywordType keyword;
  489. private:
  490. template <typename Iterator, typename Context, typename Skipper>
  491. static spirit::qi::detail::fail_function<Iterator, Context, Skipper>
  492. fail_function(
  493. Iterator& first, Iterator const& last
  494. , Context& context, Skipper const& skipper)
  495. {
  496. return spirit::qi::detail::fail_function<Iterator, Context, Skipper>
  497. (first, last, context, skipper);
  498. }
  499. };
  500. }}}}
  501. ///////////////////////////////////////////////////////////////////////////////
  502. namespace boost { namespace spirit { namespace qi
  503. {
  504. ///////////////////////////////////////////////////////////////////////////
  505. // Parser generators: make_xxx function (objects)
  506. ///////////////////////////////////////////////////////////////////////////
  507. template <typename T1, typename T2, typename Subject, typename Modifiers, typename Distinct, typename MakeDirectiveHelper>
  508. struct make_directive_internal_2_args
  509. {
  510. // is the keyword a string keyword ?
  511. typedef typename traits::is_string<T1> is_string_kwd_type;
  512. // make the keyword type
  513. typedef typename mpl::if_< is_string_kwd_type ,
  514. T1 ,
  515. typename result_of::compile<qi::domain, T1>::type
  516. >::type keyword_type;
  517. typedef typename add_const<keyword_type>::type const_keyword;
  518. // select the pass iterator type
  519. typedef typename MakeDirectiveHelper::iterator_type iterator_type;
  520. // determine if a no case modifier applies to the context
  521. typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
  522. // Determine the full type of the kwd / complex_kwd directive
  523. typedef typename
  524. mpl::if_<
  525. is_string_kwd_type,
  526. repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case, Distinct >,
  527. repository::qi::complex_kwd_parser<Subject, const_keyword, iterator_type, Distinct >
  528. >::type result_type;
  529. // Return a kwd parser object
  530. template <typename Terminal>
  531. result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::true_ ) const
  532. {
  533. typename spirit::detail::get_encoding<Modifiers,
  534. spirit::char_encoding::standard>::type encoding;
  535. return result_type(subject
  536. ,MakeDirectiveHelper::make_iterator(term.args)
  537. ,encoding
  538. );
  539. }
  540. template <typename Terminal>
  541. result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::false_ ) const
  542. {
  543. return result_type(subject
  544. ,fusion::at_c<0>(term.args)
  545. ,MakeDirectiveHelper::make_iterator(term.args)
  546. );
  547. }
  548. template <typename Terminal>
  549. result_type create_kwd(Terminal const &term, Subject const & subject, Modifiers const& /*modifiers*/, boost::mpl::true_ ) const
  550. {
  551. return create_kwd_string(term,subject,no_case());
  552. }
  553. // Return a complex_kwd parser object
  554. template <typename Terminal>
  555. result_type create_kwd(Terminal const &term , Subject const & subject, Modifiers const& modifiers, boost::mpl::false_ ) const
  556. {
  557. return result_type(subject
  558. ,compile<qi::domain>(fusion::at_c<0>(term.args),modifiers)
  559. ,MakeDirectiveHelper::make_iterator(term.args)
  560. );
  561. }
  562. // Select which object type to return
  563. template <typename Terminal>
  564. result_type operator()(
  565. Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
  566. {
  567. return create_kwd(term, subject, modifiers, is_string_kwd_type());
  568. }
  569. };
  570. // Directive kwd(key)[p]
  571. template <typename T1, typename Subject, typename Modifiers, typename Distinct>
  572. struct make_directive_internal
  573. {
  574. // is the keyword a string keyword ?
  575. typedef typename traits::is_string<T1> is_string_kwd_type;
  576. // make the keyword type
  577. typedef typename mpl::if_< is_string_kwd_type ,
  578. T1 ,
  579. typename result_of::compile<qi::domain, T1, Modifiers>::type
  580. >::type keyword_type;
  581. typedef typename add_const<keyword_type>::type const_keyword;
  582. // select the pass iterator type
  583. typedef repository::qi::kwd_pass_iterator<int> iterator_type;
  584. // determine if a no case modifier applies to the context
  585. typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
  586. // Determine the full type of the kwd / complex_kwd directive
  587. typedef typename
  588. mpl::if_<
  589. is_string_kwd_type,
  590. repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case, Distinct >,
  591. repository::qi::complex_kwd_parser<Subject, const_keyword, iterator_type, Distinct>
  592. >::type result_type;
  593. // Return a kwd parser object
  594. template <typename Terminal>
  595. result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::true_) const
  596. {
  597. typename spirit::detail::get_encoding<Modifiers,
  598. spirit::char_encoding::standard>::type encoding;
  599. return result_type(subject
  600. ,fusion::at_c<0>(term.args)
  601. ,iterator_type()
  602. ,encoding
  603. );
  604. }
  605. template <typename Terminal>
  606. result_type create_kwd_string(Terminal const &term, Subject const & subject, boost::mpl::false_) const
  607. {
  608. return result_type(subject
  609. ,fusion::at_c<0>(term.args)
  610. ,iterator_type()
  611. );
  612. }
  613. template <typename Terminal>
  614. result_type create_kwd(Terminal const &term, Subject const & subject, Modifiers const& /*modifiers*/, boost::mpl::true_ ) const
  615. {
  616. return create_kwd_string(term,subject,no_case());
  617. }
  618. // Return a complex_kwd parser object
  619. template <typename Terminal>
  620. result_type create_kwd(Terminal const &term , Subject const & subject, Modifiers const& modifiers, boost::mpl::false_ ) const
  621. {
  622. return result_type(subject
  623. ,compile<qi::domain>(fusion::at_c<0>(term.args),modifiers)
  624. ,iterator_type()
  625. );
  626. }
  627. // Select which object type to return
  628. template <typename Terminal>
  629. result_type operator()(
  630. Terminal const& term, Subject const& subject, Modifiers const& modifiers ) const
  631. {
  632. return create_kwd(term, subject, modifiers, is_string_kwd_type());
  633. }
  634. };
  635. template <typename T1, typename Subject, typename Modifiers>
  636. struct make_directive<
  637. terminal_ex<repository::tag::kwd, fusion::vector1<T1> >, Subject, Modifiers>
  638. {
  639. typedef make_directive_internal<T1, Subject, Modifiers, mpl::false_> make_directive_type;
  640. typedef typename make_directive_type::result_type result_type;
  641. template <typename Terminal>
  642. result_type operator()(
  643. Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
  644. {
  645. return make_directive_type()(term, subject, modifiers);
  646. }
  647. };
  648. template <typename T1, typename Subject, typename Modifiers>
  649. struct make_directive<
  650. terminal_ex<repository::tag::dkwd, fusion::vector1<T1> >, Subject, Modifiers>
  651. {
  652. typedef make_directive_internal<T1, Subject, Modifiers, mpl::true_> make_directive_type;
  653. typedef typename make_directive_type::result_type result_type;
  654. template <typename Terminal>
  655. result_type operator()(
  656. Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
  657. {
  658. return make_directive_type()(term, subject, modifiers);
  659. }
  660. };
  661. // Directive ikwd(key)[p]
  662. template <typename T1, typename Subject, typename Modifiers>
  663. struct make_directive<
  664. terminal_ex<repository::tag::ikwd, fusion::vector1<T1> >, Subject, Modifiers>
  665. {
  666. typedef typename add_const<T1>::type const_keyword;
  667. typedef repository::qi::kwd_pass_iterator<int> iterator_type;
  668. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type;
  669. template <typename Terminal>
  670. result_type operator()(
  671. Terminal const& term, Subject const& subject, unused_type) const
  672. {
  673. typename spirit::detail::get_encoding<Modifiers,
  674. spirit::char_encoding::standard>::type encoding;
  675. return result_type(subject
  676. ,fusion::at_c<0>(term.args)
  677. ,iterator_type()
  678. ,encoding
  679. );
  680. }
  681. };
  682. template <typename T1, typename Subject, typename Modifiers>
  683. struct make_directive<
  684. terminal_ex<repository::tag::idkwd, fusion::vector1<T1> >, Subject, Modifiers>
  685. {
  686. typedef typename add_const<T1>::type const_keyword;
  687. typedef repository::qi::kwd_pass_iterator<int> iterator_type;
  688. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type;
  689. template <typename Terminal>
  690. result_type operator()(
  691. Terminal const& term, Subject const& subject, unused_type) const
  692. {
  693. typename spirit::detail::get_encoding<Modifiers,
  694. spirit::char_encoding::standard>::type encoding;
  695. return result_type(subject
  696. ,fusion::at_c<0>(term.args)
  697. ,iterator_type()
  698. ,encoding
  699. );
  700. }
  701. };
  702. // Directive kwd(key,exact)[p]
  703. template <typename T>
  704. struct make_exact_helper
  705. {
  706. typedef repository::qi::kwd_exact_iterator<T> iterator_type;
  707. template<typename Args>
  708. static iterator_type make_iterator(Args const& args)
  709. {
  710. return iterator_type(fusion::at_c<1>(args));
  711. }
  712. };
  713. template <typename T1, typename T2, typename Subject, typename Modifiers>
  714. struct make_directive<
  715. terminal_ex<repository::tag::kwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
  716. {
  717. typedef make_directive_internal_2_args< T1
  718. , T2
  719. , Subject
  720. , Modifiers
  721. , mpl::false_
  722. , make_exact_helper<T2>
  723. > make_directive_type;
  724. typedef typename make_directive_type::result_type result_type;
  725. template <typename Terminal>
  726. result_type operator()(
  727. Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
  728. {
  729. return make_directive_type()(term,subject, modifiers);
  730. }
  731. };
  732. template <typename T1, typename T2, typename Subject, typename Modifiers>
  733. struct make_directive<
  734. terminal_ex<repository::tag::dkwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
  735. {
  736. typedef make_directive_internal_2_args< T1
  737. , T2
  738. , Subject
  739. , Modifiers
  740. , mpl::true_
  741. , make_exact_helper<T2>
  742. > make_directive_type;
  743. typedef typename make_directive_type::result_type result_type;
  744. template <typename Terminal>
  745. result_type operator()(
  746. Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
  747. {
  748. return make_directive_type()(term, subject, modifiers);
  749. }
  750. };
  751. // Directive ikwd(key,exact)[p]
  752. template <typename T1, typename T2, typename Subject, typename Modifiers>
  753. struct make_directive<
  754. terminal_ex<repository::tag::ikwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
  755. {
  756. typedef typename add_const<T1>::type const_keyword;
  757. typedef repository::qi::kwd_exact_iterator<T2> iterator_type;
  758. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type;
  759. template <typename Terminal>
  760. result_type operator()(
  761. Terminal const& term, Subject const& subject, Modifiers const& /*modifiers*/) const
  762. {
  763. typename spirit::detail::get_encoding<Modifiers,
  764. spirit::char_encoding::standard>::type encoding;
  765. return result_type(subject
  766. , fusion::at_c<0>(term.args)
  767. , fusion::at_c<1>(term.args)
  768. , encoding
  769. );
  770. }
  771. };
  772. template <typename T1, typename T2, typename Subject, typename Modifiers>
  773. struct make_directive<
  774. terminal_ex<repository::tag::idkwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
  775. {
  776. typedef typename add_const<T1>::type const_keyword;
  777. typedef repository::qi::kwd_exact_iterator<T2> iterator_type;
  778. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type;
  779. template <typename Terminal>
  780. result_type operator()(
  781. Terminal const& term, Subject const& subject, Modifiers const& /*modifiers*/) const
  782. {
  783. typename spirit::detail::get_encoding<Modifiers,
  784. spirit::char_encoding::standard>::type encoding;
  785. return result_type(subject
  786. , fusion::at_c<0>(term.args)
  787. , fusion::at_c<1>(term.args)
  788. , encoding
  789. );
  790. }
  791. };
  792. // Directive kwd(min, max)[p]
  793. template <typename T>
  794. struct make_finite_helper
  795. {
  796. typedef repository::qi::kwd_finite_iterator<T> iterator_type;
  797. template<typename Args>
  798. static iterator_type make_iterator(Args const& args)
  799. {
  800. return iterator_type(fusion::at_c<1>(args),fusion::at_c<2>(args));
  801. }
  802. };
  803. template <typename T1, typename T2, typename Subject, typename Modifiers>
  804. struct make_directive<
  805. terminal_ex<repository::tag::kwd, fusion::vector3<T1,T2,T2> >, Subject, Modifiers>
  806. {
  807. typedef make_directive_internal_2_args< T1
  808. , T2
  809. , Subject
  810. , Modifiers
  811. , mpl::false_
  812. , make_finite_helper<T2>
  813. > make_directive_type;
  814. typedef typename make_directive_type::result_type result_type;
  815. template <typename Terminal>
  816. result_type operator()(
  817. Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
  818. {
  819. return make_directive_type()(term,subject, modifiers);
  820. }
  821. };
  822. template <typename T1, typename T2, typename Subject, typename Modifiers>
  823. struct make_directive<
  824. terminal_ex<repository::tag::dkwd, fusion::vector3<T1,T2,T2> >, Subject, Modifiers>
  825. {
  826. typedef make_directive_internal_2_args< T1
  827. , T2
  828. , Subject
  829. , Modifiers
  830. , mpl::true_
  831. , make_finite_helper<T2>
  832. > make_directive_type;
  833. typedef typename make_directive_type::result_type result_type;
  834. template <typename Terminal>
  835. result_type operator()(
  836. Terminal const& term, Subject const& subject, Modifiers const& modifiers) const
  837. {
  838. return make_directive_type()(term,subject, modifiers);
  839. }
  840. };
  841. // Directive ikwd(min, max)[p]
  842. template <typename T1, typename T2, typename Subject, typename Modifiers>
  843. struct make_directive<
  844. terminal_ex<repository::tag::ikwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers>
  845. {
  846. typedef typename add_const<T1>::type const_keyword;
  847. typedef repository::qi::kwd_finite_iterator<T2> iterator_type;
  848. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type;
  849. template <typename Terminal>
  850. result_type operator()(
  851. Terminal const& term, Subject const& subject, unused_type) const
  852. {
  853. typename spirit::detail::get_encoding<Modifiers,
  854. spirit::char_encoding::standard>::type encoding;
  855. return result_type(subject, fusion::at_c<0>(term.args),
  856. iterator_type(
  857. fusion::at_c<1>(term.args)
  858. , fusion::at_c<2>(term.args)
  859. , encoding
  860. )
  861. );
  862. }
  863. };
  864. template <typename T1, typename T2, typename Subject, typename Modifiers>
  865. struct make_directive<
  866. terminal_ex<repository::tag::idkwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers>
  867. {
  868. typedef typename add_const<T1>::type const_keyword;
  869. typedef repository::qi::kwd_finite_iterator<T2> iterator_type;
  870. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type;
  871. template <typename Terminal>
  872. result_type operator()(
  873. Terminal const& term, Subject const& subject, unused_type) const
  874. {
  875. typename spirit::detail::get_encoding<Modifiers,
  876. spirit::char_encoding::standard>::type encoding;
  877. return result_type(subject, fusion::at_c<0>(term.args),
  878. iterator_type(
  879. fusion::at_c<1>(term.args)
  880. , fusion::at_c<2>(term.args)
  881. , encoding
  882. )
  883. );
  884. }
  885. };
  886. // Directive kwd(min, inf)[p]
  887. template <typename T>
  888. struct make_infinite_helper
  889. {
  890. typedef repository::qi::kwd_infinite_iterator<T> iterator_type;
  891. template<typename Args>
  892. static iterator_type make_iterator(Args const& args)
  893. {
  894. return iterator_type(fusion::at_c<1>(args));
  895. }
  896. };
  897. template <typename T1, typename T2, typename Subject, typename Modifiers>
  898. struct make_directive<
  899. terminal_ex<repository::tag::kwd, fusion::vector3<T1,T2,inf_type> >, Subject, Modifiers>
  900. {
  901. typedef make_directive_internal_2_args< T1
  902. , T2
  903. , Subject
  904. , Modifiers
  905. , mpl::false_
  906. , make_infinite_helper<T2>
  907. > make_directive_type;
  908. typedef typename make_directive_type::result_type result_type;
  909. template <typename Terminal>
  910. result_type operator()(
  911. Terminal const& term, Subject const& subject, unused_type) const
  912. {
  913. return make_directive_type()(term,subject, unused_type());
  914. }
  915. };
  916. template <typename T1, typename T2, typename Subject, typename Modifiers>
  917. struct make_directive<
  918. terminal_ex<repository::tag::dkwd, fusion::vector3<T1,T2,inf_type> >, Subject, Modifiers>
  919. {
  920. typedef make_directive_internal_2_args< T1
  921. , T2
  922. , Subject
  923. , Modifiers
  924. , mpl::false_
  925. , make_infinite_helper<T2>
  926. > make_directive_type;
  927. typedef typename make_directive_type::result_type result_type;
  928. template <typename Terminal>
  929. result_type operator()(
  930. Terminal const& term, Subject const& subject, unused_type) const
  931. {
  932. return make_directive_type()(term,subject, unused_type());
  933. }
  934. };
  935. // Directive ikwd(min, inf)[p]
  936. template <typename T1, typename T2, typename Subject, typename Modifiers>
  937. struct make_directive<
  938. terminal_ex<repository::tag::ikwd
  939. , fusion::vector3<T1, T2, inf_type> >, Subject, Modifiers>
  940. {
  941. typedef typename add_const<T1>::type const_keyword;
  942. typedef repository::qi::kwd_infinite_iterator<T2> iterator_type;
  943. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::false_ > result_type;
  944. template <typename Terminal>
  945. result_type operator()(
  946. Terminal const& term, Subject const& subject, unused_type) const
  947. {
  948. typename spirit::detail::get_encoding<Modifiers,
  949. spirit::char_encoding::standard>::type encoding;
  950. return result_type(subject
  951. , fusion::at_c<0>(term.args)
  952. , fusion::at_c<1>(term.args)
  953. , encoding
  954. );
  955. }
  956. };
  957. template <typename T1, typename T2, typename Subject, typename Modifiers>
  958. struct make_directive<
  959. terminal_ex<repository::tag::idkwd
  960. , fusion::vector3<T1, T2, inf_type> >, Subject, Modifiers>
  961. {
  962. typedef typename add_const<T1>::type const_keyword;
  963. typedef repository::qi::kwd_infinite_iterator<T2> iterator_type;
  964. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_, mpl::true_ > result_type;
  965. template <typename Terminal>
  966. result_type operator()(
  967. Terminal const& term, Subject const& subject, unused_type) const
  968. {
  969. typename spirit::detail::get_encoding<Modifiers,
  970. spirit::char_encoding::standard>::type encoding;
  971. return result_type(subject
  972. , fusion::at_c<0>(term.args)
  973. , fusion::at_c<1>(term.args)
  974. , encoding
  975. );
  976. }
  977. };
  978. }}}
  979. namespace boost { namespace spirit { namespace traits
  980. {
  981. template <typename Subject, typename KeywordType
  982. , typename LoopIter, typename NoCase , typename Distinct>
  983. struct has_semantic_action<
  984. repository::qi::kwd_parser< Subject, KeywordType, LoopIter, NoCase, Distinct > >
  985. : unary_has_semantic_action<Subject> {};
  986. template <typename Subject, typename KeywordType
  987. , typename LoopIter, typename Distinct >
  988. struct has_semantic_action<
  989. repository::qi::complex_kwd_parser< Subject, KeywordType, LoopIter, Distinct > >
  990. : unary_has_semantic_action<Subject> {};
  991. template <typename Subject, typename KeywordType
  992. , typename LoopIter, typename NoCase, typename Attribute, typename Context
  993. , typename Iterator, typename Distinct>
  994. struct handles_container<repository::qi::kwd_parser<Subject, KeywordType, LoopIter, NoCase, Distinct>, Attribute
  995. , Context, Iterator>
  996. : unary_handles_container<Subject, Attribute, Context, Iterator> {};
  997. template <typename Subject, typename KeywordType
  998. , typename LoopIter
  999. , typename Attribute, typename Context
  1000. , typename Iterator, typename Distinct>
  1001. struct handles_container<repository::qi::complex_kwd_parser<Subject, KeywordType, LoopIter, Distinct>, Attribute
  1002. , Context, Iterator>
  1003. : unary_handles_container<Subject, Attribute, Context, Iterator> {};
  1004. }}}
  1005. #if defined(_MSC_VER)
  1006. # pragma warning(pop)
  1007. #endif
  1008. #endif