/Src/Dependencies/Boost/boost/spirit/repository/home/qi/directive/kwd.hpp

http://hadesmem.googlecode.com/ · C++ Header · 588 lines · 442 code · 92 blank · 54 comment · 16 complexity · 2aa45a506ae27c86dba12e802026334d MD5 · raw file

  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/support/container.hpp>
  17. #include <boost/spirit/home/qi/detail/attributes.hpp>
  18. #include <boost/spirit/home/qi/detail/fail_function.hpp>
  19. #include <boost/spirit/home/support/info.hpp>
  20. #include <boost/spirit/repository/home/support/kwd.hpp>
  21. #include <boost/fusion/include/at.hpp>
  22. #include <boost/foreach.hpp>
  23. #include <vector>
  24. namespace boost { namespace spirit
  25. {
  26. ///////////////////////////////////////////////////////////////////////////
  27. // Enablers
  28. ///////////////////////////////////////////////////////////////////////////
  29. template < typename T>
  30. struct use_directive<qi::domain
  31. , terminal_ex<repository::tag::kwd // enables kwd(key)[p]
  32. , fusion::vector1<T > >
  33. > : traits::is_string<T> {};
  34. template < typename T>
  35. struct use_directive<qi::domain
  36. , terminal_ex<repository::tag::ikwd // enables ikwd(key)[p]
  37. , fusion::vector1<T > >
  38. > : traits::is_string<T> {};
  39. template < typename T1, typename T2>
  40. struct use_directive<qi::domain
  41. , terminal_ex<repository::tag::kwd // enables kwd(key,exact)[p]
  42. , fusion::vector2< T1, T2 > >
  43. > : traits::is_string<T1> {};
  44. template < typename T1, typename T2>
  45. struct use_directive<qi::domain
  46. , terminal_ex<repository::tag::ikwd // enables ikwd(key,exact)[p]
  47. , fusion::vector2< T1, T2 > >
  48. > : traits::is_string<T1> {};
  49. template < typename T1, typename T2>
  50. struct use_directive<qi::domain
  51. , terminal_ex<repository::tag::kwd // enables kwd(min, max)[p]
  52. , fusion::vector3< T1, T2, T2 > >
  53. > : traits::is_string<T1> {};
  54. template < typename T1, typename T2>
  55. struct use_directive<qi::domain
  56. , terminal_ex<repository::tag::ikwd // enables ikwd(min, max)[p]
  57. , fusion::vector3< T1, T2, T2 > >
  58. > : traits::is_string<T1> {};
  59. template < typename T1, typename T2>
  60. struct use_directive<qi::domain
  61. , terminal_ex<repository::tag::kwd // enables kwd(min, inf)[p]
  62. , fusion::vector3<T1, T2, inf_type > >
  63. > : traits::is_string<T1> {};
  64. template < typename T1, typename T2>
  65. struct use_directive<qi::domain
  66. , terminal_ex<repository::tag::ikwd // enables ikwd(min, inf)[p]
  67. , fusion::vector3<T1, T2, inf_type > >
  68. > : traits::is_string<T1> {};
  69. /* template <> // enables *lazy* kwd(exact)[p]
  70. struct use_lazy_directive<
  71. qi::domain
  72. , tag::kwd
  73. , 1 // arity
  74. > : mpl::true_ {};
  75. template <> // enables *lazy* kwd(min, max)[p]
  76. struct use_lazy_directive< // and kwd(min, inf)[p]
  77. qi::domain
  78. , tag::kwd
  79. , 2 // arity
  80. > : mpl::true_ {};
  81. */
  82. }}
  83. namespace boost { namespace spirit { namespace repository { namespace qi
  84. {
  85. using repository::kwd;
  86. using repository::ikwd;
  87. using spirit::inf;
  88. using spirit::inf_type;
  89. template <typename T>
  90. struct kwd_pass_iterator // handles kwd(exact)[p]
  91. {
  92. kwd_pass_iterator() {}
  93. bool flag_init() const { return true; }
  94. bool register_successful_parse(bool &flag,T &i) const {
  95. flag=true;
  96. return true;
  97. }
  98. private:
  99. // silence MSVC warning C4512: assignment operator could not be generated
  100. kwd_pass_iterator& operator= (kwd_pass_iterator const&);
  101. };
  102. template <typename T>
  103. struct kwd_exact_iterator // handles kwd(exact)[p]
  104. {
  105. kwd_exact_iterator(T const exact)
  106. : exact(exact){}
  107. typedef T type;
  108. bool flag_init() const { return false; }
  109. bool register_successful_parse(bool &flag,T &i) const {
  110. i++;
  111. if(i<exact)
  112. {
  113. flag=false;
  114. return true;
  115. }
  116. else if(i==exact)
  117. {
  118. flag=true;
  119. return true;
  120. }
  121. else
  122. return flag=false;
  123. }
  124. T const exact;
  125. private:
  126. // silence MSVC warning C4512: assignment operator could not be generated
  127. kwd_exact_iterator& operator= (kwd_exact_iterator const&);
  128. };
  129. template <typename T>
  130. struct kwd_finite_iterator // handles kwd(min, max)[p]
  131. {
  132. kwd_finite_iterator(T const min, T const max)
  133. : min BOOST_PREVENT_MACRO_SUBSTITUTION (min)
  134. , max BOOST_PREVENT_MACRO_SUBSTITUTION (max)
  135. {}
  136. typedef T type;
  137. bool flag_init() const { return min==0; }
  138. bool register_successful_parse(bool &flag,T &i) const {
  139. i++;
  140. if(i<min)
  141. {
  142. flag=false;
  143. return true;
  144. }
  145. else if(i>=min && i<=max)
  146. {
  147. return flag=true;
  148. }
  149. else
  150. return flag=false;
  151. }
  152. T const min;
  153. T const max;
  154. private:
  155. // silence MSVC warning C4512: assignment operator could not be generated
  156. kwd_finite_iterator& operator= (kwd_finite_iterator const&);
  157. };
  158. template <typename T>
  159. struct kwd_infinite_iterator // handles kwd(min, inf)[p]
  160. {
  161. kwd_infinite_iterator(T const min)
  162. : min BOOST_PREVENT_MACRO_SUBSTITUTION (min) {}
  163. typedef T type;
  164. bool flag_init() const { return min==0; }
  165. bool register_successful_parse(bool &flag,T &i) const {
  166. i++;
  167. flag = i>=min;
  168. return true;
  169. }
  170. T const min;
  171. private:
  172. // silence MSVC warning C4512: assignment operator could not be generated
  173. kwd_infinite_iterator& operator= (kwd_infinite_iterator const&);
  174. };
  175. // This class enables the transportation of parameters needed to call
  176. // the occurence constraint checker from higher level calls
  177. // It also serves to select the correct parse function call
  178. // of the keyword parser. The implementation changes depending if it is
  179. // called form a keyword parsing loop or not.
  180. template <typename Skipper, typename NoCasePass>
  181. struct skipper_keyword_marker
  182. {
  183. typedef NoCasePass no_case_pass;
  184. skipper_keyword_marker(Skipper const &skipper,bool &flag,int &counter) :
  185. skipper(skipper)
  186. , flag(flag)
  187. , counter(counter)
  188. {}
  189. const Skipper &skipper;
  190. bool &flag;
  191. int &counter;
  192. };
  193. template <typename Subject, typename KeywordType, typename LoopIter , typename NoCase >
  194. struct kwd_parser : spirit::qi::unary_parser<kwd_parser<Subject, KeywordType, LoopIter , NoCase > >
  195. {
  196. struct kwd_parser_id;
  197. typedef Subject subject_type;
  198. typedef NoCase no_case_keyword;
  199. typedef typename
  200. remove_const<typename traits::char_type_of<KeywordType>::type>::type
  201. char_type;
  202. typedef std::basic_string<char_type> keyword_type;
  203. template <typename Context, typename Iterator>
  204. struct attribute
  205. {
  206. typedef typename
  207. traits::build_std_vector<
  208. typename traits::attribute_of<
  209. Subject, Context, Iterator>::type
  210. >::type
  211. type;
  212. };
  213. kwd_parser(Subject const& subject
  214. , typename add_reference<KeywordType>::type keyword
  215. , LoopIter const& iter)
  216. : subject(subject), iter(iter), keyword(keyword) {}
  217. // Call the subject parser on a non container attribute
  218. template <typename Iterator, typename Context
  219. , typename Skipper, typename Attribute>
  220. bool parse_impl(Iterator& first, Iterator const& last
  221. , Context& context, Skipper const& skipper
  222. , Attribute& attr,mpl::false_) const
  223. {
  224. return subject.parse(first,last,context,skipper,attr);
  225. }
  226. // Call the subject parser on a container attribute
  227. template <typename Iterator, typename Context
  228. , typename Skipper, typename Attribute>
  229. bool parse_impl(Iterator& first, Iterator const& last
  230. , Context& context, Skipper const& skipper
  231. , Attribute& attr,mpl::true_) const
  232. {
  233. // synthesized attribute needs to be default constructed
  234. typename traits::container_value<Attribute>::type val =
  235. typename traits::container_value<Attribute>::type();
  236. Iterator save = first;
  237. bool r = subject.parse(first,last,context,skipper, val);
  238. if (r)
  239. {
  240. // push the parsed value into our attribute
  241. r = traits::push_back(attr, val);
  242. if (!r)
  243. first = save;
  244. }
  245. return r;
  246. }
  247. template <typename Iterator, typename Context
  248. , typename Skipper, typename Attribute,typename NoCasePass>
  249. bool parse(Iterator& first, Iterator const& last
  250. , Context& context, skipper_keyword_marker<Skipper,NoCasePass> const& skipper
  251. , Attribute &attr) const
  252. {
  253. typedef typename traits::attribute_of<
  254. Subject, Context, Iterator>::type
  255. subject_attribute;
  256. typedef typename mpl::and_<
  257. traits::is_container<Attribute>
  258. , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > >
  259. >::type predicate;
  260. if((no_case_keyword::value && NoCasePass::value) || !NoCasePass::value)
  261. {
  262. if(parse_impl(first,last,context,skipper.skipper,attr, predicate()))
  263. return iter.register_successful_parse(skipper.flag,skipper.counter);
  264. }
  265. return false;
  266. }
  267. template <typename Iterator, typename Context
  268. , typename Skipper, typename Attribute>
  269. bool parse(Iterator& first, Iterator const& last
  270. , Context& context, Skipper const& skipper
  271. , Attribute& attr) const
  272. {
  273. typedef typename traits::attribute_of<
  274. Subject, Context, Iterator>::type
  275. subject_attribute;
  276. typedef typename mpl::and_<
  277. traits::is_container<Attribute>
  278. , mpl::not_< traits::is_weak_substitute< subject_attribute,Attribute > >
  279. >::type predicate;
  280. // Parse the keyword
  281. bool flag = iter.flag_init();
  282. int counter = 0;
  283. Iterator save = first;
  284. spirit::qi::skip_over(first, last, skipper);
  285. if(keyword.parse(first,last,context,skipper,unused)){
  286. // Followed by the subject parser
  287. spirit::qi::skip_over(first, last, skipper);
  288. if(parse_impl(first,last,context,skipper,attr, predicate()))
  289. {
  290. return iter.register_successful_parse(flag,counter);
  291. }
  292. }
  293. first = save;
  294. return flag;
  295. }
  296. template <typename Context>
  297. info what(Context& context) const
  298. {
  299. if(no_case_keyword::value)
  300. return info("ikwd", subject.what(context));
  301. else
  302. return info("kwd", subject.what(context));
  303. }
  304. Subject subject;
  305. LoopIter iter;
  306. spirit::qi::literal_string<KeywordType, true> keyword;
  307. private:
  308. // silence MSVC warning C4512: assignment operator could not be generated
  309. kwd_parser& operator= (kwd_parser const&);
  310. template <typename Iterator, typename Context, typename Skipper>
  311. static spirit::qi::detail::fail_function<Iterator, Context, Skipper>
  312. fail_function(
  313. Iterator& first, Iterator const& last
  314. , Context& context, Skipper const& skipper)
  315. {
  316. return spirit::qi::detail::fail_function<Iterator, Context, Skipper>
  317. (first, last, context, skipper);
  318. }
  319. };
  320. }}}}
  321. ///////////////////////////////////////////////////////////////////////////////
  322. namespace boost { namespace spirit { namespace qi
  323. {
  324. ///////////////////////////////////////////////////////////////////////////
  325. // Parser generators: make_xxx function (objects)
  326. ///////////////////////////////////////////////////////////////////////////
  327. // Directive kwd(key)[p]
  328. template <typename T1, typename Subject, typename Modifiers>
  329. struct make_directive<
  330. terminal_ex<repository::tag::kwd, fusion::vector1<T1> >, Subject, Modifiers>
  331. {
  332. typedef typename add_const<T1>::type const_keyword;
  333. typedef repository::qi::kwd_pass_iterator<int> iterator_type;
  334. typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
  335. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
  336. template <typename Terminal>
  337. result_type operator()(
  338. Terminal const& term, Subject const& subject, unused_type) const
  339. {
  340. return result_type(subject
  341. ,fusion::at_c<0>(term.args)
  342. ,iterator_type()
  343. );
  344. }
  345. };
  346. // Directive ikwd(key)[p]
  347. template <typename T1, typename Subject, typename Modifiers>
  348. struct make_directive<
  349. terminal_ex<repository::tag::ikwd, fusion::vector1<T1> >, Subject, Modifiers>
  350. {
  351. typedef typename add_const<T1>::type const_keyword;
  352. typedef repository::qi::kwd_pass_iterator<int> iterator_type;
  353. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
  354. template <typename Terminal>
  355. result_type operator()(
  356. Terminal const& term, Subject const& subject, unused_type) const
  357. {
  358. /* typename spirit::detail::get_encoding<Modifiers,
  359. spirit::char_encoding::standard>::type encoding;*/
  360. return result_type(subject
  361. ,fusion::at_c<0>(term.args)
  362. ,iterator_type()
  363. );
  364. }
  365. };
  366. // Directive kwd(key,exact)[p]
  367. template <typename T1, typename T2, typename Subject, typename Modifiers>
  368. struct make_directive<
  369. terminal_ex<repository::tag::kwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
  370. {
  371. typedef typename add_const<T1>::type const_keyword;
  372. typedef repository::qi::kwd_exact_iterator<T2> iterator_type;
  373. typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
  374. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
  375. template <typename Terminal>
  376. result_type operator()(
  377. Terminal const& term, Subject const& subject, unused_type) const
  378. {
  379. return result_type(subject
  380. ,fusion::at_c<0>(term.args)
  381. ,fusion::at_c<1>(term.args)
  382. );
  383. }
  384. };
  385. // Directive ikwd(key,exact)[p]
  386. template <typename T1, typename T2, typename Subject, typename Modifiers>
  387. struct make_directive<
  388. terminal_ex<repository::tag::ikwd, fusion::vector2<T1,T2> >, Subject, Modifiers>
  389. {
  390. typedef typename add_const<T1>::type const_keyword;
  391. typedef repository::qi::kwd_exact_iterator<T2> iterator_type;
  392. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
  393. template <typename Terminal>
  394. result_type operator()(
  395. Terminal const& term, Subject const& subject, unused_type) const
  396. {
  397. return result_type(subject
  398. , fusion::at_c<0>(term.args)
  399. , fusion::at_c<1>(term.args)
  400. );
  401. }
  402. };
  403. // Directive kwd(min, max)[p]
  404. template <typename T1, typename T2, typename Subject, typename Modifiers>
  405. struct make_directive<
  406. terminal_ex<repository::tag::kwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers>
  407. {
  408. typedef typename add_const<T1>::type const_keyword;
  409. typedef repository::qi::kwd_finite_iterator<T2> iterator_type;
  410. typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
  411. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
  412. template <typename Terminal>
  413. result_type operator()(
  414. Terminal const& term, Subject const& subject, unused_type) const
  415. {
  416. return result_type(subject, fusion::at_c<0>(term.args),
  417. iterator_type(
  418. fusion::at_c<1>(term.args)
  419. , fusion::at_c<2>(term.args)
  420. )
  421. );
  422. }
  423. };
  424. // Directive ikwd(min, max)[p]
  425. template <typename T1, typename T2, typename Subject, typename Modifiers>
  426. struct make_directive<
  427. terminal_ex<repository::tag::ikwd, fusion::vector3< T1, T2, T2> >, Subject, Modifiers>
  428. {
  429. typedef typename add_const<T1>::type const_keyword;
  430. typedef repository::qi::kwd_finite_iterator<T2> iterator_type;
  431. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
  432. template <typename Terminal>
  433. result_type operator()(
  434. Terminal const& term, Subject const& subject, unused_type) const
  435. {
  436. return result_type(subject, fusion::at_c<0>(term.args),
  437. iterator_type(
  438. fusion::at_c<1>(term.args)
  439. , fusion::at_c<2>(term.args)
  440. )
  441. );
  442. }
  443. };
  444. // Directive kwd(min, inf)[p]
  445. template <typename T1, typename T2, typename Subject, typename Modifiers>
  446. struct make_directive<
  447. terminal_ex<repository::tag::kwd
  448. , fusion::vector3<T1, T2, inf_type> >, Subject, Modifiers>
  449. {
  450. typedef typename add_const<T1>::type const_keyword;
  451. typedef repository::qi::kwd_infinite_iterator<T2> iterator_type;
  452. typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case;
  453. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, no_case > result_type;
  454. template <typename Terminal>
  455. result_type operator()(
  456. Terminal const& term, Subject const& subject, unused_type) const
  457. {
  458. return result_type(subject
  459. , fusion::at_c<0>(term.args)
  460. , fusion::at_c<1>(term.args)
  461. );
  462. }
  463. };
  464. // Directive ikwd(min, inf)[p]
  465. template <typename T1, typename T2, typename Subject, typename Modifiers>
  466. struct make_directive<
  467. terminal_ex<repository::tag::ikwd
  468. , fusion::vector3<T1, T2, inf_type> >, Subject, Modifiers>
  469. {
  470. typedef typename add_const<T1>::type const_keyword;
  471. typedef repository::qi::kwd_infinite_iterator<T2> iterator_type;
  472. typedef repository::qi::kwd_parser<Subject, const_keyword, iterator_type, mpl::true_ > result_type;
  473. template <typename Terminal>
  474. result_type operator()(
  475. Terminal const& term, Subject const& subject, unused_type) const
  476. {
  477. typename spirit::detail::get_encoding<Modifiers,
  478. spirit::char_encoding::standard>::type encoding;
  479. return result_type(subject
  480. , fusion::at_c<0>(term.args)
  481. , fusion::at_c<1>(term.args)
  482. );
  483. }
  484. };
  485. }}}
  486. namespace boost { namespace spirit { namespace traits
  487. {
  488. template <typename Subject, typename KeywordType
  489. , typename LoopIter, typename NoCase >
  490. struct has_semantic_action<
  491. repository::qi::kwd_parser< Subject, KeywordType, LoopIter, NoCase > >
  492. : unary_has_semantic_action<Subject> {};
  493. }}}
  494. #endif