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