First public contribution.
1 /*=============================================================================
2 Copyright (c) 2002-2003 Joel de Guzman
3 Copyright (c) 2002-2003 Martin Wille
4 http://spirit.sourceforge.net/
6 Use, modification and distribution is subject to the Boost Software
7 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 #ifndef BOOST_SPIRIT_WHILE_HPP
11 #define BOOST_SPIRIT_WHILE_HPP
13 #include <boost/spirit/core/parser.hpp>
14 #include <boost/spirit/core/composite/composite.hpp>
15 #include <boost/spirit/dynamic/impl/conditions.ipp>
17 ////////////////////////////////////////////////////////////////////////////////
18 namespace boost { namespace spirit {
22 //////////////////////////////////
24 // object are created by while_parser_gen and do_parser_gen
25 template <typename ParsableT, typename CondT, bool is_do_parser>
27 : public condition_evaluator< typename as_parser<CondT>::type >
28 , public unary // the parent stores a copy of the body parser
30 typename as_parser<ParsableT>::type,
31 parser<while_parser<ParsableT, CondT, is_do_parser> >
34 typedef while_parser<ParsableT, CondT, is_do_parser> self_t;
36 typedef as_parser<ParsableT> as_parser_t;
37 typedef typename as_parser_t::type parser_t;
38 typedef as_parser<CondT> cond_as_parser_t;
39 typedef typename cond_as_parser_t::type condition_t;
41 typedef unary<parser_t, parser<self_t> > base_t;
42 typedef condition_evaluator<condition_t> eval_t;
45 //////////////////////////////
46 // constructor, saves condition and body parser
47 while_parser(ParsableT const &body, CondT const &cond)
48 : eval_t(cond_as_parser_t::convert(cond))
49 , base_t(as_parser_t::convert(body))
52 //////////////////////////////
53 // result type computer.
54 template <typename ScannerT>
57 typedef typename match_result
58 <ScannerT, nil_t>::type type;
61 //////////////////////////////
62 // parse member function
63 template <typename ScannerT>
64 typename parser_result<self_t, ScannerT>::type
65 parse(ScannerT const& scan) const
67 typedef typename parser_result<parser_t, ScannerT>::type sresult_t;
68 typedef typename ScannerT::iterator_t iterator_t;
70 iterator_t save(scan.first);
71 std::size_t length = 0;
74 bool dont_check_condition = is_do_parser;
76 while (dont_check_condition || (eval_length=this->evaluate(scan))>=0)
78 dont_check_condition = false;
79 length += eval_length;
80 sresult_t tmp(this->subject().parse(scan));
87 return scan.no_match();
90 return scan.create_match(length, nil_t(), save, scan.first);
94 //////////////////////////////////
95 // while-parser generator, takes the body-parser in brackets
96 // and returns the actual while-parser.
97 template <typename CondT>
98 struct while_parser_gen
100 //////////////////////////////
101 // constructor, saves the condition for use by operator[]
102 while_parser_gen(CondT const& cond_) : cond(cond_) {}
104 //////////////////////////////
105 // operator[] returns the actual while-parser object
106 template <typename ParsableT>
107 while_parser<ParsableT, CondT, false>
108 operator[](ParsableT const &subject) const
110 return while_parser<ParsableT, CondT, false>(subject, cond);
114 //////////////////////////////
115 // the condition is stored by reference here.
116 // this should not cause any harm since object of type
117 // while_parser_gen<> are only used as temporaries
118 // the while-parser object constructed by the operator[]
119 // stores a copy of the condition.
123 //////////////////////////////////
124 // do-while-parser generator, takes the condition as
125 // parameter to while_p member function and returns the
126 // actual do-while-parser.
127 template <typename ParsableT>
128 struct do_while_parser_gen
130 //////////////////////////////
131 // constructor. saves the body parser for use by while_p.
132 explicit do_while_parser_gen(ParsableT const &body_parser)
136 //////////////////////////////
137 // while_p returns the actual while-parser object
138 template <typename CondT>
139 while_parser<ParsableT, CondT, true>
140 while_p(CondT cond) const
142 return while_parser<ParsableT, CondT, true>(body, cond);
146 //////////////////////////////
147 // the body is stored by reference here
148 // this should not cause any harm since object of type
149 // do_while_parser_gen<> are only used as temporaries
150 // the while-parser object constructed by the while_p
151 // member function stores a copy of the body parser.
152 ParsableT const &body;
157 inline do_parser_gen() {}
159 template <typename ParsableT>
160 impl::do_while_parser_gen<ParsableT>
161 operator[](ParsableT const& body) const
163 return impl::do_while_parser_gen<ParsableT>(body);
168 //////////////////////////////////
169 // while_p function, while-parser generator
170 // Usage: spirit::while_p(Condition)[Body]
171 template <typename CondT>
172 impl::while_parser_gen<CondT>
173 while_p(CondT const& cond)
175 return impl::while_parser_gen<CondT>(cond);
178 //////////////////////////////////
179 // do_p functor, do-while-parser generator
180 // Usage: spirit::do_p[Body].while_p(Condition)
181 impl::do_parser_gen const do_p = impl::do_parser_gen();
183 }} // namespace boost::spirit
185 #endif // BOOST_SPIRIT_WHILE_HPP