1 /*============================================================================= 2 Boost.Wave: A Standard compliant C++ preprocessor library 3 4 http://www.boost.org/ 5 6 Copyright (c) 2001-2010 Hartmut Kaiser. Distributed under the Boost 7 Software License, Version 1.0. (See accompanying file 8 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 =============================================================================*/ 10 11 #if !defined(BOOST_CORRECT_TOKEN_POSITIONS_HK_061106_INCLUDED) 12 #define BOOST_CORRECT_TOKEN_POSITIONS_HK_061106_INCLUDED 13 14 #include <boost/iterator/transform_iterator.hpp> 15 16 /////////////////////////////////////////////////////////////////////////////// 17 namespace detail 18 { 19 // count the newlines in a C style comment 20 template <typename String> count_newlines(String const & str)21 unsigned count_newlines(String const& str) 22 { 23 unsigned newlines = 0; 24 typename String::size_type p = str.find_first_of('\n'); 25 while (p != String::npos) 26 { 27 ++newlines; 28 p = str.find_first_of('\n', p+1); 29 } 30 return newlines; 31 } 32 33 // return the length of the last line in a C style comment 34 template <typename String> last_line_length(String const & str)35 unsigned last_line_length(String const& str) 36 { 37 unsigned len = str.size(); 38 typename String::size_type p = str.find_last_of('\n'); 39 if (p != String::npos) 40 len -= p; 41 return len; 42 } 43 } 44 45 /////////////////////////////////////////////////////////////////////////////// 46 // This is the position correcting functor 47 template <typename Token> 48 struct correct_token_position 49 : public boost::wave::context_policies::eat_whitespace<Token> 50 { correct_token_positioncorrect_token_position51 correct_token_position(typename Token::string_type filename) 52 : pos(filename) {} 53 54 /////////////////////////////////////////////////////////////////////////// 55 // 56 // The function 'generated_token' will be called by the library whenever a 57 // token is about to be returned from the library. 58 // 59 // The parameter 'ctx' is a reference to the context object used for 60 // instantiating the preprocessing iterators by the user. 61 // 62 // The parameter 't' is the token about to be returned from the library. 63 // This function may alter the token, but in this case it must be 64 // implemented with a corresponding signature: 65 // 66 // TokenT const& 67 // generated_token(ContextT const& ctx, TokenT& t); 68 // 69 // which makes it possible to modify the token in place. 70 // 71 // The default behavior is to return the token passed as the parameter 72 // without modification. 73 // 74 /////////////////////////////////////////////////////////////////////////// 75 template <typename Context> 76 Token const& generated_tokencorrect_token_position77 generated_token(Context const& ctx, Token& token) 78 { 79 typedef typename Token::string_type string_type; 80 typedef typename Token::position_type position_type; 81 82 using namespace boost::wave; 83 84 // adjust the current position 85 position_type current_pos(pos); 86 87 token_id id = token_id(token); 88 string_type const& v (token.get_value()); 89 90 switch (id) { 91 case T_NEWLINE: 92 case T_CPPCOMMENT: 93 pos.set_line(current_pos.get_line()+1); 94 pos.set_column(1); 95 break; 96 97 case T_CCOMMENT: 98 { 99 unsigned lines = detail::count_newlines(v); 100 if (lines > 0) { 101 pos.set_line(current_pos.get_line() + lines); 102 pos.set_column(detail::last_line_length(v)); 103 } 104 else { 105 pos.set_column(current_pos.get_column() + 106 detail::last_line_length(v)); 107 } 108 } 109 break; 110 111 default: 112 pos.set_column(current_pos.get_column() + v.size()); 113 break; 114 } 115 116 // set the new position in the token to be returned 117 token.set_corrected_position(current_pos); 118 return token; 119 } 120 121 typename Token::position_type pos; 122 }; 123 124 /////////////////////////////////////////////////////////////////////////////// 125 126 #endif 127