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