]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | |
49 | 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 | |
67 | 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 | int 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[] | |
104 | 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> | |
110 | 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. | |
134 | 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> | |
142 | 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 | { | |
159 | inline do_parser_gen() {} | |
160 | ||
161 | template <typename ParsableT> | |
162 | impl::do_while_parser_gen<ParsableT> | |
163 | 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> | |
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 |