correct_token_positions.hpp 4.1 KB

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