]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Boost.Wave: A Standard compliant C++ preprocessor library | |
3 | ||
4 | Definition of the lexer iterator | |
5 | ||
6 | http://www.boost.org/ | |
7 | ||
8 | Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost | |
9 | Software License, Version 1.0. (See accompanying file | |
10 | LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
11 | =============================================================================*/ | |
12 | ||
13 | #if !defined(SLEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED) | |
14 | #define SLEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED | |
15 | ||
16 | #include <string> | |
20effc67 | 17 | #include <iosfwd> |
7c673cae FG |
18 | |
19 | #include <boost/assert.hpp> | |
20 | #include <boost/shared_ptr.hpp> | |
21 | #include <boost/spirit/include/support_multi_pass.hpp> | |
22 | ||
23 | #include <boost/wave/language_support.hpp> | |
24 | #include <boost/wave/util/file_position.hpp> | |
25 | #include <boost/wave/util/functor_input.hpp> | |
26 | ||
27 | #include "slex_interface.hpp" | |
28 | ||
29 | #if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310) | |
30 | #define BOOST_WAVE_EOF_PREFIX static | |
31 | #else | |
32 | #define BOOST_WAVE_EOF_PREFIX | |
33 | #endif | |
34 | ||
35 | /////////////////////////////////////////////////////////////////////////////// | |
36 | namespace boost { | |
37 | namespace wave { | |
38 | namespace cpplexer { | |
39 | namespace slex { | |
40 | namespace impl { | |
41 | ||
42 | /////////////////////////////////////////////////////////////////////////////// | |
43 | // | |
44 | // lex_iterator_functor_shim | |
45 | // | |
46 | /////////////////////////////////////////////////////////////////////////////// | |
47 | ||
48 | template <typename TokenT> | |
49 | class slex_iterator_functor_shim | |
50 | { | |
51 | typedef typename TokenT::position_type position_type; | |
52 | ||
53 | public: | |
54 | slex_iterator_functor_shim() | |
55 | #if /*0 != __DECCXX_VER || */defined(__PGI) | |
56 | : eof() | |
57 | #endif // 0 != __DECCXX_VER | |
58 | {} | |
59 | ||
60 | // interface to the boost::spirit::classic::iterator_policies::functor_input | |
61 | // policy | |
62 | typedef TokenT result_type; | |
63 | typedef slex_iterator_functor_shim unique; | |
64 | typedef lex_input_interface<TokenT>* shared; | |
65 | ||
66 | BOOST_WAVE_EOF_PREFIX result_type const eof; | |
67 | ||
68 | template <typename MultiPass> | |
69 | static result_type& get_next(MultiPass& mp, result_type& result) | |
70 | { | |
71 | return mp.shared()->ftor->get(result); | |
72 | } | |
73 | ||
74 | // this will be called whenever the last reference to a multi_pass will | |
75 | // be released | |
76 | template <typename MultiPass> | |
77 | static void destroy(MultiPass& mp) | |
78 | { | |
79 | delete mp.shared()->ftor; | |
80 | } | |
81 | ||
82 | template <typename MultiPass> | |
83 | static void set_position(MultiPass& mp, position_type const &pos) | |
84 | { | |
85 | mp.shared()->ftor->set_position(pos); | |
86 | } | |
87 | ||
88 | #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | |
89 | template <typename MultiPass> | |
90 | static bool has_include_guards(MultiPass& mp, std::string& guard_name) | |
91 | { | |
92 | return mp.shared()->ftor->has_include_guards(guard_name); | |
93 | } | |
94 | #endif | |
95 | ||
96 | private: | |
97 | boost::shared_ptr<lex_input_interface<TokenT> > functor_ptr; | |
98 | }; | |
99 | ||
100 | #if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310) | |
101 | /////////////////////////////////////////////////////////////////////////////// | |
102 | // eof token | |
103 | template <typename TokenT> | |
104 | typename slex_iterator_functor_shim<TokenT>::result_type const | |
105 | slex_iterator_functor_shim<TokenT>::eof = | |
106 | typename slex_iterator_functor_shim<TokenT>::result_type(); | |
107 | #endif // 0 != __COMO_VERSION__ | |
108 | ||
109 | /////////////////////////////////////////////////////////////////////////////// | |
110 | } // namespace impl | |
111 | ||
112 | /////////////////////////////////////////////////////////////////////////////// | |
113 | // | |
114 | // slex_iterator | |
115 | // | |
116 | // A generic C++ lexer interface class, which allows to plug in different | |
117 | // lexer implementations (template parameter LexT). The following | |
118 | // requirement apply: | |
119 | // | |
120 | // - the lexer type should have a function implemented, which returnes | |
121 | // the next lexed token from the input stream: | |
122 | // typename LexT::token_type get(); | |
123 | // - at the end of the input stream this function should return the | |
124 | // eof token equivalent | |
125 | // - the lexer should implement a constructor taking two iterators | |
126 | // pointing to the beginning and the end of the input stream and | |
127 | // a third parameter containing the name of the parsed input file, | |
128 | // the 4th parameter contains the information about the mode the | |
129 | // preprocessor is used in (C99/C++ mode etc.) | |
130 | // | |
131 | /////////////////////////////////////////////////////////////////////////////// | |
132 | ||
133 | /////////////////////////////////////////////////////////////////////////////// | |
134 | // Divide the given functor type into its components (unique and shared) | |
135 | // and build a std::pair from these parts | |
136 | template <typename FunctorData> | |
137 | struct make_multi_pass | |
138 | { | |
139 | typedef | |
140 | std::pair<typename FunctorData::unique, typename FunctorData::shared> | |
141 | functor_data_type; | |
142 | typedef typename FunctorData::result_type result_type; | |
143 | ||
144 | typedef boost::spirit::iterator_policies::split_functor_input input_policy; | |
145 | typedef boost::spirit::iterator_policies::ref_counted ownership_policy; | |
146 | #if defined(BOOST_WAVE_DEBUG) | |
147 | typedef boost::spirit::iterator_policies::buf_id_check check_policy; | |
148 | #else | |
149 | typedef boost::spirit::iterator_policies::no_check check_policy; | |
150 | #endif | |
151 | typedef boost::spirit::iterator_policies::split_std_deque storage_policy; | |
152 | ||
153 | typedef boost::spirit::iterator_policies::default_policy< | |
154 | ownership_policy, check_policy, input_policy, storage_policy> | |
155 | policy_type; | |
156 | typedef boost::spirit::multi_pass<functor_data_type, policy_type> type; | |
157 | }; | |
158 | ||
159 | /////////////////////////////////////////////////////////////////////////////// | |
160 | template <typename TokenT> | |
161 | class slex_iterator | |
162 | : public make_multi_pass<impl::slex_iterator_functor_shim<TokenT> >::type | |
163 | { | |
164 | typedef impl::slex_iterator_functor_shim<TokenT> input_policy_type; | |
165 | ||
166 | typedef typename make_multi_pass<input_policy_type>::type base_type; | |
167 | typedef typename make_multi_pass<input_policy_type>::functor_data_type | |
168 | functor_data_type; | |
169 | ||
170 | typedef typename input_policy_type::unique unique_functor_type; | |
171 | typedef typename input_policy_type::shared shared_functor_type; | |
172 | ||
173 | public: | |
174 | typedef TokenT token_type; | |
175 | ||
176 | slex_iterator() | |
177 | {} | |
178 | ||
179 | template <typename IteratorT> | |
180 | slex_iterator(IteratorT const &first, IteratorT const &last, | |
181 | typename TokenT::position_type const &pos, | |
182 | boost::wave::language_support language) | |
183 | : base_type( | |
184 | functor_data_type( | |
185 | unique_functor_type(), | |
186 | slex_input_interface<TokenT> | |
187 | ::new_lexer(first, last, pos, language) | |
188 | ) | |
189 | ) | |
190 | {} | |
191 | ||
192 | void set_position(typename TokenT::position_type const &pos) | |
193 | { | |
194 | typedef typename token_type::position_type position_type; | |
195 | ||
196 | // set the new position in the current token | |
197 | token_type const& currtoken = this->base_type::dereference(*this); | |
198 | position_type currpos = currtoken.get_position(); | |
199 | ||
200 | currpos.set_file(pos.get_file()); | |
201 | currpos.set_line(pos.get_line()); | |
202 | const_cast<token_type&>(currtoken).set_position(currpos); | |
203 | ||
204 | // set the new position for future tokens as well | |
205 | if (token_type::string_type::npos != | |
206 | currtoken.get_value().find_first_of('\n')) | |
207 | { | |
208 | currpos.set_line(pos.get_line() + 1); | |
209 | } | |
210 | unique_functor_type::set_position(*this, currpos); | |
211 | } | |
212 | ||
213 | #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | |
214 | // return, whether the current file has include guards | |
215 | // this function returns meaningful results only if the file was scanned | |
216 | // completely | |
217 | bool has_include_guards(std::string& guard_name) const | |
218 | { | |
219 | return unique_functor_type::has_include_guards(*this, guard_name); | |
220 | } | |
221 | #endif | |
222 | }; | |
223 | ||
224 | /////////////////////////////////////////////////////////////////////////////// | |
225 | } // slex | |
226 | } // namespace cpplexer | |
227 | } // namespace wave | |
228 | } // namespace boost | |
229 | ||
230 | #undef BOOST_WAVE_EOF_PREFIX | |
231 | ||
232 | #endif // !defined(SLEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED) |