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