~ubuntu-branches/ubuntu/warty/aqsis/warty

« back to all changes in this revision

Viewing changes to boost/boost/spirit/iterator/multi_pass.hpp

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:25:04 UTC
  • Revision ID: james.westby@ubuntu.com-20040824072504-zf993vnevvisdsvb
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*=============================================================================
 
2
    Spirit v1.6.1
 
3
    Copyright (c) 2001, Daniel C. Nuffer
 
4
    http://spirit.sourceforge.net/
 
5
 
 
6
    Permission to copy, use, modify, sell and distribute this software is
 
7
    granted provided this copyright notice appears in all copies. This
 
8
    software is provided "as is" without express or implied warranty, and
 
9
    with no claim as to its suitability for any purpose.
 
10
=============================================================================*/
 
11
#ifndef BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
 
12
#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
 
13
 
 
14
#include <boost/config.hpp>
 
15
#include <boost/throw_exception.hpp>
 
16
#include <boost/detail/workaround.hpp>
 
17
 
 
18
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
 
19
#  error multi_pass iterator supported only on MSVC 7.0 and above.
 
20
#else
 
21
// the newer version of multi_pass
 
22
 
 
23
#include <deque>
 
24
#include <iterator>
 
25
#include <iostream>
 
26
#include <algorithm>    // for std::swap
 
27
#include <exception>    // for std::exception
 
28
 
 
29
#include <boost/limits.hpp>
 
30
#include <boost/iterator.hpp>
 
31
 
 
32
#include "fixed_size_queue.hpp"
 
33
#include "boost/spirit/core/assert.hpp" // for BOOST_SPIRIT_ASSERT
 
34
 
 
35
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
 
36
# include "boost/spirit/core/impl/msvc.hpp"  // for more compatible iterator_traits
 
37
#define BOOST_SPIRIT_IT_NS impl
 
38
#else
 
39
#define BOOST_SPIRIT_IT_NS std
 
40
#endif
 
41
 
 
42
#if (defined(BOOST_INTEL_CXX_VERSION) && !defined(_STLPORT_VERSION))
 
43
# include "boost/spirit/core/impl/msvc.hpp"  // for more compatible iterator_traits
 
44
#undef BOOST_SPIRIT_IT_NS
 
45
#define BOOST_SPIRIT_IT_NS impl
 
46
#endif
 
47
 
 
48
///////////////////////////////////////////////////////////////////////////////
 
49
namespace boost { namespace spirit {
 
50
 
 
51
namespace impl {
 
52
    template <typename T>
 
53
    inline void mp_swap(T& t1, T& t2);
 
54
}
 
55
 
 
56
namespace multi_pass_policies
 
57
{
 
58
 
 
59
///////////////////////////////////////////////////////////////////////////////
 
60
// class ref_counted
 
61
// Implementation of an OwnershipPolicy used by multi_pass.
 
62
//
 
63
// Implementation modified from RefCounted class from the Loki library by
 
64
// Andrei Alexandrescu
 
65
///////////////////////////////////////////////////////////////////////////////
 
66
class ref_counted
 
67
{
 
68
    protected:
 
69
        ref_counted()
 
70
            : count(new unsigned int(1))
 
71
        {}
 
72
 
 
73
        ref_counted(ref_counted const& x)
 
74
            : count(x.count)
 
75
        {}
 
76
 
 
77
        // clone is called when a copy of the iterator is made, so increment
 
78
        // the ref-count.
 
79
        void clone()
 
80
        {
 
81
            ++*count;
 
82
        }
 
83
 
 
84
        // called when a copy is deleted.  Decrement the ref-count.  Return
 
85
        // value of true indicates that the last copy has been released.
 
86
        bool release()
 
87
        {
 
88
            if (!--*count)
 
89
            {
 
90
                delete count;
 
91
                count = 0;
 
92
                return true;
 
93
            }
 
94
            return false;
 
95
        }
 
96
 
 
97
        void swap(ref_counted& x)
 
98
        {
 
99
            impl::mp_swap(count, x.count);
 
100
        }
 
101
 
 
102
    public:
 
103
        // returns true if there is only one iterator in existence.
 
104
        // std_deque StoragePolicy will free it's buffered data if this
 
105
        // returns true.
 
106
        bool unique() const
 
107
        {
 
108
            return *count == 1;
 
109
        }
 
110
 
 
111
    private:
 
112
        unsigned int* count;
 
113
};
 
114
 
 
115
///////////////////////////////////////////////////////////////////////////////
 
116
// class first_owner
 
117
// Implementation of an OwnershipPolicy used by multi_pass
 
118
// This ownership policy dictates that the first iterator created will
 
119
// determine the lifespan of the shared components.  This works well for
 
120
// spirit, since no dynamic allocation of iterators is done, and all copies
 
121
// are make on the stack.
 
122
//
 
123
// There is a caveat about using this policy together with the std_deque
 
124
// StoragePolicy. Since first_owner always returns false from unique(),
 
125
// std_deque will only release the queued data if clear_queue() is called.
 
126
///////////////////////////////////////////////////////////////////////////////
 
127
class first_owner
 
128
{
 
129
    protected:
 
130
        first_owner()
 
131
            : first(true)
 
132
        {}
 
133
 
 
134
        first_owner(first_owner const&)
 
135
            : first(false)
 
136
        {}
 
137
 
 
138
        void clone()
 
139
        {
 
140
        }
 
141
 
 
142
        // return true to indicate deletion of resources
 
143
        bool release()
 
144
        {
 
145
            return first;
 
146
        }
 
147
 
 
148
        void swap(first_owner&)
 
149
        {
 
150
            // if we're the first, we still remain the first, even if assigned
 
151
            // to, so don't swap first_.  swap is only called from operator=
 
152
        }
 
153
 
 
154
    public:
 
155
        bool unique() const
 
156
        {
 
157
            return false; // no way to know, so always return false
 
158
        }
 
159
 
 
160
    private:
 
161
        bool first;
 
162
};
 
163
 
 
164
///////////////////////////////////////////////////////////////////////////////
 
165
// class illegal_backtracking
 
166
// thrown by buf_id_check CheckingPolicy if an instance of an iterator is
 
167
// used after another one has invalidated the queue
 
168
///////////////////////////////////////////////////////////////////////////////
 
169
class illegal_backtracking : public std::exception
 
170
{
 
171
public:
 
172
 
 
173
    illegal_backtracking() throw() {}
 
174
    ~illegal_backtracking() throw() {}
 
175
 
 
176
    virtual const char*
 
177
    what() const throw()
 
178
    { return "boost::spirit::illegal_backtracking"; }
 
179
};
 
180
 
 
181
///////////////////////////////////////////////////////////////////////////////
 
182
// class buf_id_check
 
183
// Implementation of the CheckingPolicy used by multi_pass
 
184
// This policy is most effective when used together with the std_deque
 
185
// StoragePolicy.
 
186
// If used with the fixed_size_queue StoragePolicy, it will not detect
 
187
// iterator derefereces that are out of the range of the queue.
 
188
///////////////////////////////////////////////////////////////////////////////
 
189
class buf_id_check
 
190
{
 
191
    protected:
 
192
        buf_id_check()
 
193
            : shared_buf_id(new unsigned long(0))
 
194
            , buf_id(0)
 
195
        {}
 
196
 
 
197
        buf_id_check(buf_id_check const& x)
 
198
            : shared_buf_id(x.shared_buf_id)
 
199
            , buf_id(x.buf_id)
 
200
        {}
 
201
 
 
202
        // will be called from the destructor of the last iterator.
 
203
        void destroy()
 
204
        {
 
205
            delete shared_buf_id;
 
206
            shared_buf_id = 0;
 
207
        }
 
208
 
 
209
        void swap(buf_id_check& x)
 
210
        {
 
211
            impl::mp_swap(shared_buf_id, x.shared_buf_id);
 
212
            impl::mp_swap(buf_id, x.buf_id);
 
213
        }
 
214
 
 
215
        // called to verify that everything is okay.
 
216
        void check() const
 
217
        {
 
218
            if (buf_id != *shared_buf_id)
 
219
            {
 
220
                boost::throw_exception(illegal_backtracking());
 
221
            }
 
222
        }
 
223
 
 
224
        // called from multi_pass::clear_queue, so we can increment the count
 
225
        void clear_queue()
 
226
        {
 
227
            ++*shared_buf_id;
 
228
            ++buf_id;
 
229
        }
 
230
 
 
231
    private:
 
232
        unsigned long* shared_buf_id;
 
233
        unsigned long buf_id;
 
234
};
 
235
 
 
236
///////////////////////////////////////////////////////////////////////////////
 
237
// class no_check
 
238
// Implementation of the CheckingPolicy used by multi_pass
 
239
// It does not do anything :-)
 
240
///////////////////////////////////////////////////////////////////////////////
 
241
class no_check
 
242
{
 
243
    protected:
 
244
        no_check() {}
 
245
        no_check(no_check const&) {}
 
246
        void destroy() {}
 
247
        void swap(no_check&) {}
 
248
        void check() const {}
 
249
        void clear_queue() {}
 
250
};
 
251
 
 
252
///////////////////////////////////////////////////////////////////////////////
 
253
// class std_deque
 
254
// Implementation of the StoragePolicy used by multi_pass
 
255
// This stores all data in a std::deque, and keeps an offset to the current
 
256
// position. It stores all the data unless there is only one
 
257
// iterator using the queue.
 
258
// Note: a position is used instead of an iterator, because a push_back on
 
259
// a deque can invalidate any iterators.
 
260
///////////////////////////////////////////////////////////////////////////////
 
261
class std_deque
 
262
{
 
263
    public:
 
264
 
 
265
template <typename ValueT>
 
266
class inner
 
267
{
 
268
#if defined(__BORLANDC__) || BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
 
269
    public:
 
270
#else
 
271
    private:
 
272
#endif
 
273
        typedef std::deque<ValueT> queue_type;
 
274
        queue_type* queuedElements;
 
275
        mutable typename queue_type::size_type queuePosition;
 
276
 
 
277
    protected:
 
278
        inner()
 
279
            : queuedElements(new queue_type)
 
280
            , queuePosition(0)
 
281
        {}
 
282
 
 
283
        inner(inner const& x)
 
284
            : queuedElements(x.queuedElements)
 
285
            , queuePosition(x.queuePosition)
 
286
        {}
 
287
 
 
288
        // will be called from the destructor of the last iterator.
 
289
        void destroy()
 
290
        {
 
291
            BOOST_SPIRIT_ASSERT(queuedElements);
 
292
            delete queuedElements;
 
293
            queuedElements = 0;
 
294
        }
 
295
 
 
296
        void swap(inner& x)
 
297
        {
 
298
            impl::mp_swap(queuedElements, x.queuedElements);
 
299
            impl::mp_swap(queuePosition, x.queuePosition);
 
300
        }
 
301
 
 
302
        // This is called when the iterator is dereferenced.  It's a template
 
303
        // method so we can recover the type of the multi_pass iterator
 
304
        // and call unique and access the m_input data member.
 
305
        template <typename MultiPassT>
 
306
        static typename MultiPassT::reference dereference(MultiPassT const& mp)
 
307
        {
 
308
            if (mp.queuePosition == mp.queuedElements->size())
 
309
            {
 
310
                // check if this is the only iterator
 
311
                if (mp.unique())
 
312
                {
 
313
                    // free up the memory used by the queue.
 
314
                    if (mp.queuedElements->size() > 0)
 
315
                    {
 
316
                        mp.queuedElements->clear();
 
317
                        mp.queuePosition = 0;
 
318
                    }
 
319
                }
 
320
                return mp.get_input();
 
321
            }
 
322
            else
 
323
            {
 
324
                return (*mp.queuedElements)[mp.queuePosition];
 
325
            }
 
326
        }
 
327
 
 
328
        // This is called when the iterator is incremented.  It's a template
 
329
        // method so we can recover the type of the multi_pass iterator
 
330
        // and call unique and access the m_input data member.
 
331
        template <typename MultiPassT>
 
332
        static void increment(MultiPassT& mp)
 
333
        {
 
334
            if (mp.queuePosition == mp.queuedElements->size())
 
335
            {
 
336
                // check if this is the only iterator
 
337
                if (mp.unique())
 
338
                {
 
339
                    // free up the memory used by the queue.
 
340
                    if (mp.queuedElements->size() > 0)
 
341
                    {
 
342
                        mp.queuedElements->clear();
 
343
                        mp.queuePosition = 0;
 
344
                    }
 
345
                }
 
346
                else
 
347
                {
 
348
                    mp.queuedElements->push_back(mp.get_input());
 
349
                    ++mp.queuePosition;
 
350
                }
 
351
                mp.advance_input();
 
352
            }
 
353
            else
 
354
            {
 
355
                ++mp.queuePosition;
 
356
            }
 
357
 
 
358
        }
 
359
 
 
360
        // called to forcibly clear the queue
 
361
        void clear_queue()
 
362
        {
 
363
            queuedElements->clear();
 
364
            queuePosition = 0;
 
365
        }
 
366
 
 
367
        // called to determine whether the iterator is an eof iterator
 
368
        template <typename MultiPassT>
 
369
        static bool is_eof(MultiPassT const& mp)
 
370
        {
 
371
            return mp.queuePosition == mp.queuedElements->size() &&
 
372
                mp.input_at_eof();
 
373
        }
 
374
 
 
375
        // called by operator==
 
376
        bool equal_to(inner const& x) const
 
377
        {
 
378
            return queuePosition == x.queuePosition;
 
379
        }
 
380
 
 
381
        // called by operator<
 
382
        bool less_than(inner const& x) const
 
383
        {
 
384
            return queuePosition < x.queuePosition;
 
385
        }
 
386
}; // class inner
 
387
 
 
388
}; // class std_deque
 
389
 
 
390
 
 
391
///////////////////////////////////////////////////////////////////////////////
 
392
// class fixed_size_queue
 
393
// Implementation of the StoragePolicy used by multi_pass
 
394
// fixed_size_queue keeps a circular buffer (implemented by
 
395
// boost::spirit::fixed_size_queue class) that is size N+1 and stores N elements.
 
396
// It is up to the user to ensure that there is enough look ahead for their
 
397
// grammar.  Currently there is no way to tell if an iterator is pointing
 
398
// to forgotten data.  The leading iterator will put an item in the queue
 
399
// and remove one when it is incremented.  No dynamic allocation is done,
 
400
// except on creation of the queue (fixed_size_queue constructor).
 
401
///////////////////////////////////////////////////////////////////////////////
 
402
template < std::size_t N>
 
403
class fixed_size_queue
 
404
{
 
405
    public:
 
406
 
 
407
template <typename ValueT>
 
408
class inner
 
409
{
 
410
#if defined(__BORLANDC__) || BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
 
411
    public:
 
412
#else
 
413
    private:
 
414
#endif
 
415
        typedef boost::spirit::fixed_size_queue<ValueT, N> queue_type;
 
416
        queue_type * queuedElements;
 
417
        mutable typename queue_type::iterator queuePosition;
 
418
 
 
419
    protected:
 
420
        inner()
 
421
            : queuedElements(new queue_type)
 
422
            , queuePosition(queuedElements->begin())
 
423
        {}
 
424
 
 
425
        inner(inner const& x)
 
426
            : queuedElements(x.queuedElements)
 
427
            , queuePosition(x.queuePosition)
 
428
        {}
 
429
 
 
430
        // will be called from the destructor of the last iterator.
 
431
        void destroy()
 
432
        {
 
433
            BOOST_SPIRIT_ASSERT(queuedElements);
 
434
            delete queuedElements;
 
435
            queuedElements = 0;
 
436
        }
 
437
 
 
438
        void swap(inner& x)
 
439
        {
 
440
            impl::mp_swap(queuedElements, x.queuedElements);
 
441
            impl::mp_swap(queuePosition, x.queuePosition);
 
442
        }
 
443
 
 
444
        // This is called when the iterator is dereferenced.  It's a template
 
445
        // method so we can recover the type of the multi_pass iterator
 
446
        // and access the m_input data member.
 
447
        template <typename MultiPassT>
 
448
        static typename MultiPassT::reference dereference(MultiPassT const& mp)
 
449
        {
 
450
            if (mp.queuePosition == mp.queuedElements->end())
 
451
            {
 
452
                return mp.get_input();
 
453
            }
 
454
            else
 
455
            {
 
456
                return *mp.queuePosition;
 
457
            }
 
458
        }
 
459
 
 
460
        // This is called when the iterator is incremented.  It's a template
 
461
        // method so we can recover the type of the multi_pass iterator
 
462
        // and access the m_input data member.
 
463
        template <typename MultiPassT>
 
464
        static void increment(MultiPassT& mp)
 
465
        {
 
466
            if (mp.queuePosition == mp.queuedElements->end())
 
467
            {
 
468
                // don't let the queue get larger than N
 
469
                if (mp.queuedElements->size() >= N)
 
470
                    mp.queuedElements->pop_front();
 
471
 
 
472
                mp.queuedElements->push_back(mp.get_input());
 
473
                mp.advance_input();
 
474
            }
 
475
            ++mp.queuePosition;
 
476
        }
 
477
 
 
478
        // no-op
 
479
        void clear_queue()
 
480
        {}
 
481
 
 
482
        // called to determine whether the iterator is an eof iterator
 
483
        template <typename MultiPassT>
 
484
        static bool is_eof(MultiPassT const& mp)
 
485
        {
 
486
            return mp.queuePosition == mp.queuedElements->end() &&
 
487
                mp.input_at_eof();
 
488
        }
 
489
 
 
490
        // called by operator==
 
491
        bool equal_to(inner const& x) const
 
492
        {
 
493
            return queuePosition == x.queuePosition;
 
494
        }
 
495
 
 
496
        // called by operator<
 
497
        bool less_than(inner const& x) const
 
498
        {
 
499
            return queuePosition < x.queuePosition;
 
500
        }
 
501
}; // class inner
 
502
 
 
503
}; // class fixed_size_queue
 
504
 
 
505
 
 
506
///////////////////////////////////////////////////////////////////////////////
 
507
// class input_iterator
 
508
// Implementation of the InputPolicy used by multi_pass
 
509
// input_iterator encapsulates an input iterator of type InputT
 
510
///////////////////////////////////////////////////////////////////////////////
 
511
class input_iterator
 
512
{
 
513
    public:
 
514
 
 
515
template <typename InputT>
 
516
class inner
 
517
{
 
518
    public:
 
519
        typedef 
 
520
            typename BOOST_SPIRIT_IT_NS::iterator_traits<InputT>::value_type 
 
521
            value_type;
 
522
        typedef 
 
523
            typename BOOST_SPIRIT_IT_NS::iterator_traits<InputT>::difference_type
 
524
            difference_type;
 
525
        typedef 
 
526
            typename BOOST_SPIRIT_IT_NS::iterator_traits<InputT>::pointer 
 
527
            pointer;
 
528
        typedef 
 
529
            typename BOOST_SPIRIT_IT_NS::iterator_traits<InputT>::reference 
 
530
            reference;
 
531
 
 
532
    protected:
 
533
        inner()
 
534
            : input(new InputT())
 
535
            , val(new value_type)
 
536
        {}
 
537
 
 
538
        inner(InputT x)
 
539
            : input(new InputT(x))
 
540
            , val(new value_type(**input))
 
541
        {}
 
542
 
 
543
        inner(inner const& x)
 
544
            : input(x.input)
 
545
            , val(x.val)
 
546
        {}
 
547
 
 
548
        void destroy()
 
549
        {
 
550
            delete input;
 
551
            input = 0;
 
552
            delete val;
 
553
            val = 0;
 
554
        }
 
555
 
 
556
        bool same_input(inner const& x) const
 
557
        {
 
558
            return input == x.input;
 
559
        }
 
560
 
 
561
        typedef 
 
562
            typename BOOST_SPIRIT_IT_NS::iterator_traits<InputT>::value_type 
 
563
            value_t;
 
564
        void swap(inner& x)
 
565
        {
 
566
            impl::mp_swap(input, x.input);
 
567
            impl::mp_swap(val, x.val);
 
568
        }
 
569
 
 
570
    public:
 
571
        reference get_input() const
 
572
        {
 
573
            return *val;
 
574
        }
 
575
 
 
576
        void advance_input()
 
577
        {
 
578
            ++*input;
 
579
            *val = **input;
 
580
        }
 
581
 
 
582
        bool input_at_eof() const
 
583
        {
 
584
            return *input == InputT();
 
585
        }
 
586
 
 
587
    private:
 
588
        InputT* input;
 
589
        value_type* val;
 
590
 
 
591
};
 
592
 
 
593
};
 
594
 
 
595
///////////////////////////////////////////////////////////////////////////////
 
596
// class lex_input
 
597
// Implementation of the InputPolicy used by multi_pass
 
598
// lex_input gets tokens (ints) from yylex()
 
599
///////////////////////////////////////////////////////////////////////////////
 
600
class lex_input
 
601
{
 
602
    public:
 
603
 
 
604
template <typename InputT>
 
605
class inner
 
606
{
 
607
    public:
 
608
        typedef int value_type;
 
609
    typedef std::ptrdiff_t difference_type;
 
610
        typedef int* pointer;
 
611
        typedef int& reference;
 
612
 
 
613
    protected:
 
614
        inner()
 
615
            : curtok(new int(0))
 
616
        {}
 
617
 
 
618
        inner(InputT x)
 
619
            : curtok(new int(x))
 
620
        {}
 
621
 
 
622
        inner(inner const& x)
 
623
            : curtok(x.curtok)
 
624
        {}
 
625
 
 
626
        void destroy()
 
627
        {
 
628
            delete curtok;
 
629
            curtok = 0;
 
630
        }
 
631
 
 
632
        bool same_input(inner const& x) const
 
633
        {
 
634
            return curtok == x.curtok;
 
635
        }
 
636
 
 
637
        void swap(inner& x)
 
638
        {
 
639
            impl::mp_swap(curtok, x.curtok);
 
640
        }
 
641
 
 
642
    public:
 
643
        reference get_input() const
 
644
        {
 
645
            return *curtok;
 
646
        }
 
647
 
 
648
        void advance_input()
 
649
        {
 
650
            extern int yylex();
 
651
            *curtok = yylex();
 
652
        }
 
653
 
 
654
        bool input_at_eof() const
 
655
        {
 
656
            return *curtok == 0;
 
657
        }
 
658
 
 
659
    private:
 
660
        int* curtok;
 
661
 
 
662
};
 
663
 
 
664
};
 
665
 
 
666
///////////////////////////////////////////////////////////////////////////////
 
667
// class functor_input
 
668
// Implementation of the InputPolicy used by multi_pass
 
669
// functor_input gets tokens from a functor
 
670
// Note: the functor must have a typedef for result_type
 
671
// It also must have a static variable of type result_type defined to
 
672
// represent eof that is called eof.
 
673
///////////////////////////////////////////////////////////////////////////////
 
674
class functor_input
 
675
{
 
676
    public:
 
677
 
 
678
template <typename FunctorT>
 
679
class inner
 
680
{
 
681
    typedef typename FunctorT::result_type result_type;
 
682
    public:
 
683
        typedef result_type value_type;
 
684
    typedef std::ptrdiff_t difference_type;
 
685
        typedef result_type* pointer;
 
686
        typedef result_type& reference;
 
687
 
 
688
    protected:
 
689
        inner()
 
690
            : ftor(0)
 
691
            , curtok(0)
 
692
        {}
 
693
 
 
694
        inner(FunctorT const& x)
 
695
            : ftor(new FunctorT(x))
 
696
            , curtok(new result_type((*ftor)()))
 
697
        {}
 
698
 
 
699
        inner(inner const& x)
 
700
            : ftor(x.ftor)
 
701
            , curtok(x.curtok)
 
702
        {}
 
703
 
 
704
        void destroy()
 
705
        {
 
706
            delete ftor;
 
707
            ftor = 0;
 
708
            delete curtok;
 
709
            curtok = 0;
 
710
        }
 
711
 
 
712
        bool same_input(inner const& x) const
 
713
        {
 
714
            return ftor == x.ftor;
 
715
        }
 
716
 
 
717
        void swap(inner& x)
 
718
        {
 
719
            impl::mp_swap(curtok, x.curtok);
 
720
            impl::mp_swap(ftor, x.ftor);
 
721
        }
 
722
 
 
723
    public:
 
724
        reference get_input() const
 
725
        {
 
726
            return *curtok;
 
727
        }
 
728
 
 
729
        void advance_input()
 
730
        {
 
731
            if (curtok) {
 
732
                *curtok = (*ftor)();
 
733
            }
 
734
        }
 
735
 
 
736
        bool input_at_eof() const
 
737
        {
 
738
            return !curtok || *curtok == ftor->eof;
 
739
        }
 
740
 
 
741
        FunctorT& get_functor() const
 
742
        {
 
743
            return *ftor;
 
744
        }
 
745
 
 
746
 
 
747
    private:
 
748
        FunctorT* ftor;
 
749
        result_type* curtok;
 
750
 
 
751
};
 
752
 
 
753
};
 
754
 
 
755
} // namespace multi_pass_policies
 
756
 
 
757
///////////////////////////////////////////////////////////////////////////////
 
758
// iterator_base_creator
 
759
///////////////////////////////////////////////////////////////////////////////
 
760
 
 
761
namespace iterator_ { namespace impl {
 
762
 
 
763
// Meta-function to generate a std::iterator<> base class for multi_pass. This
 
764
//  is used mainly to improve conformance of compilers not supporting PTS
 
765
//  and thus relying on inheritance to recognize an iterator.
 
766
// We are using boost::iterator<> because it offers an automatic workaround
 
767
//  for broken std::iterator<> implementations.
 
768
template <typename InputPolicyT, typename InputT>
 
769
struct iterator_base_creator
 
770
{
 
771
    typedef typename InputPolicyT::BOOST_NESTED_TEMPLATE inner<InputT> input_t;
 
772
 
 
773
    typedef boost::iterator
 
774
    <
 
775
        std::forward_iterator_tag,
 
776
        typename input_t::value_type,
 
777
        typename input_t::difference_type,
 
778
        typename input_t::pointer,
 
779
        typename input_t::reference
 
780
    > type;
 
781
};
 
782
 
 
783
}}
 
784
 
 
785
 
 
786
 
 
787
///////////////////////////////////////////////////////////////////////////////
 
788
// class template multi_pass (declaration)
 
789
///////////////////////////////////////////////////////////////////////////////
 
790
template
 
791
<
 
792
    typename InputT,
 
793
    typename InputPolicy = multi_pass_policies::input_iterator,
 
794
    typename OwnershipPolicy = multi_pass_policies::ref_counted,
 
795
    typename CheckingPolicy = multi_pass_policies::buf_id_check,
 
796
    typename StoragePolicy = multi_pass_policies::std_deque
 
797
>
 
798
class multi_pass;
 
799
 
 
800
// The default multi_pass instantiation uses a ref-counted std_deque scheme.
 
801
 
 
802
///////////////////////////////////////////////////////////////////////////////
 
803
// class template multi_pass (definition)
 
804
///////////////////////////////////////////////////////////////////////////////
 
805
template
 
806
<
 
807
    typename InputT,
 
808
    typename InputPolicy,
 
809
    typename OwnershipPolicy,
 
810
    typename CheckingPolicy,
 
811
    typename StoragePolicy
 
812
>
 
813
class multi_pass
 
814
    : public OwnershipPolicy
 
815
    , public CheckingPolicy
 
816
    , public StoragePolicy::template inner<
 
817
                typename InputPolicy::template inner<InputT>::value_type>
 
818
    , public InputPolicy::template inner<InputT>
 
819
    , public iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
 
820
{
 
821
        typedef OwnershipPolicy OP;
 
822
        typedef CheckingPolicy CHP;
 
823
        typedef typename StoragePolicy::template inner<
 
824
            typename InputPolicy::template inner<InputT>::value_type> SP;
 
825
        typedef typename InputPolicy::template inner<InputT> IP;
 
826
        typedef typename 
 
827
            iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
 
828
            IB;
 
829
 
 
830
    public:
 
831
        typedef typename IB::value_type value_type;
 
832
        typedef typename IB::difference_type difference_type;
 
833
        typedef typename IB::reference reference;
 
834
        typedef typename IB::pointer pointer;
 
835
        typedef InputT iterator_type;
 
836
 
 
837
        multi_pass();
 
838
        explicit multi_pass(InputT input);
 
839
 
 
840
#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
 
841
        multi_pass(int);
 
842
#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
 
843
 
 
844
        ~multi_pass();
 
845
 
 
846
        multi_pass(multi_pass const&);
 
847
        multi_pass& operator=(multi_pass const&);
 
848
 
 
849
        void swap(multi_pass& x);
 
850
 
 
851
        reference operator*() const;
 
852
        pointer operator->() const;
 
853
        multi_pass& operator++();
 
854
        multi_pass operator++(int);
 
855
 
 
856
        void clear_queue();
 
857
 
 
858
        bool operator==(const multi_pass& y) const;
 
859
        bool operator<(const multi_pass& y) const;
 
860
 
 
861
    private: // helper functions
 
862
        bool is_eof() const;
 
863
};
 
864
 
 
865
template
 
866
<
 
867
    typename InputT,
 
868
    typename InputPolicy,
 
869
    typename OwnershipPolicy,
 
870
    typename CheckingPolicy,
 
871
    typename StoragePolicy
 
872
>
 
873
inline
 
874
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
875
multi_pass()
 
876
    : OP()
 
877
    , CHP()
 
878
    , SP()
 
879
    , IP()
 
880
{
 
881
}
 
882
 
 
883
template
 
884
<
 
885
    typename InputT,
 
886
    typename InputPolicy,
 
887
    typename OwnershipPolicy,
 
888
    typename CheckingPolicy,
 
889
    typename StoragePolicy
 
890
>
 
891
inline
 
892
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
893
multi_pass(InputT input)
 
894
    : OP()
 
895
    , CHP()
 
896
    , SP()
 
897
    , IP(input)
 
898
{
 
899
}
 
900
 
 
901
#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
 
902
    // The standard library shipped with gcc-3.1 has a bug in
 
903
    // bits/basic_string.tcc. It tries  to use iter::iter(0) to
 
904
    // construct an iterator. Ironically, this  happens in sanity
 
905
    // checking code that isn't required by the standard.
 
906
    // The workaround is to provide an additional constructor that
 
907
    // ignores its int argument and behaves like the default constructor.
 
908
template
 
909
<
 
910
    typename InputT,
 
911
    typename InputPolicy,
 
912
    typename OwnershipPolicy,
 
913
    typename CheckingPolicy,
 
914
    typename StoragePolicy
 
915
>
 
916
inline
 
917
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
918
multi_pass(int)
 
919
    : OP()
 
920
    , CHP()
 
921
    , SP()
 
922
    , IP()
 
923
{
 
924
}
 
925
#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
 
926
 
 
927
template
 
928
<
 
929
    typename InputT,
 
930
    typename InputPolicy,
 
931
    typename OwnershipPolicy,
 
932
    typename CheckingPolicy,
 
933
    typename StoragePolicy
 
934
>
 
935
inline
 
936
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
937
~multi_pass()
 
938
{
 
939
    if (OP::release())
 
940
    {
 
941
        CHP::destroy();
 
942
        SP::destroy();
 
943
        IP::destroy();
 
944
    }
 
945
}
 
946
 
 
947
template
 
948
<
 
949
    typename InputT,
 
950
    typename InputPolicy,
 
951
    typename OwnershipPolicy,
 
952
    typename CheckingPolicy,
 
953
    typename StoragePolicy
 
954
>
 
955
inline
 
956
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
957
multi_pass(
 
958
        multi_pass const& x)
 
959
    : OP(x)
 
960
    , CHP(x)
 
961
    , SP(x)
 
962
    , IP(x)
 
963
{
 
964
    OP::clone();
 
965
}
 
966
 
 
967
template
 
968
<
 
969
    typename InputT,
 
970
    typename InputPolicy,
 
971
    typename OwnershipPolicy,
 
972
    typename CheckingPolicy,
 
973
    typename StoragePolicy
 
974
>
 
975
inline
 
976
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
 
977
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
978
operator=(
 
979
        multi_pass const& x)
 
980
{
 
981
    multi_pass temp(x);
 
982
    temp.swap(*this);
 
983
    return *this;
 
984
}
 
985
 
 
986
template
 
987
<
 
988
    typename InputT,
 
989
    typename InputPolicy,
 
990
    typename OwnershipPolicy,
 
991
    typename CheckingPolicy,
 
992
    typename StoragePolicy
 
993
>
 
994
inline void
 
995
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
996
swap(multi_pass& x)
 
997
{
 
998
    OP::swap(x);
 
999
    CHP::swap(x);
 
1000
    SP::swap(x);
 
1001
    IP::swap(x);
 
1002
}
 
1003
 
 
1004
template
 
1005
<
 
1006
    typename InputT,
 
1007
    typename InputPolicy,
 
1008
    typename OwnershipPolicy,
 
1009
    typename CheckingPolicy,
 
1010
    typename StoragePolicy
 
1011
>
 
1012
inline
 
1013
typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
1014
reference
 
1015
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
1016
operator*() const
 
1017
{
 
1018
    CHP::check();
 
1019
    return SP::dereference(*this);
 
1020
}
 
1021
 
 
1022
template
 
1023
<
 
1024
    typename InputT,
 
1025
    typename InputPolicy,
 
1026
    typename OwnershipPolicy,
 
1027
    typename CheckingPolicy,
 
1028
    typename StoragePolicy
 
1029
>
 
1030
inline
 
1031
typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
1032
pointer
 
1033
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
1034
operator->() const
 
1035
{
 
1036
    return &(operator*());
 
1037
}
 
1038
 
 
1039
template
 
1040
<
 
1041
    typename InputT,
 
1042
    typename InputPolicy,
 
1043
    typename OwnershipPolicy,
 
1044
    typename CheckingPolicy,
 
1045
    typename StoragePolicy
 
1046
>
 
1047
inline
 
1048
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
 
1049
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
1050
operator++()
 
1051
{
 
1052
    CHP::check();
 
1053
    SP::increment(*this);
 
1054
    return *this;
 
1055
}
 
1056
 
 
1057
template
 
1058
<
 
1059
    typename InputT,
 
1060
    typename InputPolicy,
 
1061
    typename OwnershipPolicy,
 
1062
    typename CheckingPolicy,
 
1063
    typename StoragePolicy
 
1064
>
 
1065
inline
 
1066
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>
 
1067
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
1068
operator++(int)
 
1069
{
 
1070
    multi_pass
 
1071
    <
 
1072
        InputT,
 
1073
        InputPolicy,
 
1074
        OwnershipPolicy,
 
1075
        CheckingPolicy,
 
1076
        StoragePolicy
 
1077
    > tmp(*this);
 
1078
 
 
1079
    ++*this;
 
1080
 
 
1081
    return tmp;
 
1082
}
 
1083
 
 
1084
template
 
1085
<
 
1086
    typename InputT,
 
1087
    typename InputPolicy,
 
1088
    typename OwnershipPolicy,
 
1089
    typename CheckingPolicy,
 
1090
    typename StoragePolicy
 
1091
>
 
1092
inline void
 
1093
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
1094
clear_queue()
 
1095
{
 
1096
    SP::clear_queue();
 
1097
    CHP::clear_queue();
 
1098
}
 
1099
 
 
1100
template
 
1101
<
 
1102
    typename InputT,
 
1103
    typename InputPolicy,
 
1104
    typename OwnershipPolicy,
 
1105
    typename CheckingPolicy,
 
1106
    typename StoragePolicy
 
1107
>
 
1108
inline bool
 
1109
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
1110
is_eof() const
 
1111
{
 
1112
    return SP::is_eof(*this);
 
1113
}
 
1114
 
 
1115
///// Comparisons
 
1116
template
 
1117
<
 
1118
    typename InputT,
 
1119
    typename InputPolicy,
 
1120
    typename OwnershipPolicy,
 
1121
    typename CheckingPolicy,
 
1122
    typename StoragePolicy
 
1123
>
 
1124
inline bool
 
1125
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
1126
operator==(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
 
1127
        StoragePolicy>& y) const
 
1128
{
 
1129
    if (is_eof() && y.is_eof())
 
1130
    {
 
1131
        return true;  // both are EOF
 
1132
    }
 
1133
    else if (is_eof() ^ y.is_eof())
 
1134
    {
 
1135
        return false; // one is EOF, one isn't
 
1136
    }
 
1137
    else if (!IP::same_input(y))
 
1138
    {
 
1139
        return false;
 
1140
    }
 
1141
    else
 
1142
    {
 
1143
        return SP::equal_to(y);
 
1144
    }
 
1145
}
 
1146
 
 
1147
template
 
1148
<
 
1149
    typename InputT,
 
1150
    typename InputPolicy,
 
1151
    typename OwnershipPolicy,
 
1152
    typename CheckingPolicy,
 
1153
    typename StoragePolicy
 
1154
>
 
1155
inline bool
 
1156
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
 
1157
operator<(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
 
1158
        StoragePolicy>& y) const
 
1159
{
 
1160
    return SP::less_than(y);
 
1161
}
 
1162
 
 
1163
template
 
1164
<
 
1165
    typename InputT,
 
1166
    typename InputPolicy,
 
1167
    typename OwnershipPolicy,
 
1168
    typename CheckingPolicy,
 
1169
    typename StoragePolicy
 
1170
>
 
1171
inline
 
1172
bool operator!=(
 
1173
        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
 
1174
                        StoragePolicy>& x,
 
1175
        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
 
1176
                        StoragePolicy>& y)
 
1177
{
 
1178
    return !(x == y);
 
1179
}
 
1180
 
 
1181
template
 
1182
<
 
1183
    typename InputT,
 
1184
    typename InputPolicy,
 
1185
    typename OwnershipPolicy,
 
1186
    typename CheckingPolicy,
 
1187
    typename StoragePolicy
 
1188
>
 
1189
inline
 
1190
bool operator>(
 
1191
        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
 
1192
                        StoragePolicy>& x,
 
1193
        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
 
1194
                        StoragePolicy>& y)
 
1195
{
 
1196
    return y < x;
 
1197
}
 
1198
 
 
1199
template
 
1200
<
 
1201
    typename InputT,
 
1202
    typename InputPolicy,
 
1203
    typename OwnershipPolicy,
 
1204
    typename CheckingPolicy,
 
1205
    typename StoragePolicy
 
1206
>
 
1207
inline
 
1208
bool operator>=(
 
1209
        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
 
1210
                        StoragePolicy>& x,
 
1211
        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
 
1212
                        StoragePolicy>& y)
 
1213
{
 
1214
    return !(x < y);
 
1215
}
 
1216
 
 
1217
template
 
1218
<
 
1219
    typename InputT,
 
1220
    typename InputPolicy,
 
1221
    typename OwnershipPolicy,
 
1222
    typename CheckingPolicy,
 
1223
    typename StoragePolicy
 
1224
>
 
1225
inline
 
1226
bool operator<=(
 
1227
        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
 
1228
                        StoragePolicy>& x,
 
1229
        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
 
1230
                        StoragePolicy>& y)
 
1231
{
 
1232
    return !(y < x);
 
1233
}
 
1234
 
 
1235
///// Generator function
 
1236
template <typename InputT>
 
1237
inline multi_pass<InputT>
 
1238
make_multi_pass(InputT i)
 
1239
{
 
1240
    return multi_pass<InputT>(i);
 
1241
}
 
1242
 
 
1243
// this could be a template typedef, since such a thing doesn't
 
1244
// exist in C++, we'll use inheritance to accomplish the same thing.
 
1245
 
 
1246
template <typename InputT, std::size_t N>
 
1247
class look_ahead :
 
1248
    public multi_pass<
 
1249
        InputT,
 
1250
        multi_pass_policies::input_iterator,
 
1251
        multi_pass_policies::first_owner,
 
1252
        multi_pass_policies::no_check,
 
1253
        multi_pass_policies::fixed_size_queue<N> >
 
1254
{
 
1255
        typedef multi_pass<
 
1256
            InputT,
 
1257
            multi_pass_policies::input_iterator,
 
1258
            multi_pass_policies::first_owner,
 
1259
            multi_pass_policies::no_check,
 
1260
            multi_pass_policies::fixed_size_queue<N> > base_t;
 
1261
    public:
 
1262
        look_ahead()
 
1263
            : base_t() {}
 
1264
 
 
1265
        explicit look_ahead(InputT x)
 
1266
            : base_t(x) {}
 
1267
 
 
1268
        look_ahead(look_ahead const& x)
 
1269
            : base_t(x) {}
 
1270
 
 
1271
#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
 
1272
        look_ahead(int)         // workaround for a bug in the library
 
1273
            : base_t() {}       // shipped with gcc 3.1
 
1274
#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
 
1275
 
 
1276
    // default generated operators destructor and assignment operator are okay.
 
1277
};
 
1278
 
 
1279
template
 
1280
<
 
1281
    typename InputT,
 
1282
    typename InputPolicy,
 
1283
    typename OwnershipPolicy,
 
1284
    typename CheckingPolicy,
 
1285
    typename StoragePolicy
 
1286
>
 
1287
void swap(
 
1288
    multi_pass<
 
1289
        InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
 
1290
    > &x,
 
1291
    multi_pass<
 
1292
        InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
 
1293
    > &y)
 
1294
{
 
1295
    x.swap(y);
 
1296
}
 
1297
 
 
1298
namespace impl {
 
1299
#if __GNUC__ == 2
 
1300
    using std::swap;
 
1301
#endif
 
1302
    template <typename T>
 
1303
    inline void mp_swap(T& t1, T& t2)
 
1304
    {
 
1305
        using std::swap;
 
1306
        using boost::spirit::swap;
 
1307
        swap(t1, t2);
 
1308
    }
 
1309
}
 
1310
 
 
1311
///////////////////////////////////////////////////////////////////////////////
 
1312
}} // namespace boost::spirit
 
1313
 
 
1314
#undef BOOST_SPIRIT_IT_NS
 
1315
#endif  // defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
 
1316
#endif  // BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
 
1317