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