real_positions.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*=============================================================================
  2. Boost.Wave: A Standard compliant C++ preprocessor library
  3. Sample showing how to correct the positions inside the returned tokens in
  4. a way that these appear to be consecutive (ignoring positions from macro
  5. definitions).
  6. http://www.boost.org/
  7. Copyright (c) 2001-2010 Hartmut Kaiser. Distributed under the Boost
  8. Software License, Version 1.0. (See accompanying file
  9. LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. =============================================================================*/
  11. #include <iostream>
  12. #include <fstream>
  13. #include <iomanip>
  14. #include <string>
  15. #include <vector>
  16. ///////////////////////////////////////////////////////////////////////////////
  17. // Include Wave itself
  18. #include <boost/wave.hpp>
  19. ///////////////////////////////////////////////////////////////////////////////
  20. // Include the lexer stuff
  21. #include "real_position_token.hpp" // token class
  22. #include <boost/wave/cpplexer/cpp_lex_iterator.hpp> // lexer type
  23. #include "correct_token_positions.hpp"
  24. ///////////////////////////////////////////////////////////////////////////////
  25. //
  26. // Special output operator for a lex_token.
  27. //
  28. // Note: this doesn't compile if BOOST_SPIRIT_DEBUG is defined.
  29. //
  30. ///////////////////////////////////////////////////////////////////////////////
  31. template <typename PositionT>
  32. inline std::ostream &
  33. operator<< (std::ostream &stream, lex_token<PositionT> const &t)
  34. {
  35. using namespace std;
  36. using namespace boost::wave;
  37. token_id id = token_id(t);
  38. stream << setw(16)
  39. << left << boost::wave::get_token_name(id) << " ("
  40. << "#" << setw(3) << BASEID_FROM_TOKEN(id);
  41. if (ExtTokenTypeMask & id) {
  42. // this is an extended token id
  43. if (AltTokenType == (id & ExtTokenOnlyMask)) {
  44. stream << ", AltTokenType";
  45. }
  46. else if (TriGraphTokenType == (id & ExtTokenOnlyMask)) {
  47. stream << ", TriGraphTokenType";
  48. }
  49. else if (AltExtTokenType == (id & ExtTokenOnlyMask)){
  50. stream << ", AltExtTokenType";
  51. }
  52. }
  53. stream << "): >";
  54. typedef typename lex_token<PositionT>::string_type string_type;
  55. string_type const& value = t.get_value();
  56. for (std::size_t i = 0; i < value.size(); ++i) {
  57. switch (value[i]) {
  58. case '\r': stream << "\\r"; break;
  59. case '\n': stream << "\\n"; break;
  60. case '\t': stream << "\\t"; break;
  61. default:
  62. stream << value[i];
  63. break;
  64. }
  65. }
  66. stream << "<" << std::endl;
  67. stream << " at: " << t.get_position().get_file() << " ("
  68. << setw(3) << right << t.get_position().get_line() << "/"
  69. << setw(2) << right << t.get_position().get_column()
  70. << ")" << std::endl;
  71. stream << " and: " << t.get_corrected_position().get_file() << " ("
  72. << setw(3) << right << t.get_corrected_position().get_line() << "/"
  73. << setw(2) << right << t.get_corrected_position().get_column()
  74. << ")";
  75. return stream;
  76. }
  77. ///////////////////////////////////////////////////////////////////////////////
  78. // main entry point
  79. int main(int argc, char *argv[])
  80. {
  81. if (2 != argc) {
  82. std::cerr << "Usage: real_positions infile" << std::endl;
  83. return -1;
  84. }
  85. // current file position is saved for exception handling
  86. boost::wave::util::file_position_type current_position;
  87. try {
  88. // Open and read in the specified input file.
  89. std::ifstream instream(argv[1]);
  90. std::string instring;
  91. if (!instream.is_open()) {
  92. std::cerr << "Could not open input file: " << argv[1] << std::endl;
  93. return -2;
  94. }
  95. instream.unsetf(std::ios::skipws);
  96. instring = std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
  97. std::istreambuf_iterator<char>());
  98. // The template real_positions::lex_token<> is the token type to be
  99. // used by the Wave library.
  100. typedef lex_token<> token_type;
  101. // The template boost::wave::cpplexer::lex_iterator<> is the lexer type to
  102. // be used by the Wave library.
  103. typedef boost::wave::cpplexer::lex_iterator<token_type>
  104. lex_iterator_type;
  105. // This is the resulting context type to use. The first template parameter
  106. // should match the iterator type to be used during construction of the
  107. // corresponding context object (see below).
  108. typedef boost::wave::context<
  109. std::string::iterator, lex_iterator_type,
  110. boost::wave::iteration_context_policies::load_file_to_string,
  111. correct_token_position<token_type> >
  112. context_type;
  113. // This preprocessor hooks are used to correct the file positions inside
  114. // the tokens returned from the library
  115. correct_token_position<token_type> hooks(argv[1]);
  116. // The preprocessor iterator shouldn't be constructed directly. It is
  117. // to be generated through a wave::context<> object. This wave:context<>
  118. // object is to be used additionally to initialize and define different
  119. // parameters of the actual preprocessing (not done here).
  120. //
  121. // The preprocessing of the input stream is done on the fly behind the
  122. // scenes during iteration over the context_type::iterator_type stream.
  123. context_type ctx (instring.begin(), instring.end(), argv[1], hooks);
  124. // analyze the input file
  125. context_type::iterator_type first = ctx.begin();
  126. context_type::iterator_type last = ctx.end();
  127. while (first != last) {
  128. current_position = (*first).get_position();
  129. std::cout << *first << std::endl;
  130. ++first;
  131. }
  132. }
  133. catch (boost::wave::cpp_exception const& e) {
  134. // some preprocessing error
  135. std::cerr
  136. << e.file_name() << "(" << e.line_no() << "): "
  137. << e.description() << std::endl;
  138. return 2;
  139. }
  140. catch (std::exception const& e) {
  141. // use last recognized token to retrieve the error position
  142. std::cerr
  143. << current_position.get_file()
  144. << "(" << current_position.get_line() << "): "
  145. << "exception caught: " << e.what()
  146. << std::endl;
  147. return 3;
  148. }
  149. catch (...) {
  150. // use last recognized token to retrieve the error position
  151. std::cerr
  152. << current_position.get_file()
  153. << "(" << current_position.get_line() << "): "
  154. << "unexpected exception caught." << std::endl;
  155. return 4;
  156. }
  157. return 0;
  158. }