Line data Source code
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(CPP_LEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED) 14 : #define CPP_LEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED 15 : 16 : #include <string> 17 : 18 : #include <boost/assert.hpp> 19 : #include <boost/intrusive_ptr.hpp> 20 : 21 : #include <boost/wave/wave_config.hpp> 22 : #include <boost/spirit/include/support_multi_pass.hpp> 23 : 24 : #include <boost/wave/util/file_position.hpp> 25 : #include <boost/wave/util/functor_input.hpp> 26 : #include <boost/wave/cpplexer/cpp_lex_interface_generator.hpp> 27 : 28 : #include <boost/wave/language_support.hpp> 29 : 30 : // this must occur after all of the includes and before any code appears 31 : #ifdef BOOST_HAS_ABI_HEADERS 32 : #include BOOST_ABI_PREFIX 33 : #endif 34 : 35 : #if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310) 36 : #define BOOST_WAVE_EOF_PREFIX static 37 : #else 38 : #define BOOST_WAVE_EOF_PREFIX 39 : #endif 40 : 41 : /////////////////////////////////////////////////////////////////////////////// 42 : namespace boost { 43 : namespace wave { 44 : namespace cpplexer { 45 : namespace impl { 46 : 47 : /////////////////////////////////////////////////////////////////////////////// 48 : // 49 : // lex_iterator_functor_shim 50 : // 51 : /////////////////////////////////////////////////////////////////////////////// 52 : 53 : template <typename TokenT> 54 : class lex_iterator_functor_shim 55 : { 56 : typedef typename TokenT::position_type position_type; 57 : 58 : public: 59 0 : lex_iterator_functor_shim() 60 : #if /*0 != __DECCXX_VER || */defined(__PGI) 61 : : eof() 62 : #endif 63 : {} 64 : 65 : #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310) 66 : lex_iterator_functor_shim& operator= (lex_iterator_functor_shim const& rhs) 67 : { return *this; } // nothing to do here 68 : #endif 69 : 70 : // interface to the iterator_policies::split_functor_input policy 71 : typedef TokenT result_type; 72 : typedef lex_iterator_functor_shim unique; 73 : typedef lex_input_interface<TokenT>* shared; 74 : 75 : BOOST_WAVE_EOF_PREFIX result_type const eof; 76 : 77 : template <typename MultiPass> 78 0 : static result_type& get_next(MultiPass& mp, result_type& result) 79 : { 80 0 : return mp.shared()->ftor->get(result); 81 : } 82 : 83 : // this will be called whenever the last reference to a multi_pass will 84 : // be released 85 : template <typename MultiPass> 86 0 : static void destroy(MultiPass& mp) 87 : { 88 0 : delete mp.shared()->ftor; 89 : } 90 : 91 : template <typename MultiPass> 92 0 : static void set_position(MultiPass& mp, position_type const &pos) 93 : { 94 0 : mp.shared()->ftor->set_position(pos); 95 0 : } 96 : #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 97 : template <typename MultiPass> 98 0 : static bool has_include_guards(MultiPass& mp, std::string& guard_name) 99 : { 100 0 : return mp.shared()->ftor->has_include_guards(guard_name); 101 : } 102 : #endif 103 : }; 104 : 105 : /////////////////////////////////////////////////////////////////////////////// 106 : // eof token 107 : #if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310) 108 : template <typename TokenT> 109 : typename lex_iterator_functor_shim<TokenT>::result_type const 110 : lex_iterator_functor_shim<TokenT>::eof; 111 : #endif // 0 != __COMO_VERSION__ 112 : 113 : /////////////////////////////////////////////////////////////////////////////// 114 : } // namespace impl 115 : 116 : /////////////////////////////////////////////////////////////////////////////// 117 : // 118 : // lex_iterator 119 : // 120 : // A generic C++ lexer interface class, which allows to plug in different 121 : // lexer implementations. The interface between the lexer type used and 122 : // the preprocessor component depends on the token type only (template 123 : // parameter TokenT). 124 : // Additionally, the following requirements apply: 125 : // 126 : // - the lexer type should have a function implemented, which returnes 127 : // the next lexed token from the input stream: 128 : // typename TokenT get(); 129 : // - at the end of the input stream this function should return the 130 : // eof token equivalent 131 : // - the lexer should implement a constructor taking two iterators 132 : // pointing to the beginning and the end of the input stream, 133 : // a third parameter containing the name of the parsed input file 134 : // and a 4th parameter of the type boost::wave::language_support 135 : // which specifies, which language subset should be supported (C++, 136 : // C99, C++11 etc.). 137 : // 138 : /////////////////////////////////////////////////////////////////////////////// 139 : 140 : /////////////////////////////////////////////////////////////////////////////// 141 : // Divide the given functor type into its components (unique and shared) 142 : // and build a std::pair from these parts 143 : template <typename FunctorData> 144 : struct make_multi_pass 145 : { 146 : typedef 147 : std::pair<typename FunctorData::unique, typename FunctorData::shared> 148 : functor_data_type; 149 : typedef typename FunctorData::result_type result_type; 150 : 151 : typedef boost::spirit::iterator_policies::split_functor_input input_policy; 152 : typedef boost::spirit::iterator_policies::ref_counted ownership_policy; 153 : #if defined(BOOST_WAVE_DEBUG) 154 : typedef boost::spirit::iterator_policies::buf_id_check check_policy; 155 : #else 156 : typedef boost::spirit::iterator_policies::no_check check_policy; 157 : #endif 158 : typedef boost::spirit::iterator_policies::split_std_deque storage_policy; 159 : 160 : typedef boost::spirit::iterator_policies::default_policy< 161 : ownership_policy, check_policy, input_policy, storage_policy> 162 : policy_type; 163 : typedef boost::spirit::multi_pass<functor_data_type, policy_type> type; 164 : }; 165 : 166 : /////////////////////////////////////////////////////////////////////////////// 167 : template <typename TokenT> 168 0 : class lex_iterator 169 : : public make_multi_pass<impl::lex_iterator_functor_shim<TokenT> >::type 170 : { 171 : typedef impl::lex_iterator_functor_shim<TokenT> input_policy_type; 172 : 173 : typedef typename make_multi_pass<input_policy_type>::type base_type; 174 : typedef typename make_multi_pass<input_policy_type>::functor_data_type 175 : functor_data_type; 176 : 177 : typedef typename input_policy_type::unique unique_functor_type; 178 : typedef typename input_policy_type::shared shared_functor_type; 179 : 180 : public: 181 : typedef TokenT token_type; 182 : 183 0 : lex_iterator() 184 0 : {} 185 : 186 : template <typename IteratorT> 187 0 : lex_iterator(IteratorT const &first, IteratorT const &last, 188 : typename TokenT::position_type const &pos, 189 : boost::wave::language_support language) 190 : : base_type( 191 : functor_data_type( 192 : unique_functor_type(), 193 : lex_input_interface_generator<TokenT> 194 0 : ::new_lexer(first, last, pos, language) 195 : ) 196 0 : ) 197 : {} 198 : 199 0 : void set_position(typename TokenT::position_type const &pos) 200 : { 201 : typedef typename TokenT::position_type position_type; 202 : 203 : // set the new position in the current token 204 0 : token_type const& currtoken = this->base_type::dereference(*this); 205 0 : position_type currpos = currtoken.get_position(); 206 : 207 0 : currpos.set_file(pos.get_file()); 208 0 : currpos.set_line(pos.get_line()); 209 0 : const_cast<token_type&>(currtoken).set_position(currpos); 210 : 211 : // set the new position for future tokens as well 212 0 : if (token_type::string_type::npos != 213 0 : currtoken.get_value().find_first_of('\n')) 214 : { 215 0 : currpos.set_line(pos.get_line() + 1); 216 : } 217 0 : unique_functor_type::set_position(*this, currpos); 218 0 : } 219 : 220 : #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 221 : // return, whether the current file has include guards 222 : // this function returns meaningful results only if the file was scanned 223 : // completely 224 0 : bool has_include_guards(std::string& guard_name) const 225 : { 226 0 : return unique_functor_type::has_include_guards(*this, guard_name); 227 : } 228 : #endif 229 : }; 230 : 231 : /////////////////////////////////////////////////////////////////////////////// 232 : } // namespace cpplexer 233 : } // namespace wave 234 : } // namespace boost 235 : 236 : // the suffix header occurs after all of the code 237 : #ifdef BOOST_HAS_ABI_HEADERS 238 : #include BOOST_ABI_SUFFIX 239 : #endif 240 : 241 : #undef BOOST_WAVE_EOF_PREFIX 242 : 243 : #endif // !defined(CPP_LEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED)