1 //  Copyright (c) 2001-2011 Hartmut Kaiser
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #if !defined(BOOST_SPIRIT_LEX_LEXER_ITERATOR_MAR_16_2007_0353PM)
7 #define BOOST_SPIRIT_LEX_LEXER_ITERATOR_MAR_16_2007_0353PM
8 
9 #if defined(_MSC_VER)
10 #pragma once
11 #endif
12 
13 #include <boost/spirit/home/support/multi_pass_wrapper.hpp>
14 #if defined(BOOST_SPIRIT_DEBUG)
15 #include <boost/spirit/home/support/iterators/detail/buf_id_check_policy.hpp>
16 #else
17 #include <boost/spirit/home/support/iterators/detail/no_check_policy.hpp>
18 #endif
19 #include <boost/spirit/home/support/iterators/detail/split_functor_input_policy.hpp>
20 #include <boost/spirit/home/support/iterators/detail/ref_counted_policy.hpp>
21 #include <boost/spirit/home/support/iterators/detail/split_std_deque_policy.hpp>
22 #include <boost/spirit/home/support/iterators/multi_pass.hpp>
23 
24 namespace boost { namespace spirit { namespace lex { namespace lexertl
25 {
26     ///////////////////////////////////////////////////////////////////////////
27     template <typename FunctorData>
28     struct make_multi_pass
29     {
30         // Divide the given functor type into its components (unique and
31         // shared) and build a std::pair from these parts
32         typedef std::pair<typename FunctorData::unique
33           , typename FunctorData::shared> functor_data_type;
34 
35         // This is the result type returned from the iterator
36         typedef typename FunctorData::result_type result_type;
37 
38         // Compose the multi_pass iterator policy type from the appropriate
39         // policies
40         typedef iterator_policies::split_functor_input input_policy;
41         typedef iterator_policies::ref_counted ownership_policy;
42 #if defined(BOOST_SPIRIT_DEBUG)
43         typedef iterator_policies::buf_id_check check_policy;
44 #else
45         typedef iterator_policies::no_check check_policy;
46 #endif
47         typedef iterator_policies::split_std_deque storage_policy;
48 
49         typedef iterator_policies::default_policy<
50                 ownership_policy, check_policy, input_policy, storage_policy>
51             policy_type;
52 
53         // Compose the multi_pass iterator from the policy
54         typedef spirit::multi_pass<functor_data_type, policy_type> type;
55     };
56 
57     ///////////////////////////////////////////////////////////////////////////
58     //  lexer_iterator exposes an iterator for a lexertl based dfa (lexer)
59     //  The template parameters have the same semantics as described for the
60     //  functor above.
61     ///////////////////////////////////////////////////////////////////////////
62     template <typename Functor>
63     class iterator : public make_multi_pass<Functor>::type
64     {
65     public:
66         typedef typename Functor::unique unique_functor_type;
67         typedef typename Functor::shared shared_functor_type;
68 
69         typedef typename Functor::iterator_type base_iterator_type;
70         typedef typename Functor::result_type token_type;
71 
72     private:
73         typedef typename make_multi_pass<Functor>::functor_data_type
74             functor_type;
75         typedef typename make_multi_pass<Functor>::type base_type;
76         typedef typename Functor::char_type char_type;
77 
78     public:
79         // create a new iterator encapsulating the lexer object to be used
80         // for tokenization
81         template <typename IteratorData>
iterator(IteratorData const & iterdata_,base_iterator_type & first,base_iterator_type const & last,char_type const * state=0)82         iterator(IteratorData const& iterdata_, base_iterator_type& first
83               , base_iterator_type const& last, char_type const* state = 0)
84           : base_type(functor_type(unique_functor_type()
85               , shared_functor_type(iterdata_, first, last)))
86         {
87             set_state(map_state(state));
88         }
89 
90         // create an end iterator usable for end of range checking
iterator()91         iterator() {}
92 
93         // (wash): < mgaunard> T it; T it2 = ++it; doesn't ocmpile
94         //         < mgaunard> this gets fixed by adding
iterator(const base_type & base)95         iterator(const base_type& base)
96           : base_type(base) { }
97 
98         // set the new required state for the underlying lexer object
set_state(std::size_t state)99         std::size_t set_state(std::size_t state)
100         {
101             return unique_functor_type::set_state(*this, state);
102         }
103 
104         // get the current state for the underlying lexer object
get_state()105         std::size_t get_state()
106         {
107             return unique_functor_type::get_state(*this);
108         }
109 
110         // map the given state name to a corresponding state id as understood
111         // by the underlying lexer object
map_state(char_type const * statename)112         std::size_t map_state(char_type const* statename)
113         {
114             return (0 != statename)
115               ? unique_functor_type::map_state(*this, statename)
116               : 0;
117         }
118     };
119 }}
120 
121 namespace traits
122 {
123     template <typename Functor>
124     struct is_multi_pass<spirit::lex::lexertl::iterator<Functor> >
125       : mpl::true_ {};
126 
127     template <typename Functor>
clear_queue(spirit::lex::lexertl::iterator<Functor> & mp,BOOST_SCOPED_ENUM (traits::clear_mode)mode)128     void clear_queue(spirit::lex::lexertl::iterator<Functor> & mp
129         , BOOST_SCOPED_ENUM(traits::clear_mode) mode)
130     {
131         mp.clear_queue(mode);
132     }
133 
134     template <typename Functor>
inhibit_clear_queue(spirit::lex::lexertl::iterator<Functor> & mp,bool flag)135     void inhibit_clear_queue(spirit::lex::lexertl::iterator<Functor>& mp, bool flag)
136     {
137         mp.inhibit_clear_queue(flag);
138     }
139 
140     template <typename Functor>
inhibit_clear_queue(spirit::lex::lexertl::iterator<Functor> & mp)141     bool inhibit_clear_queue(spirit::lex::lexertl::iterator<Functor>& mp)
142     {
143         return mp.inhibit_clear_queue();
144     }
145 }
146 
147 }}
148 
149 #endif
150