source: NonGTP/Boost/boost/wave/util/insert_whitespace_detection.hpp @ 857

Revision 857, 10.2 KB checked in by igarcia, 19 years ago (diff)
Line 
1/*=============================================================================
2    Boost.Wave: A Standard compliant C++ preprocessor library
3
4    Detect the need to insert a whitespace token into the output stream
5   
6    http://www.boost.org/
7
8    Copyright (c) 2001-2005 Hartmut Kaiser. Distributed under the Boost
9    Software License, Version 1.0. (See accompanying file
10    LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11=============================================================================*/
12#if !defined(INSERT_WHITESPACE_DETECTION_HPP_765EF77B_0513_4967_BDD6_6A38148C4C96_INCLUDED)
13#define INSERT_WHITESPACE_DETECTION_HPP_765EF77B_0513_4967_BDD6_6A38148C4C96_INCLUDED
14
15#include <boost/wave/wave_config.hpp>   
16#include <boost/wave/token_ids.hpp>   
17
18///////////////////////////////////////////////////////////////////////////////
19namespace boost {
20namespace wave {
21namespace util {
22
23namespace impl {
24
25// T_IDENTIFIER
26    template <typename StringT>
27    inline bool
28    would_form_universal_char (StringT const &value)
29    {
30        if ('u' != value[0] && 'U' != value[0])
31            return false;
32        if ('u' == value[0] && value.size() < 5)
33            return false;
34        if ('U' == value[0] && value.size() < 9)
35            return false;
36   
37    typename StringT::size_type pos =
38        value.find_first_not_of("0123456789abcdefABCDEF", 1);
39       
40        if (StringT::npos == pos ||
41            ('u' == value[0] && pos > 5) ||
42            ('U' == value[0] && pos > 9))
43        {
44            return true;        // would form an universal char
45        }
46        return false;
47    }
48    template <typename StringT>
49    inline bool
50    handle_identifier(boost::wave::token_id prev,
51        boost::wave::token_id before, StringT const &value)
52    {
53        using namespace boost::wave;
54        switch (static_cast<unsigned int>(prev)) {
55        case T_IDENTIFIER:
56        case T_NONREPLACABLE_IDENTIFIER:
57        case T_COMPL_ALT:
58        case T_OR_ALT:
59        case T_AND_ALT:
60        case T_NOT_ALT:
61        case T_XOR_ALT:
62        case T_ANDASSIGN_ALT:
63        case T_ORASSIGN_ALT:
64        case T_XORASSIGN_ALT:
65        case T_NOTEQUAL_ALT:
66        case T_FIXEDPOINTLIT:
67            return true;
68
69        case T_FLOATLIT:
70        case T_INTLIT:
71            return (value.size() > 1 || (value[0] != 'e' && value[0] != 'E'));
72           
73         // avoid constructing universal characters (\u1234)
74        case TOKEN_FROM_ID('\\', UnknownTokenType):
75            return would_form_universal_char(value);
76        }
77        return false;
78    }
79// T_INTLIT
80    inline bool
81    handle_intlit(boost::wave::token_id prev, boost::wave::token_id before)
82    {
83        using namespace boost::wave;
84        switch (static_cast<unsigned int>(prev)) {
85        case T_IDENTIFIER:
86        case T_NONREPLACABLE_IDENTIFIER:
87        case T_INTLIT:
88        case T_FLOATLIT:
89        case T_FIXEDPOINTLIT:
90            return true;
91        }
92        return false;
93    }
94// T_FLOATLIT
95    inline bool
96    handle_floatlit(boost::wave::token_id prev,
97        boost::wave::token_id before)
98    {
99        using namespace boost::wave;
100        switch (static_cast<unsigned int>(prev)) {
101        case T_IDENTIFIER:
102        case T_NONREPLACABLE_IDENTIFIER:
103        case T_INTLIT:
104        case T_FLOATLIT:
105        case T_FIXEDPOINTLIT:
106            return true;
107        }
108        return false;
109    }
110// <% T_LEFTBRACE
111    inline bool
112    handle_alt_leftbrace(boost::wave::token_id prev,
113        boost::wave::token_id before)
114    {
115        using namespace boost::wave;
116        switch (static_cast<unsigned int>(prev)) {
117        case T_LESS:        // <<%
118        case T_SHIFTLEFT:   // <<<%
119            return true;
120        }
121        return false;
122    }
123// <: T_LEFTBRACKET
124    inline bool
125    handle_alt_leftbracket(boost::wave::token_id prev,
126        boost::wave::token_id before)
127    {
128        using namespace boost::wave;
129        switch (static_cast<unsigned int>(prev)) {
130        case T_LESS:        // <<:
131        case T_SHIFTLEFT:   // <<<:
132            return true;
133        }
134        return false;
135    }
136// T_FIXEDPOINTLIT
137    inline bool
138    handle_fixedpointlit(boost::wave::token_id prev,
139        boost::wave::token_id before)
140    {
141        using namespace boost::wave;
142        switch (static_cast<unsigned int>(prev)) {
143        case T_IDENTIFIER:
144        case T_NONREPLACABLE_IDENTIFIER:
145        case T_INTLIT:
146        case T_FLOATLIT:
147        case T_FIXEDPOINTLIT:
148            return true;
149        }
150        return false;
151    }
152// T_DOT
153    inline bool
154    handle_dot(boost::wave::token_id prev, boost::wave::token_id before)
155    {
156        using namespace boost::wave;
157        switch (static_cast<unsigned int>(prev)) {
158        case T_DOT:
159            if (T_DOT == before)
160                return true;    // ...
161            break;
162        }
163        return false;
164    }
165// T_QUESTION_MARK
166    inline bool
167    handle_questionmark(boost::wave::token_id prev,
168        boost::wave::token_id before)
169    {
170        using namespace boost::wave;
171        switch(static_cast<unsigned int>(prev)) {
172        case TOKEN_FROM_ID('\\', UnknownTokenType):     // \?
173        case T_QUESTION_MARK:   // ??
174            return true;
175        }
176        return false;
177    }
178// T_NEWLINE
179    inline bool
180    handle_newline(boost::wave::token_id prev,
181        boost::wave::token_id before)
182    {
183        using namespace boost::wave;
184        switch(static_cast<unsigned int>(prev)) {
185        case TOKEN_FROM_ID('\\', UnknownTokenType): // \ \n
186        case T_DIVIDE:
187            if (T_QUESTION_MARK == before)
188                return true;    // ?/\n     // may be \\n
189            break;
190        }
191        return false;
192    }
193   
194}   // namespace impl
195
196class insert_whitespace_detection
197{
198public:
199    insert_whitespace_detection()
200    :   prev(boost::wave::T_EOF), beforeprev(boost::wave::T_EOF)
201    {}
202   
203    template <typename StringT>
204    bool must_insert(boost::wave::token_id current, StringT const &value)
205    {
206        using namespace boost::wave;
207        switch (current) {
208        case T_NONREPLACABLE_IDENTIFIER:
209        case T_IDENTIFIER:
210            return impl::handle_identifier(prev, beforeprev, value);
211        case T_INTLIT:
212            return impl::handle_intlit(prev, beforeprev);
213        case T_FLOATLIT:
214            return impl::handle_floatlit(prev, beforeprev);
215        case T_STRINGLIT:
216            if (TOKEN_FROM_ID('L', UnknownTokenType) == prev)       // 'L'
217                return true;
218            break;
219        case T_LEFTBRACE_ALT:
220            return impl::handle_alt_leftbrace(prev, beforeprev);
221        case T_LEFTBRACKET_ALT:
222            return impl::handle_alt_leftbracket(prev, beforeprev);
223        case T_FIXEDPOINTLIT:
224            return impl::handle_fixedpointlit(prev, beforeprev);
225        case T_DOT:
226            return impl::handle_dot(prev, beforeprev);
227        case T_QUESTION_MARK:
228            return impl::handle_questionmark(prev, beforeprev);
229        case T_NEWLINE:
230            return impl::handle_newline(prev, beforeprev);
231
232        case T_LEFTPAREN:
233        case T_RIGHTPAREN:
234        case T_LEFTBRACKET:
235        case T_RIGHTBRACKET:
236        case T_SEMICOLON:
237        case T_COMMA:
238        case T_COLON:
239            switch (static_cast<unsigned int>(prev)) {
240            case T_LEFTPAREN:
241            case T_RIGHTPAREN:
242            case T_LEFTBRACKET:
243            case T_RIGHTBRACKET:
244            case T_LEFTBRACE:
245            case T_RIGHTBRACE:
246                return false;   // no insertion between parens/brackets/braces
247
248            default:
249                break;
250            }       
251            break;
252           
253        case T_LEFTBRACE:
254        case T_RIGHTBRACE:
255            switch (static_cast<unsigned int>(prev)) {
256            case T_LEFTPAREN:
257            case T_RIGHTPAREN:
258            case T_LEFTBRACKET:
259            case T_RIGHTBRACKET:
260            case T_LEFTBRACE:
261            case T_RIGHTBRACE:
262            case T_SEMICOLON:
263            case T_COMMA:
264            case T_COLON:
265                return false;   // no insertion between parens/brackets/braces
266
267            case T_QUESTION_MARK:
268                if (T_QUESTION_MARK == beforeprev)
269                    return true;
270                break;
271               
272            default:
273                break;
274            }
275            break;
276                           
277        case T_MINUS:
278        case T_MINUSMINUS:
279        case T_LESS:
280        case T_EQUAL:
281        case T_ASSIGN:
282        case T_GREATER:
283        case T_DIVIDE:
284        case T_CHARLIT:
285        case T_NOT:
286        case T_NOTEQUAL:
287        case T_DIVIDEASSIGN:
288        case T_MINUSASSIGN:
289            if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev)
290                return true;    // ??{op}
291            break;
292
293        case T_COMPL_ALT:
294        case T_OR_ALT:
295        case T_AND_ALT:
296        case T_NOT_ALT:
297        case T_XOR_ALT:
298        case T_ANDASSIGN_ALT:
299        case T_ORASSIGN_ALT:
300        case T_XORASSIGN_ALT:
301        case T_NOTEQUAL_ALT:
302            if (T_IDENTIFIER == prev || T_NONREPLACABLE_IDENTIFIER == prev ||
303                IS_CATEGORY(prev, KeywordTokenType))
304                return true;
305            break;
306        }
307
308    // else, handle operators separately
309        if (IS_CATEGORY(current, OperatorTokenType) &&
310            IS_CATEGORY(prev, OperatorTokenType))
311        {
312            return true;    // operators must be delimited always
313        }
314        return false;
315    }
316    void shift_tokens (boost::wave::token_id next_id)
317    {
318        beforeprev = prev;
319        prev = next_id;
320    }
321   
322private:
323    boost::wave::token_id prev;        // the previous analyzed token
324    boost::wave::token_id beforeprev;  // the token before the previous
325};
326
327///////////////////////////////////////////////////////////////////////////////
328}   //  namespace util
329}   //  namespace wave
330}   //  namespace boost
331
332#endif // !defined(INSERT_WHITESPACE_DETECTION_HPP_765EF77B_0513_4967_BDD6_6A38148C4C96_INCLUDED)
Note: See TracBrowser for help on using the repository browser.