1 /*============================================================================= 2 Boost.Wave: A Standard compliant C++ preprocessor library 3 4 Definition of the lexer iterator for the xpressive lexer 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(XLEX_ITERATOR_HPP) 14 #define XLEX_ITERATOR_HPP 15 16 #include <string> 17 #include <iosfwd> 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 "xlex_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 xlex { 40 namespace impl { 41 42 /////////////////////////////////////////////////////////////////////////////// 43 // 44 // lex_iterator_functor_shim 45 // 46 /////////////////////////////////////////////////////////////////////////////// 47 48 template <typename TokenT> 49 class xlex_iterator_functor_shim 50 { 51 typedef typename TokenT::position_type position_type; 52 53 public: xlex_iterator_functor_shim()54 xlex_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 64 BOOST_WAVE_EOF_PREFIX result_type const eof; 65 typedef xlex_iterator_functor_shim unique; 66 typedef lex_input_interface<TokenT>* shared; 67 68 template <typename MultiPass> get_next(MultiPass & mp,result_type & result)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> destroy(MultiPass & mp)77 static void destroy(MultiPass& mp) 78 { 79 delete mp.shared()->ftor; 80 } 81 82 template <typename MultiPass> set_position(MultiPass & mp,position_type const & pos)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> has_include_guards(MultiPass & mp,std::string & guard_name)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 xlex_iterator_functor_shim<TokenT>::result_type const 105 xlex_iterator_functor_shim<TokenT>::eof = 106 typename xlex_iterator_functor_shim<TokenT>::result_type(); 107 #endif // 0 != __COMO_VERSION__ 108 109 /////////////////////////////////////////////////////////////////////////////// 110 } // namespace impl 111 112 /////////////////////////////////////////////////////////////////////////////// 113 // 114 // xlex_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 returns 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 xlex_iterator 162 : public make_multi_pass<impl::xlex_iterator_functor_shim<TokenT> >::type 163 { 164 typedef impl::xlex_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 xlex_iterator()176 xlex_iterator() 177 {} 178 179 template <typename IteratorT> xlex_iterator(IteratorT const & first,IteratorT const & last,typename TokenT::position_type const & pos,boost::wave::language_support language)180 xlex_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 xlex_input_interface<TokenT> 187 ::new_lexer(first, last, pos, language) 188 ) 189 ) 190 {} 191 set_position(typename TokenT::position_type const & pos)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 has_include_guards(std::string & guard_name) const217 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 } // namespace xlex 226 } // namespace cpplexer 227 } // namespace wave 228 } // namespace boost 229 230 #undef BOOST_WAVE_EOF_PREFIX 231 232 #endif // !defined(XLEX_ITERATOR_HPP) 233