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