kwd.hpp 44 KB

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