cpp_tokens.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*=============================================================================
  2. Boost.Wave: A Standard compliant C++ preprocessor library
  3. Sample: Print out the preprocessed tokens returned by the Wave iterator
  4. This sample shows, how it is possible to use a custom lexer type and a
  5. custom token type with the Wave library.
  6. http://www.boost.org/
  7. Copyright (c) 2001-2012 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 "cpp_tokens.hpp" // global configuration
  12. ///////////////////////////////////////////////////////////////////////////////
  13. // Include Wave itself
  14. #include <boost/wave.hpp>
  15. ///////////////////////////////////////////////////////////////////////////////
  16. // The following files contain the custom lexer type to use
  17. #include "slex_token.hpp"
  18. #include "slex_iterator.hpp"
  19. ///////////////////////////////////////////////////////////////////////////////
  20. // include lexer specifics, import lexer names
  21. #if !defined(BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION)
  22. #include "slex/cpp_slex_lexer.hpp"
  23. #endif // !defined(BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION)
  24. ///////////////////////////////////////////////////////////////////////////////
  25. // import required names
  26. using namespace boost::spirit::classic;
  27. using std::string;
  28. using std::getline;
  29. using std::ifstream;
  30. using std::cout;
  31. using std::cerr;
  32. using std::endl;
  33. using std::ostream;
  34. ///////////////////////////////////////////////////////////////////////////////
  35. // main program
  36. int
  37. main(int argc, char *argv[])
  38. {
  39. if (2 != argc) {
  40. cout << "Usage: cpp_tokens input_file" << endl;
  41. return 1;
  42. }
  43. // read the file to analyse into a std::string
  44. ifstream infile(argv[1]);
  45. string teststr;
  46. if (infile.is_open()) {
  47. infile.unsetf(std::ios::skipws);
  48. #if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
  49. // this is known to be very slow for large files on some systems
  50. copy (std::istream_iterator<char>(infile),
  51. std::istream_iterator<char>(),
  52. std::inserter(teststr, teststr.end()));
  53. #else
  54. teststr = std::string(std::istreambuf_iterator<char>(infile.rdbuf()),
  55. std::istreambuf_iterator<char>());
  56. #endif
  57. }
  58. else {
  59. teststr = argv[1];
  60. }
  61. // The following typedef does the trick. It defines the context type to use,
  62. // which depends on the lexer type (provided by the second template
  63. // parameter). Our lexer type 'slex_iterator<>' depends on a custom token type
  64. // 'slex_token<>'. Our custom token type differs from the original one provided
  65. // by the Wave library only by defining an additional operator<<(), which is
  66. // used to dump the token information carried by a given token (see loop
  67. // below).
  68. typedef boost::wave::cpplexer::slex_token<> token_type;
  69. typedef boost::wave::cpplexer::slex::slex_iterator<token_type> lexer_type;
  70. typedef boost::wave::context<std::string::iterator, lexer_type>
  71. context_type;
  72. // The C++ preprocessor iterator shouldn't be constructed directly. It is to be
  73. // generated through a boost::wave::context<> object. This object is
  74. // additionally to be used to initialize and define different parameters of
  75. // the actual preprocessing.
  76. // The preprocessing of the input stream is done on the fly behind the scenes
  77. // during iteration over the context_type::iterator_type stream.
  78. context_type ctx (teststr.begin(), teststr.end(), argv[1]);
  79. ctx.set_language(boost::wave::support_cpp0x);
  80. ctx.set_language(boost::wave::enable_preserve_comments(ctx.get_language()));
  81. ctx.set_language(boost::wave::enable_prefer_pp_numbers(ctx.get_language()));
  82. ctx.set_language(boost::wave::enable_emit_contnewlines(ctx.get_language()));
  83. context_type::iterator_type first = ctx.begin();
  84. context_type::iterator_type last = ctx.end();
  85. context_type::token_type current_token;
  86. try {
  87. // Traverse over the tokens generated from the input and dump the token
  88. // contents.
  89. while (first != last) {
  90. // retrieve next token
  91. current_token = *first;
  92. // output token info
  93. cout << "matched " << current_token << endl;
  94. ++first;
  95. }
  96. }
  97. catch (boost::wave::cpp_exception const& e) {
  98. // some preprocessing error
  99. cerr
  100. << e.file_name() << "(" << e.line_no() << "): "
  101. << e.description() << endl;
  102. return 2;
  103. }
  104. catch (std::exception const& e) {
  105. // use last recognized token to retrieve the error position
  106. cerr
  107. << current_token.get_position().get_file()
  108. << "(" << current_token.get_position().get_line() << "): "
  109. << "unexpected exception: " << e.what()
  110. << endl;
  111. return 3;
  112. }
  113. catch (...) {
  114. // use last recognized token to retrieve the error position
  115. cerr
  116. << current_token.get_position().get_file()
  117. << "(" << current_token.get_position().get_line() << "): "
  118. << "unexpected exception." << endl;
  119. return 4;
  120. }
  121. return 0;
  122. }