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