]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Boost.Wave: A Standard compliant C++ preprocessor library | |
3 | ||
4 | Definition of the unput queue iterator | |
5 | ||
6 | http://www.boost.org/ | |
7 | ||
8 | Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost | |
9 | Software License, Version 1.0. (See accompanying file | |
10 | LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
11 | =============================================================================*/ | |
12 | #if !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED) | |
13 | #define UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED | |
14 | ||
15 | #include <list> | |
16 | ||
17 | #include <boost/assert.hpp> | |
18 | #include <boost/iterator_adaptors.hpp> | |
19 | ||
20 | #include <boost/wave/wave_config.hpp> | |
21 | #include <boost/wave/token_ids.hpp> // token_id | |
22 | ||
23 | // this must occur after all of the includes and before any code appears | |
24 | #ifdef BOOST_HAS_ABI_HEADERS | |
25 | #include BOOST_ABI_PREFIX | |
26 | #endif | |
27 | ||
28 | /////////////////////////////////////////////////////////////////////////////// | |
29 | namespace boost { | |
30 | namespace wave { | |
31 | namespace util { | |
32 | ||
33 | /////////////////////////////////////////////////////////////////////////////// | |
34 | // | |
35 | // unput_queue_iterator | |
36 | // | |
37 | // The unput_queue_iterator templates encapsulates an unput_queue together | |
38 | // with the direct input to be read after the unput queue is emptied | |
39 | // | |
40 | // This version is for the new iterator_adaptors (was released with | |
41 | // Boost V1.31.0) | |
42 | // | |
43 | /////////////////////////////////////////////////////////////////////////////// | |
44 | template <typename IteratorT, typename TokenT, typename ContainerT> | |
45 | class unput_queue_iterator | |
46 | : public boost::iterator_adaptor< | |
47 | unput_queue_iterator<IteratorT, TokenT, ContainerT>, | |
48 | IteratorT, TokenT const, std::forward_iterator_tag> | |
49 | { | |
50 | typedef boost::iterator_adaptor< | |
51 | unput_queue_iterator<IteratorT, TokenT, ContainerT>, | |
52 | IteratorT, TokenT const, std::forward_iterator_tag> | |
53 | base_type; | |
54 | ||
55 | public: | |
56 | typedef ContainerT container_type; | |
57 | typedef IteratorT iterator_type; | |
58 | ||
59 | unput_queue_iterator(IteratorT const &it, ContainerT &queue) | |
60 | : base_type(it), unput_queue(queue) | |
61 | {} | |
62 | ||
63 | ContainerT &get_unput_queue() | |
64 | { return unput_queue; } | |
65 | ContainerT const &get_unput_queue() const | |
66 | { return unput_queue; } | |
67 | IteratorT &get_base_iterator() | |
68 | { return base_type::base_reference(); } | |
69 | IteratorT const &get_base_iterator() const | |
70 | { return base_type::base_reference(); } | |
71 | ||
72 | unput_queue_iterator &operator= (unput_queue_iterator const &rhs) | |
73 | { | |
74 | if (this != &rhs) { | |
75 | unput_queue = rhs.unput_queue; | |
76 | base_type::operator=(rhs); | |
77 | } | |
78 | return *this; | |
79 | } | |
80 | ||
81 | typename base_type::reference dereference() const | |
82 | { | |
83 | if (!unput_queue.empty()) | |
84 | return unput_queue.front(); | |
85 | return *base_type::base_reference(); | |
86 | } | |
87 | ||
88 | void increment() | |
89 | { | |
90 | if (!unput_queue.empty()) { | |
91 | // there exist pending tokens in the unput queue | |
92 | unput_queue.pop_front(); | |
93 | } | |
94 | else { | |
95 | // the unput_queue is empty, so advance the base iterator | |
96 | ++base_type::base_reference(); | |
97 | } | |
98 | } | |
99 | ||
100 | template < | |
101 | typename OtherDerivedT, typename OtherIteratorT, | |
102 | typename V, typename C, typename R, typename D | |
103 | > | |
104 | bool equal( | |
105 | boost::iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D> | |
106 | const &x) const | |
107 | { | |
108 | // two iterators are equal, if both begin() iterators of the queue | |
109 | // objects are equal and the base iterators are equal as well | |
110 | OtherDerivedT const &rhs = static_cast<OtherDerivedT const &>(x); | |
111 | return | |
112 | ((unput_queue.empty() && rhs.unput_queue.empty()) || | |
113 | (&unput_queue == &rhs.unput_queue && | |
114 | unput_queue.begin() == rhs.unput_queue.begin() | |
115 | ) | |
116 | ) && | |
117 | (get_base_iterator() == rhs.get_base_iterator()); | |
118 | } | |
119 | ||
120 | private: | |
121 | ContainerT &unput_queue; | |
122 | }; | |
123 | ||
124 | namespace impl { | |
125 | ||
126 | /////////////////////////////////////////////////////////////////////////// | |
127 | template <typename IteratorT, typename TokenT, typename ContainerT> | |
128 | struct gen_unput_queue_iterator | |
129 | { | |
130 | typedef ContainerT container_type; | |
131 | typedef IteratorT iterator_type; | |
132 | typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> | |
133 | return_type; | |
134 | ||
135 | static container_type last; | |
136 | ||
137 | static return_type | |
138 | generate(iterator_type const &it) | |
139 | { | |
140 | return return_type(it, last); | |
141 | } | |
142 | ||
143 | static return_type | |
144 | generate(ContainerT &queue, iterator_type const &it) | |
145 | { | |
146 | return return_type(it, queue); | |
147 | } | |
148 | }; | |
149 | ||
150 | template <typename IteratorT, typename TokenT, typename ContainerT> | |
151 | typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>:: | |
152 | container_type | |
153 | gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::last = | |
154 | typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>:: | |
155 | container_type(); | |
156 | ||
157 | /////////////////////////////////////////////////////////////////////////// | |
158 | template <typename IteratorT, typename TokenT, typename ContainerT> | |
159 | struct gen_unput_queue_iterator< | |
160 | unput_queue_iterator<IteratorT, TokenT, ContainerT>, | |
161 | TokenT, ContainerT> | |
162 | { | |
163 | typedef ContainerT container_type; | |
164 | typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> | |
165 | iterator_type; | |
166 | typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> | |
167 | return_type; | |
168 | ||
169 | static container_type last; | |
170 | ||
171 | static return_type | |
172 | generate(iterator_type &it) | |
173 | { | |
174 | return return_type(it.base(), last); | |
175 | } | |
176 | ||
177 | static return_type | |
178 | generate(ContainerT &queue, iterator_type &it) | |
179 | { | |
180 | return return_type(it.base(), queue); | |
181 | } | |
182 | }; | |
183 | ||
184 | /////////////////////////////////////////////////////////////////////////// | |
185 | template <typename IteratorT> | |
186 | struct assign_iterator | |
187 | { | |
188 | static void | |
189 | do_ (IteratorT &dest, IteratorT const &src) | |
190 | { | |
191 | dest = src; | |
192 | } | |
193 | }; | |
194 | ||
195 | /////////////////////////////////////////////////////////////////////////// | |
196 | // | |
197 | // Look for the first non-whitespace token and return this token id. | |
198 | // Note though, that the embedded unput_queues are not touched in any way! | |
199 | // | |
200 | template <typename IteratorT> | |
201 | struct next_token | |
202 | { | |
203 | static boost::wave::token_id | |
204 | peek(IteratorT it, IteratorT end, bool skip_whitespace = true) | |
205 | { | |
206 | using namespace boost::wave; | |
207 | if (skip_whitespace) { | |
208 | for (++it; it != end; ++it) { | |
209 | if (!IS_CATEGORY(*it, WhiteSpaceTokenType) && | |
210 | T_NEWLINE != token_id(*it)) | |
211 | { | |
212 | break; // stop at the first non-whitespace token | |
213 | } | |
214 | } | |
215 | } | |
216 | else { | |
217 | ++it; // we have at least to look ahead | |
218 | } | |
219 | if (it != end) | |
220 | return token_id(*it); | |
221 | return T_EOI; | |
222 | } | |
223 | }; | |
224 | ||
225 | template <typename IteratorT, typename TokenT, typename ContainerT> | |
226 | struct next_token< | |
227 | unput_queue_iterator<IteratorT, TokenT, ContainerT> > { | |
228 | ||
229 | typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> iterator_type; | |
230 | ||
231 | static boost::wave::token_id | |
232 | peek(iterator_type it, iterator_type end, bool skip_whitespace = true) | |
233 | { | |
234 | using namespace boost::wave; | |
235 | ||
236 | typename iterator_type::container_type &queue = it.get_unput_queue(); | |
237 | ||
238 | // first try to find it in the unput_queue | |
239 | if (0 != queue.size()) { | |
240 | typename iterator_type::container_type::iterator cit = queue.begin(); | |
241 | typename iterator_type::container_type::iterator cend = queue.end(); | |
242 | ||
243 | if (skip_whitespace) { | |
244 | for (++cit; cit != cend; ++cit) { | |
245 | if (!IS_CATEGORY(*cit, WhiteSpaceTokenType) && | |
246 | T_NEWLINE != token_id(*cit)) | |
247 | { | |
248 | break; // stop at the first non-whitespace token | |
249 | } | |
250 | } | |
251 | } | |
252 | else { | |
253 | ++cit; // we have at least to look ahead | |
254 | } | |
255 | if (cit != cend) | |
256 | return token_id(*cit); | |
257 | } | |
258 | ||
259 | // second try to move on into the base iterator stream | |
260 | typename iterator_type::iterator_type base_it = it.get_base_iterator(); | |
261 | typename iterator_type::iterator_type base_end = end.get_base_iterator(); | |
262 | ||
263 | if (0 == queue.size()) | |
264 | ++base_it; // advance, if the unput queue is empty | |
265 | ||
266 | if (skip_whitespace) { | |
267 | for (/**/; base_it != base_end; ++base_it) { | |
268 | if (!IS_CATEGORY(*base_it, WhiteSpaceTokenType) && | |
269 | T_NEWLINE != token_id(*base_it)) | |
270 | { | |
271 | break; // stop at the first non-whitespace token | |
272 | } | |
273 | } | |
274 | } | |
275 | if (base_it == base_end) | |
276 | return T_EOI; | |
277 | ||
278 | return token_id(*base_it); | |
279 | } | |
280 | }; | |
281 | ||
282 | /////////////////////////////////////////////////////////////////////////////// | |
283 | } // namespace impl | |
284 | ||
285 | /////////////////////////////////////////////////////////////////////////////// | |
286 | } // namespace util | |
287 | } // namespace wave | |
288 | } // namespace boost | |
289 | ||
290 | // the suffix header occurs after all of the code | |
291 | #ifdef BOOST_HAS_ABI_HEADERS | |
292 | #include BOOST_ABI_SUFFIX | |
293 | #endif | |
294 | ||
295 | #endif // !defined(UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED) |