source: NonGTP/Boost/boost/spirit/iterator/position_iterator.hpp @ 857

Revision 857, 13.5 KB checked in by igarcia, 18 years ago (diff)
Line 
1/*=============================================================================
2    Copyright (c) 2002 Juan Carlos Arevalo-Baeza
3    Copyright (c) 2002-2003 Hartmut Kaiser
4    Copyright (c) 2003 Giovanni Bajo
5    http://spirit.sourceforge.net/
6
7    Use, modification and distribution is subject to the Boost Software
8    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9    http://www.boost.org/LICENSE_1_0.txt)
10=============================================================================*/
11#ifndef BOOST_SPIRIT_POSITION_ITERATOR_HPP
12#define BOOST_SPIRIT_POSITION_ITERATOR_HPP
13
14#include <string>
15#include <boost/config.hpp>
16#include <boost/concept_check.hpp>
17
18namespace boost { namespace spirit {
19
20///////////////////////////////////////////////////////////////////////////////
21//
22//  file_position_without_column
23//
24//  A structure to hold positional information. This includes the file,
25//  and the line number
26//
27///////////////////////////////////////////////////////////////////////////////
28struct file_position_without_column {
29    std::string file;
30    int line;
31
32    file_position_without_column(std::string const& file_ = std::string(),
33                  int line_ = 1):
34        file    (file_),
35        line    (line_)
36    {}
37
38    bool operator==(const file_position_without_column& fp) const
39    { return line == fp.line && file == fp.file; }
40};
41
42///////////////////////////////////////////////////////////////////////////////
43//
44//  file_position
45//
46//  This structure holds complete file position, including file name,
47//  line and column number
48//
49///////////////////////////////////////////////////////////////////////////////
50struct file_position : public file_position_without_column {
51    int column;
52
53    file_position(std::string const& file_ = std::string(),
54                  int line_ = 1, int column_ = 1):
55        file_position_without_column (file_, line_),
56        column                       (column_)
57    {}
58
59    bool operator==(const file_position& fp) const
60    { return column == fp.column && line == fp.line && file == fp.file; }
61};
62
63
64///////////////////////////////////////////////////////////////////////////////
65//
66//  position_policy<>
67//
68//  This template is the policy to handle the file position. It is specialized
69//  on the position type. Providing a custom file_position also requires
70//  providing a specialization of this class.
71//
72//  Policy interface:
73//
74//    Default constructor of the custom position class must be accessible.
75//    set_tab_chars(unsigned int chars) - Set the tabstop width
76//    next_char(PositionT& pos)  - Notify that a new character has been
77//      processed
78//    tabulation(PositionT& pos) - Notify that a tab character has been
79//      processed
80//    next_line(PositionT& pos)  - Notify that a new line delimiter has
81//      been reached.
82//
83///////////////////////////////////////////////////////////////////////////////
84template <typename PositionT>
85class position_policy;
86
87
88// Forward declaration
89template <typename ForwardIteratorT, typename PositionT, typename SelfT>
90class position_iterator;
91
92///////////////////////////////////////////////////////////////////////////////
93}} /* namespace boost::spirit */
94
95
96// This must be included here for full compatibility with old MSVC
97#include "boost/spirit/iterator/impl/position_iterator.ipp"
98
99///////////////////////////////////////////////////////////////////////////////
100namespace boost { namespace spirit {
101
102///////////////////////////////////////////////////////////////////////////////
103//
104//  position_iterator
105//
106//  It wraps an iterator, and keeps track of the current position in the input,
107//  as it gets incremented.
108//
109//  The wrapped iterator must be at least a Forward iterator. The position
110//  iterator itself will always be a non-mutable Forward iterator.
111//
112//  In order to have begin/end iterators constructed, the end iterator must be
113//  empty constructed. Similar to what happens with stream iterators. The begin
114//  iterator must be constructed from both, the begin and end iterators of the
115//  wrapped iterator type. This is necessary to implement the lookahead of
116//  characters necessary to parse CRLF sequences.
117//
118//  In order to extract the current positional data from the iterator, you may
119//  use the get_position member function.
120//
121//  You can also use the set_position member function to reset the current
122//  position to something new.
123//
124//  The structure that holds the current position can be customized through a
125//  template parameter, and the class position_policy must be specialized
126//  on the new type to define how to handle it. Currently, it's possible
127//  to choose between the file_position and file_position_without_column
128//  (which saves some overhead if managing current column is not required).
129//
130///////////////////////////////////////////////////////////////////////////////
131
132#if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \
133     BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
134#error "Please use at least Boost V1.31.0 while compiling the position_iterator class!"
135#else // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
136
137///////////////////////////////////////////////////////////////////////////////
138//
139//  Uses the newer iterator_adaptor version (should be released with
140//  Boost V1.31.0)
141//
142///////////////////////////////////////////////////////////////////////////////
143template <
144    typename ForwardIteratorT,
145    typename PositionT = file_position,
146    typename SelfT = nil_t
147>
148class position_iterator
149:   public iterator_::impl::position_iterator_base_generator<
150        SelfT,
151        ForwardIteratorT,
152        PositionT
153    >::type,
154    public position_policy<PositionT>
155{
156private:
157
158    typedef position_policy<PositionT> position_policy_t;
159    typedef typename iterator_::impl::position_iterator_base_generator<
160            SelfT,
161            ForwardIteratorT,
162            PositionT
163        >::type base_t;
164    typedef typename iterator_::impl::position_iterator_base_generator<
165            SelfT,
166            ForwardIteratorT,
167            PositionT
168        >::main_iter_t main_iter_t;
169
170public:
171
172    typedef PositionT position_t;
173
174    position_iterator()
175    :   _isend(true)
176    {}
177
178    position_iterator(
179        const ForwardIteratorT& begin,
180        const ForwardIteratorT& end)
181    :   base_t(begin), _end(end), _pos(PositionT()), _isend(begin == end)
182    {}
183
184    template <typename FileNameT>
185    position_iterator(
186        const ForwardIteratorT& begin,
187        const ForwardIteratorT& end,
188        FileNameT fileName)
189    :   base_t(begin), _end(end), _pos(PositionT(fileName)),
190        _isend(begin == end)
191    {}
192
193    template <typename FileNameT, typename LineT>
194    position_iterator(
195        const ForwardIteratorT& begin,
196        const ForwardIteratorT& end,
197        FileNameT fileName, LineT line)
198    :   base_t(begin), _end(end), _pos(PositionT(fileName, line)),
199        _isend(begin == end)
200    {}
201
202    template <typename FileNameT, typename LineT, typename ColumnT>
203    position_iterator(
204        const ForwardIteratorT& begin,
205        const ForwardIteratorT& end,
206        FileNameT fileName, LineT line, ColumnT column)
207    :   base_t(begin), _end(end), _pos(PositionT(fileName, line, column)),
208        _isend(begin == end)
209    {}
210
211    position_iterator(
212        const ForwardIteratorT& begin,
213        const ForwardIteratorT& end,
214        const PositionT& pos)
215    :   base_t(begin), _end(end), _pos(pos), _isend(begin == end)
216    {}
217
218    position_iterator(const position_iterator& iter)
219    :   base_t(iter.base()), position_policy_t(iter),
220        _end(iter._end), _pos(iter._pos), _isend(iter._isend)
221    {}
222
223    position_iterator& operator=(const position_iterator& iter)
224    {
225        base_t::operator=(iter);
226        position_policy_t::operator=(iter);
227        _end = iter._end;
228        _pos = iter._pos;
229        _isend = iter._isend;
230        return *this;
231    }
232
233    void set_position(PositionT const& newpos) { _pos = newpos; }
234    PositionT& get_position() { return _pos; }
235    PositionT const& get_position() const { return _pos; }
236
237    void set_tabchars(unsigned int chars)
238    {
239        // This function (which comes from the position_policy) has a
240        //  different name on purpose, to avoid messing with using
241        //  declarations or qualified calls to access the base template
242        //  function, which might break some compilers.
243        this->position_policy_t::set_tab_chars(chars);
244    }
245
246private:
247    friend class boost::iterator_core_access;
248
249    void increment()
250    {
251        typename base_t::reference val = *(this->base());
252        if (val == '\n' || val == '\r') {
253            ++this->base_reference();
254            if (this->base_reference() != _end) {
255                typename base_t::reference val2 = *(this->base());
256                if ((val == '\n' && val2 == '\r')
257                    || (val == '\r' && val2 == '\n'))
258                {
259                    ++this->base_reference();
260                }
261            }
262            this->next_line(_pos);
263            static_cast<main_iter_t &>(*this).newline();
264        }
265        else if (val == '\t') {
266            this->tabulation(_pos);
267            ++this->base_reference();
268        }
269        else {
270            this->next_char(_pos);
271            ++this->base_reference();
272        }
273
274        // The iterator is at the end only if it's the same
275        //  of the
276        _isend = (this->base_reference() == _end);
277    }
278
279    template <
280        typename OtherDerivedT, typename OtherIteratorT,
281        typename V, typename C, typename R, typename D
282    >
283    bool equal(iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D>
284        const &x) const
285    {
286        OtherDerivedT const &rhs = static_cast<OtherDerivedT const &>(x);
287        bool x_is_end = rhs._isend;
288
289        return (_isend && x_is_end) ||
290            (!_isend && !x_is_end && this->base() == rhs.base());
291    }
292
293protected:
294
295    void newline(void)
296    {}
297
298    ForwardIteratorT _end;
299    PositionT _pos;
300    bool _isend;
301};
302
303#endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
304
305///////////////////////////////////////////////////////////////////////////////
306//
307//  position_iterator2
308//
309//  Equivalent to position_iterator, but it is able to extract the current
310//  line into a string. This is very handy for error reports.
311//
312//  Notice that the footprint of this class is higher than position_iterator,
313//  (how much depends on how bulky the underlying iterator is), so it should
314//  be used only if necessary.
315//
316///////////////////////////////////////////////////////////////////////////////
317
318template
319<
320    typename ForwardIteratorT,
321    typename PositionT = file_position
322>
323class position_iterator2
324    : public position_iterator
325    <
326        ForwardIteratorT,
327        PositionT,
328        position_iterator2<ForwardIteratorT, PositionT>
329    >
330{
331    typedef position_iterator
332    <
333        ForwardIteratorT,
334        PositionT,
335        position_iterator2<ForwardIteratorT, PositionT> // JDG 4-15-03
336    >  base_t;
337
338public:
339    typedef typename base_t::value_type value_type;
340    typedef PositionT position_t;
341
342    position_iterator2()
343    {}
344
345    position_iterator2(
346        const ForwardIteratorT& begin,
347        const ForwardIteratorT& end):
348        base_t(begin, end),
349        _startline(begin)
350    {}
351
352    template <typename FileNameT>
353    position_iterator2(
354        const ForwardIteratorT& begin,
355        const ForwardIteratorT& end,
356        FileNameT file):
357        base_t(begin, end, file),
358        _startline(begin)
359    {}
360
361    template <typename FileNameT, typename LineT>
362    position_iterator2(
363        const ForwardIteratorT& begin,
364        const ForwardIteratorT& end,
365        FileNameT file, LineT line):
366        base_t(begin, end, file, line),
367        _startline(begin)
368    {}
369
370    template <typename FileNameT, typename LineT, typename ColumnT>
371    position_iterator2(
372        const ForwardIteratorT& begin,
373        const ForwardIteratorT& end,
374        FileNameT file, LineT line, ColumnT column):
375        base_t(begin, end, file, line, column),
376        _startline(begin)
377    {}
378
379    position_iterator2(
380        const ForwardIteratorT& begin,
381        const ForwardIteratorT& end,
382        const PositionT& pos):
383        base_t(begin, end, pos),
384        _startline(begin)
385    {}
386
387    position_iterator2(const position_iterator2& iter)
388        : base_t(iter), _startline(iter._startline)
389    {}
390
391    position_iterator2& operator=(const position_iterator2& iter)
392    {
393        base_t::operator=(iter);
394        _startline = iter._startline;
395        return *this;
396    }
397
398    ForwardIteratorT get_currentline_begin(void) const
399    { return _startline; }
400
401    ForwardIteratorT get_currentline_end(void) const
402    { return get_endline(); }
403
404    std::basic_string<value_type> get_currentline(void) const
405    {
406        return std::basic_string<value_type>
407            (get_currentline_begin(), get_currentline_end());
408    }
409
410protected:
411    ForwardIteratorT _startline;
412
413    friend class position_iterator<ForwardIteratorT, PositionT,
414        position_iterator2<ForwardIteratorT, PositionT> >;
415
416    ForwardIteratorT get_endline() const
417    {
418        ForwardIteratorT endline = _startline;
419        while (endline != this->_end && *endline != '\r' && *endline != '\n')
420        {
421            ++endline;
422        }
423        return endline;
424    }
425
426    void newline(void)
427    { _startline = this->base(); }
428};
429
430}} // namespace boost::spirit
431
432#endif
Note: See TracBrowser for help on using the repository browser.