1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
4 Sample showing how to correct the positions inside the returned tokens in
5 a way that these appear to be consecutive (ignoring positions from macro
10 Copyright (c) 2001-2010 Hartmut Kaiser. Distributed under the Boost
11 Software License, Version 1.0. (See accompanying file
12 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13 =============================================================================*/
21 ///////////////////////////////////////////////////////////////////////////////
22 // Include Wave itself
23 #include <boost/wave.hpp>
25 ///////////////////////////////////////////////////////////////////////////////
26 // Include the lexer stuff
27 #include "real_position_token.hpp" // token class
28 #include <boost/wave/cpplexer/cpp_lex_iterator.hpp> // lexer type
30 #include "correct_token_positions.hpp"
32 ///////////////////////////////////////////////////////////////////////////////
34 // Special output operator for a lex_token.
36 // Note: this doesn't compile if BOOST_SPIRIT_DEBUG is defined.
38 ///////////////////////////////////////////////////////////////////////////////
39 template <typename PositionT
>
41 operator<< (std::ostream
&stream
, lex_token
<PositionT
> const &t
)
44 using namespace boost::wave
;
46 token_id id
= token_id(t
);
48 << left
<< boost::wave::get_token_name(id
) << " ("
49 << "#" << setw(3) << BASEID_FROM_TOKEN(id
);
51 if (ExtTokenTypeMask
& id
) {
52 // this is an extended token id
53 if (AltTokenType
== (id
& ExtTokenOnlyMask
)) {
54 stream
<< ", AltTokenType";
56 else if (TriGraphTokenType
== (id
& ExtTokenOnlyMask
)) {
57 stream
<< ", TriGraphTokenType";
59 else if (AltExtTokenType
== (id
& ExtTokenOnlyMask
)){
60 stream
<< ", AltExtTokenType";
66 typedef typename lex_token
<PositionT
>::string_type string_type
;
68 string_type
const& value
= t
.get_value();
69 for (std::size_t i
= 0; i
< value
.size(); ++i
) {
71 case '\r': stream
<< "\\r"; break;
72 case '\n': stream
<< "\\n"; break;
73 case '\t': stream
<< "\\t"; break;
79 stream
<< "<" << std::endl
;
80 stream
<< " at: " << t
.get_position().get_file() << " ("
81 << setw(3) << right
<< t
.get_position().get_line() << "/"
82 << setw(2) << right
<< t
.get_position().get_column()
84 stream
<< " and: " << t
.get_corrected_position().get_file() << " ("
85 << setw(3) << right
<< t
.get_corrected_position().get_line() << "/"
86 << setw(2) << right
<< t
.get_corrected_position().get_column()
92 ///////////////////////////////////////////////////////////////////////////////
94 int main(int argc
, char *argv
[])
97 std::cerr
<< "Usage: real_positions infile" << std::endl
;
101 // current file position is saved for exception handling
102 boost::wave::util::file_position_type current_position
;
105 // Open and read in the specified input file.
106 std::ifstream
instream(argv
[1]);
107 std::string instring
;
109 if (!instream
.is_open()) {
110 std::cerr
<< "Could not open input file: " << argv
[1] << std::endl
;
113 instream
.unsetf(std::ios::skipws
);
114 instring
= std::string(std::istreambuf_iterator
<char>(instream
.rdbuf()),
115 std::istreambuf_iterator
<char>());
117 // The template real_positions::lex_token<> is the token type to be
118 // used by the Wave library.
119 typedef lex_token
<> token_type
;
121 // The template boost::wave::cpplexer::lex_iterator<> is the lexer type to
122 // be used by the Wave library.
123 typedef boost::wave::cpplexer::lex_iterator
<token_type
>
126 // This is the resulting context type to use. The first template parameter
127 // should match the iterator type to be used during construction of the
128 // corresponding context object (see below).
129 typedef boost::wave::context
<
130 std::string::iterator
, lex_iterator_type
,
131 boost::wave::iteration_context_policies::load_file_to_string
,
132 correct_token_position
<token_type
> >
135 // This preprocessor hooks are used to correct the file positions inside
136 // the tokens returned from the library
137 correct_token_position
<token_type
> hooks(argv
[1]);
139 // The preprocessor iterator shouldn't be constructed directly. It is
140 // to be generated through a wave::context<> object. This wave:context<>
141 // object is to be used additionally to initialize and define different
142 // parameters of the actual preprocessing (not done here).
144 // The preprocessing of the input stream is done on the fly behind the
145 // scenes during iteration over the context_type::iterator_type stream.
146 context_type
ctx (instring
.begin(), instring
.end(), argv
[1], hooks
);
148 // analyze the input file
149 context_type::iterator_type first
= ctx
.begin();
150 context_type::iterator_type last
= ctx
.end();
152 while (first
!= last
) {
153 current_position
= (*first
).get_position();
154 std::cout
<< *first
<< std::endl
;
158 catch (boost::wave::cpp_exception
const& e
) {
159 // some preprocessing error
161 << e
.file_name() << "(" << e
.line_no() << "): "
162 << e
.description() << std::endl
;
165 catch (std::exception
const& e
) {
166 // use last recognized token to retrieve the error position
168 << current_position
.get_file()
169 << "(" << current_position
.get_line() << "): "
170 << "exception caught: " << e
.what()
175 // use last recognized token to retrieve the error position
177 << current_position
.get_file()
178 << "(" << current_position
.get_line() << "): "
179 << "unexpected exception caught." << std::endl
;