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(BOOST_CPP_LEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED) 14 #define BOOST_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: lex_iterator_functor_shim()59 lex_iterator_functor_shim() 60 #if /*0 != __DECCXX_VER || */defined(__PGI) 61 : eof() 62 #endif 63 {} 64 65 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310) operator =(lex_iterator_functor_shim const & rhs)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> get_next(MultiPass & mp,result_type & result)78 static result_type& get_next(MultiPass& mp, result_type& result) 79 { 80 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> destroy(MultiPass & mp)86 static void destroy(MultiPass& mp) 87 { 88 delete mp.shared()->ftor; 89 } 90 91 template <typename MultiPass> set_position(MultiPass & mp,position_type const & pos)92 static void set_position(MultiPass& mp, position_type const &pos) 93 { 94 mp.shared()->ftor->set_position(pos); 95 } 96 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 97 template <typename MultiPass> has_include_guards(MultiPass & mp,std::string & guard_name)98 static bool has_include_guards(MultiPass& mp, std::string& guard_name) 99 { 100 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 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 lex_iterator()183 lex_iterator() 184 {} 185 186 template <typename IteratorT> lex_iterator(IteratorT const & first,IteratorT const & last,typename TokenT::position_type const & pos,boost::wave::language_support language)187 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 ::new_lexer(first, last, pos, language) 195 ) 196 ) 197 {} 198 set_position(typename TokenT::position_type const & pos)199 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 token_type const& currtoken = this->base_type::dereference(*this); 205 position_type currpos = currtoken.get_position(); 206 207 currpos.set_file(pos.get_file()); 208 currpos.set_line(pos.get_line()); 209 const_cast<token_type&>(currtoken).set_position(currpos); 210 211 // set the new position for future tokens as well 212 if (token_type::string_type::npos != 213 currtoken.get_value().find_first_of('\n')) 214 { 215 currpos.set_line(pos.get_line() + 1); 216 } 217 unique_functor_type::set_position(*this, currpos); 218 } 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 has_include_guards(std::string & guard_name) const224 bool has_include_guards(std::string& guard_name) const 225 { 226 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(BOOST_CPP_LEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED) 244