while.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*=============================================================================
  2. Copyright (c) 2002-2003 Joel de Guzman
  3. Copyright (c) 2002-2003 Martin Wille
  4. http://spirit.sourceforge.net/
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #ifndef BOOST_SPIRIT_WHILE_HPP
  9. #define BOOST_SPIRIT_WHILE_HPP
  10. #include <boost/spirit/home/classic/namespace.hpp>
  11. #include <boost/spirit/home/classic/core/parser.hpp>
  12. #include <boost/spirit/home/classic/core/composite/composite.hpp>
  13. #include <boost/spirit/home/classic/dynamic/impl/conditions.ipp>
  14. ////////////////////////////////////////////////////////////////////////////////
  15. namespace boost { namespace spirit {
  16. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  17. namespace impl {
  18. //////////////////////////////////
  19. // while parser
  20. // object are created by while_parser_gen and do_parser_gen
  21. template <typename ParsableT, typename CondT, bool is_do_parser>
  22. struct while_parser
  23. : public condition_evaluator< typename as_parser<CondT>::type >
  24. , public unary // the parent stores a copy of the body parser
  25. <
  26. typename as_parser<ParsableT>::type,
  27. parser<while_parser<ParsableT, CondT, is_do_parser> >
  28. >
  29. {
  30. typedef while_parser<ParsableT, CondT, is_do_parser> self_t;
  31. typedef as_parser<ParsableT> as_parser_t;
  32. typedef typename as_parser_t::type parser_t;
  33. typedef as_parser<CondT> cond_as_parser_t;
  34. typedef typename cond_as_parser_t::type condition_t;
  35. typedef unary<parser_t, parser<self_t> > base_t;
  36. typedef condition_evaluator<condition_t> eval_t;
  37. //////////////////////////////
  38. // constructor, saves condition and body parser
  39. while_parser(ParsableT const &body, CondT const &cond)
  40. : eval_t(cond_as_parser_t::convert(cond))
  41. , base_t(as_parser_t::convert(body))
  42. {}
  43. //////////////////////////////
  44. // result type computer.
  45. template <typename ScannerT>
  46. struct result
  47. {
  48. typedef typename match_result
  49. <ScannerT, nil_t>::type type;
  50. };
  51. //////////////////////////////
  52. // parse member function
  53. template <typename ScannerT>
  54. typename parser_result<self_t, ScannerT>::type
  55. parse(ScannerT const& scan) const
  56. {
  57. typedef typename parser_result<parser_t, ScannerT>::type sresult_t;
  58. typedef typename ScannerT::iterator_t iterator_t;
  59. iterator_t save(scan.first);
  60. std::size_t length = 0;
  61. std::ptrdiff_t eval_length = 0;
  62. bool dont_check_condition = is_do_parser;
  63. while (dont_check_condition || (eval_length=this->evaluate(scan))>=0)
  64. {
  65. dont_check_condition = false;
  66. length += eval_length;
  67. sresult_t tmp(this->subject().parse(scan));
  68. if (tmp)
  69. {
  70. length+=tmp.length();
  71. }
  72. else
  73. {
  74. return scan.no_match();
  75. }
  76. }
  77. return scan.create_match(length, nil_t(), save, scan.first);
  78. }
  79. };
  80. //////////////////////////////////
  81. // while-parser generator, takes the body-parser in brackets
  82. // and returns the actual while-parser.
  83. template <typename CondT>
  84. struct while_parser_gen
  85. {
  86. //////////////////////////////
  87. // constructor, saves the condition for use by operator[]
  88. while_parser_gen(CondT const& cond_) : cond(cond_) {}
  89. //////////////////////////////
  90. // operator[] returns the actual while-parser object
  91. template <typename ParsableT>
  92. while_parser<ParsableT, CondT, false>
  93. operator[](ParsableT const &subject) const
  94. {
  95. return while_parser<ParsableT, CondT, false>(subject, cond);
  96. }
  97. private:
  98. //////////////////////////////
  99. // the condition is stored by reference here.
  100. // this should not cause any harm since object of type
  101. // while_parser_gen<> are only used as temporaries
  102. // the while-parser object constructed by the operator[]
  103. // stores a copy of the condition.
  104. CondT const &cond;
  105. };
  106. //////////////////////////////////
  107. // do-while-parser generator, takes the condition as
  108. // parameter to while_p member function and returns the
  109. // actual do-while-parser.
  110. template <typename ParsableT>
  111. struct do_while_parser_gen
  112. {
  113. //////////////////////////////
  114. // constructor. saves the body parser for use by while_p.
  115. explicit do_while_parser_gen(ParsableT const &body_parser)
  116. : body(body_parser)
  117. {}
  118. //////////////////////////////
  119. // while_p returns the actual while-parser object
  120. template <typename CondT>
  121. while_parser<ParsableT, CondT, true>
  122. while_p(CondT cond) const
  123. {
  124. return while_parser<ParsableT, CondT, true>(body, cond);
  125. }
  126. private:
  127. //////////////////////////////
  128. // the body is stored by reference here
  129. // this should not cause any harm since object of type
  130. // do_while_parser_gen<> are only used as temporaries
  131. // the while-parser object constructed by the while_p
  132. // member function stores a copy of the body parser.
  133. ParsableT const &body;
  134. };
  135. struct do_parser_gen
  136. {
  137. inline do_parser_gen() {}
  138. template <typename ParsableT>
  139. impl::do_while_parser_gen<ParsableT>
  140. operator[](ParsableT const& body) const
  141. {
  142. return impl::do_while_parser_gen<ParsableT>(body);
  143. }
  144. };
  145. } // namespace impl
  146. //////////////////////////////////
  147. // while_p function, while-parser generator
  148. // Usage: spirit::while_p(Condition)[Body]
  149. template <typename CondT>
  150. impl::while_parser_gen<CondT>
  151. while_p(CondT const& cond)
  152. {
  153. return impl::while_parser_gen<CondT>(cond);
  154. }
  155. //////////////////////////////////
  156. // do_p functor, do-while-parser generator
  157. // Usage: spirit::do_p[Body].while_p(Condition)
  158. impl::do_parser_gen const do_p = impl::do_parser_gen();
  159. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  160. }} // namespace BOOST_SPIRIT_CLASSIC_NS
  161. #endif // BOOST_SPIRIT_WHILE_HPP