advance.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // Copyright (c) 2011 Aaron Graham
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #if !defined(BOOST_SPIRIT_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM)
  6. #define BOOST_SPIRIT_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM
  7. #include <boost/spirit/home/support/terminal.hpp>
  8. #include <boost/spirit/include/qi_parse.hpp>
  9. ///////////////////////////////////////////////////////////////////////////////
  10. // definition the place holder
  11. namespace boost { namespace spirit { namespace repository { namespace qi
  12. {
  13. BOOST_SPIRIT_TERMINAL_EX(advance)
  14. }}}}
  15. ///////////////////////////////////////////////////////////////////////////////
  16. // implementation the enabler
  17. namespace boost { namespace spirit
  18. {
  19. template <typename A0>
  20. struct use_terminal<qi::domain
  21. , terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> > >
  22. : mpl::or_<is_integral<A0>, is_enum<A0> >
  23. {};
  24. template <>
  25. struct use_lazy_terminal<qi::domain, repository::qi::tag::advance, 1>
  26. : mpl::true_
  27. {};
  28. }}
  29. ///////////////////////////////////////////////////////////////////////////////
  30. // implementation of the parser
  31. namespace boost { namespace spirit { namespace repository { namespace qi
  32. {
  33. template <typename Int>
  34. struct advance_parser
  35. : boost::spirit::qi::primitive_parser< advance_parser<Int> >
  36. {
  37. // Define the attribute type exposed by this parser component
  38. template <typename Context, typename Iterator>
  39. struct attribute
  40. {
  41. typedef boost::spirit::unused_type type;
  42. };
  43. advance_parser(Int dist)
  44. : dist(dist)
  45. {}
  46. // This function is called during the actual parsing process
  47. template <typename Iterator, typename Context
  48. , typename Skipper, typename Attribute>
  49. bool parse(Iterator& first, Iterator const& last
  50. , Context&, Skipper&, Attribute&) const
  51. {
  52. // This series of checks is designed to fail parsing on negative
  53. // values, without generating a "expression always evaluates true"
  54. // warning on unsigned types.
  55. if (dist == Int(0)) return true;
  56. if (dist < Int(1)) return false;
  57. typedef typename std::iterator_traits<Iterator>::iterator_category
  58. iterator_category;
  59. return advance(first, last, iterator_category());
  60. }
  61. // This function is called during error handling to create
  62. // a human readable string for the error context.
  63. template <typename Context>
  64. boost::spirit::info what(Context&) const
  65. {
  66. return boost::spirit::info("advance");
  67. }
  68. private:
  69. // this is the general implementation used by most iterator categories
  70. template <typename Iterator, typename IteratorCategory>
  71. bool advance(Iterator& first, Iterator const& last
  72. , IteratorCategory) const
  73. {
  74. Int n = dist;
  75. Iterator i = first;
  76. while (n)
  77. {
  78. if (i == last) return false;
  79. ++i;
  80. --n;
  81. }
  82. first = i;
  83. return true;
  84. }
  85. // this is a specialization for random access iterators
  86. template <typename Iterator>
  87. bool advance(Iterator& first, Iterator const& last
  88. , std::random_access_iterator_tag) const
  89. {
  90. Iterator const it = first + dist;
  91. if (it > last) return false;
  92. first = it;
  93. return true;
  94. }
  95. Int const dist;
  96. };
  97. }}}}
  98. ///////////////////////////////////////////////////////////////////////////////
  99. // instantiation of the parser
  100. namespace boost { namespace spirit { namespace qi
  101. {
  102. template <typename Modifiers, typename A0>
  103. struct make_primitive<
  104. terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> >
  105. , Modifiers>
  106. {
  107. typedef repository::qi::advance_parser<A0> result_type;
  108. template <typename Terminal>
  109. result_type operator()(Terminal const& term, unused_type) const
  110. {
  111. return result_type(fusion::at_c<0>(term.args));
  112. }
  113. };
  114. }}}
  115. #endif