]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Boost.Wave: A Standard compliant C++ preprocessor library | |
3 | ||
4 | Detect the need to insert a whitespace token into the output stream | |
b32b8144 | 5 | |
7c673cae FG |
6 | http://www.boost.org/ |
7 | ||
8 | Copyright (c) 2001-2012 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 | ||
b32b8144 FG |
15 | #include <boost/wave/wave_config.hpp> |
16 | #include <boost/wave/token_ids.hpp> | |
7c673cae FG |
17 | |
18 | // this must occur after all of the includes and before any code appears | |
19 | #ifdef BOOST_HAS_ABI_HEADERS | |
20 | #include BOOST_ABI_PREFIX | |
21 | #endif | |
22 | ||
23 | /////////////////////////////////////////////////////////////////////////////// | |
24 | namespace boost { | |
25 | namespace wave { | |
26 | namespace util { | |
27 | ||
28 | namespace impl { | |
29 | ||
30 | // T_IDENTIFIER | |
31 | template <typename StringT> | |
32 | inline bool | |
33 | would_form_universal_char (StringT const &value) | |
34 | { | |
35 | if ('u' != value[0] && 'U' != value[0]) | |
36 | return false; | |
37 | if ('u' == value[0] && value.size() < 5) | |
38 | return false; | |
39 | if ('U' == value[0] && value.size() < 9) | |
40 | return false; | |
b32b8144 FG |
41 | |
42 | typename StringT::size_type pos = | |
7c673cae | 43 | value.find_first_not_of("0123456789abcdefABCDEF", 1); |
b32b8144 FG |
44 | |
45 | if (StringT::npos == pos || | |
7c673cae FG |
46 | ('u' == value[0] && pos > 5) || |
47 | ('U' == value[0] && pos > 9)) | |
48 | { | |
49 | return true; // would form an universal char | |
50 | } | |
51 | return false; | |
52 | } | |
53 | template <typename StringT> | |
b32b8144 FG |
54 | inline bool |
55 | handle_identifier(boost::wave::token_id prev, | |
7c673cae FG |
56 | boost::wave::token_id before, StringT const &value) |
57 | { | |
58 | using namespace boost::wave; | |
b32b8144 | 59 | switch (prev) { |
7c673cae FG |
60 | case T_IDENTIFIER: |
61 | case T_NONREPLACABLE_IDENTIFIER: | |
62 | case T_COMPL_ALT: | |
63 | case T_OR_ALT: | |
64 | case T_AND_ALT: | |
65 | case T_NOT_ALT: | |
66 | case T_XOR_ALT: | |
67 | case T_ANDASSIGN_ALT: | |
68 | case T_ORASSIGN_ALT: | |
69 | case T_XORASSIGN_ALT: | |
70 | case T_NOTEQUAL_ALT: | |
71 | case T_FIXEDPOINTLIT: | |
72 | return true; | |
73 | ||
74 | case T_FLOATLIT: | |
75 | case T_INTLIT: | |
76 | case T_PP_NUMBER: | |
77 | return (value.size() > 1 || (value[0] != 'e' && value[0] != 'E')); | |
b32b8144 | 78 | |
7c673cae | 79 | // avoid constructing universal characters (\u1234) |
b32b8144 | 80 | case T_UNKNOWN_UNIVERSALCHAR: |
7c673cae | 81 | return would_form_universal_char(value); |
b32b8144 FG |
82 | |
83 | default: | |
84 | break; | |
7c673cae FG |
85 | } |
86 | return false; | |
87 | } | |
88 | // T_INTLIT | |
b32b8144 | 89 | inline bool |
7c673cae FG |
90 | handle_intlit(boost::wave::token_id prev, boost::wave::token_id /*before*/) |
91 | { | |
92 | using namespace boost::wave; | |
b32b8144 | 93 | switch (prev) { |
7c673cae FG |
94 | case T_IDENTIFIER: |
95 | case T_NONREPLACABLE_IDENTIFIER: | |
96 | case T_INTLIT: | |
97 | case T_FLOATLIT: | |
98 | case T_FIXEDPOINTLIT: | |
99 | case T_PP_NUMBER: | |
100 | return true; | |
b32b8144 FG |
101 | |
102 | default: | |
103 | break; | |
7c673cae FG |
104 | } |
105 | return false; | |
106 | } | |
107 | // T_FLOATLIT | |
b32b8144 FG |
108 | inline bool |
109 | handle_floatlit(boost::wave::token_id prev, | |
7c673cae FG |
110 | boost::wave::token_id /*before*/) |
111 | { | |
112 | using namespace boost::wave; | |
b32b8144 | 113 | switch (prev) { |
7c673cae FG |
114 | case T_IDENTIFIER: |
115 | case T_NONREPLACABLE_IDENTIFIER: | |
116 | case T_INTLIT: | |
117 | case T_FLOATLIT: | |
118 | case T_FIXEDPOINTLIT: | |
119 | case T_PP_NUMBER: | |
120 | return true; | |
b32b8144 FG |
121 | |
122 | default: | |
123 | break; | |
7c673cae FG |
124 | } |
125 | return false; | |
126 | } | |
127 | // <% T_LEFTBRACE | |
b32b8144 FG |
128 | inline bool |
129 | handle_alt_leftbrace(boost::wave::token_id prev, | |
7c673cae FG |
130 | boost::wave::token_id /*before*/) |
131 | { | |
132 | using namespace boost::wave; | |
b32b8144 | 133 | switch (prev) { |
7c673cae FG |
134 | case T_LESS: // <<% |
135 | case T_SHIFTLEFT: // <<<% | |
136 | return true; | |
b32b8144 FG |
137 | |
138 | default: | |
139 | break; | |
7c673cae FG |
140 | } |
141 | return false; | |
142 | } | |
143 | // <: T_LEFTBRACKET | |
b32b8144 FG |
144 | inline bool |
145 | handle_alt_leftbracket(boost::wave::token_id prev, | |
7c673cae FG |
146 | boost::wave::token_id /*before*/) |
147 | { | |
148 | using namespace boost::wave; | |
b32b8144 | 149 | switch (prev) { |
7c673cae FG |
150 | case T_LESS: // <<: |
151 | case T_SHIFTLEFT: // <<<: | |
152 | return true; | |
b32b8144 FG |
153 | |
154 | default: | |
155 | break; | |
7c673cae FG |
156 | } |
157 | return false; | |
158 | } | |
159 | // T_FIXEDPOINTLIT | |
b32b8144 FG |
160 | inline bool |
161 | handle_fixedpointlit(boost::wave::token_id prev, | |
7c673cae FG |
162 | boost::wave::token_id /*before*/) |
163 | { | |
164 | using namespace boost::wave; | |
b32b8144 | 165 | switch (prev) { |
7c673cae FG |
166 | case T_IDENTIFIER: |
167 | case T_NONREPLACABLE_IDENTIFIER: | |
168 | case T_INTLIT: | |
169 | case T_FLOATLIT: | |
170 | case T_FIXEDPOINTLIT: | |
171 | case T_PP_NUMBER: | |
172 | return true; | |
b32b8144 FG |
173 | |
174 | default: | |
175 | break; | |
7c673cae FG |
176 | } |
177 | return false; | |
178 | } | |
179 | // T_DOT | |
b32b8144 | 180 | inline bool |
7c673cae FG |
181 | handle_dot(boost::wave::token_id prev, boost::wave::token_id before) |
182 | { | |
183 | using namespace boost::wave; | |
b32b8144 | 184 | switch (prev) { |
7c673cae FG |
185 | case T_DOT: |
186 | if (T_DOT == before) | |
187 | return true; // ... | |
188 | break; | |
b32b8144 FG |
189 | |
190 | default: | |
191 | break; | |
7c673cae FG |
192 | } |
193 | return false; | |
194 | } | |
195 | // T_QUESTION_MARK | |
b32b8144 FG |
196 | inline bool |
197 | handle_questionmark(boost::wave::token_id prev, | |
7c673cae FG |
198 | boost::wave::token_id /*before*/) |
199 | { | |
200 | using namespace boost::wave; | |
b32b8144 FG |
201 | switch(prev) { |
202 | case T_UNKNOWN_UNIVERSALCHAR: // \? | |
7c673cae FG |
203 | case T_QUESTION_MARK: // ?? |
204 | return true; | |
b32b8144 FG |
205 | |
206 | default: | |
207 | break; | |
7c673cae FG |
208 | } |
209 | return false; | |
210 | } | |
211 | // T_NEWLINE | |
212 | inline bool | |
b32b8144 | 213 | handle_newline(boost::wave::token_id prev, |
7c673cae FG |
214 | boost::wave::token_id before) |
215 | { | |
216 | using namespace boost::wave; | |
b32b8144 | 217 | switch(prev) { |
7c673cae FG |
218 | case TOKEN_FROM_ID('\\', UnknownTokenType): // \ \n |
219 | case T_DIVIDE: | |
220 | if (T_QUESTION_MARK == before) | |
221 | return true; // ?/\n // may be \\n | |
222 | break; | |
b32b8144 FG |
223 | |
224 | default: | |
225 | break; | |
7c673cae FG |
226 | } |
227 | return false; | |
228 | } | |
229 | ||
b32b8144 | 230 | inline bool |
7c673cae FG |
231 | handle_parens(boost::wave::token_id prev) |
232 | { | |
b32b8144 | 233 | switch (prev) { |
7c673cae FG |
234 | case T_LEFTPAREN: |
235 | case T_RIGHTPAREN: | |
236 | case T_LEFTBRACKET: | |
237 | case T_RIGHTBRACKET: | |
238 | case T_LEFTBRACE: | |
239 | case T_RIGHTBRACE: | |
240 | case T_SEMICOLON: | |
241 | case T_COMMA: | |
242 | case T_COLON: | |
243 | // no insertion between parens/brackets/braces and operators | |
b32b8144 | 244 | return false; |
7c673cae FG |
245 | |
246 | default: | |
247 | break; | |
248 | } | |
249 | return true; | |
250 | } | |
b32b8144 | 251 | |
7c673cae FG |
252 | } // namespace impl |
253 | ||
b32b8144 | 254 | class insert_whitespace_detection |
7c673cae FG |
255 | { |
256 | public: | |
b32b8144 | 257 | insert_whitespace_detection(bool insert_whitespace_ = true) |
7c673cae | 258 | : insert_whitespace(insert_whitespace_), |
b32b8144 | 259 | prev(boost::wave::T_EOF), beforeprev(boost::wave::T_EOF) |
7c673cae | 260 | {} |
b32b8144 | 261 | |
7c673cae FG |
262 | template <typename StringT> |
263 | bool must_insert(boost::wave::token_id current, StringT const &value) | |
264 | { | |
265 | if (!insert_whitespace) | |
266 | return false; // skip whitespace insertion alltogether | |
b32b8144 | 267 | |
7c673cae | 268 | using namespace boost::wave; |
b32b8144 | 269 | switch (current) { |
7c673cae | 270 | case T_NONREPLACABLE_IDENTIFIER: |
b32b8144 FG |
271 | case T_IDENTIFIER: |
272 | return impl::handle_identifier(prev, beforeprev, value); | |
7c673cae FG |
273 | case T_PP_NUMBER: |
274 | case T_INTLIT: | |
b32b8144 | 275 | return impl::handle_intlit(prev, beforeprev); |
7c673cae | 276 | case T_FLOATLIT: |
b32b8144 | 277 | return impl::handle_floatlit(prev, beforeprev); |
7c673cae FG |
278 | case T_STRINGLIT: |
279 | if (TOKEN_FROM_ID('L', IdentifierTokenType) == prev) // 'L' | |
280 | return true; | |
281 | break; | |
282 | case T_LEFTBRACE_ALT: | |
b32b8144 | 283 | return impl::handle_alt_leftbrace(prev, beforeprev); |
7c673cae | 284 | case T_LEFTBRACKET_ALT: |
b32b8144 | 285 | return impl::handle_alt_leftbracket(prev, beforeprev); |
7c673cae | 286 | case T_FIXEDPOINTLIT: |
b32b8144 | 287 | return impl::handle_fixedpointlit(prev, beforeprev); |
7c673cae | 288 | case T_DOT: |
b32b8144 | 289 | return impl::handle_dot(prev, beforeprev); |
7c673cae | 290 | case T_QUESTION_MARK: |
b32b8144 | 291 | return impl::handle_questionmark(prev, beforeprev); |
7c673cae | 292 | case T_NEWLINE: |
b32b8144 | 293 | return impl::handle_newline(prev, beforeprev); |
7c673cae FG |
294 | |
295 | case T_LEFTPAREN: | |
296 | case T_RIGHTPAREN: | |
297 | case T_LEFTBRACKET: | |
298 | case T_RIGHTBRACKET: | |
299 | case T_SEMICOLON: | |
300 | case T_COMMA: | |
301 | case T_COLON: | |
b32b8144 | 302 | switch (prev) { |
7c673cae FG |
303 | case T_LEFTPAREN: |
304 | case T_RIGHTPAREN: | |
305 | case T_LEFTBRACKET: | |
306 | case T_RIGHTBRACKET: | |
307 | case T_LEFTBRACE: | |
308 | case T_RIGHTBRACE: | |
309 | return false; // no insertion between parens/brackets/braces | |
310 | ||
311 | default: | |
312 | if (IS_CATEGORY(prev, OperatorTokenType)) | |
313 | return false; | |
314 | break; | |
b32b8144 | 315 | } |
7c673cae | 316 | break; |
b32b8144 | 317 | |
7c673cae FG |
318 | case T_LEFTBRACE: |
319 | case T_RIGHTBRACE: | |
b32b8144 | 320 | switch (prev) { |
7c673cae FG |
321 | case T_LEFTPAREN: |
322 | case T_RIGHTPAREN: | |
323 | case T_LEFTBRACKET: | |
324 | case T_RIGHTBRACKET: | |
325 | case T_LEFTBRACE: | |
326 | case T_RIGHTBRACE: | |
327 | case T_SEMICOLON: | |
328 | case T_COMMA: | |
329 | case T_COLON: | |
330 | return false; // no insertion between parens/brackets/braces | |
331 | ||
332 | case T_QUESTION_MARK: | |
333 | if (T_QUESTION_MARK == beforeprev) | |
334 | return true; | |
335 | if (IS_CATEGORY(prev, OperatorTokenType)) | |
336 | return false; | |
337 | break; | |
b32b8144 | 338 | |
7c673cae FG |
339 | default: |
340 | break; | |
341 | } | |
342 | break; | |
b32b8144 | 343 | |
7c673cae FG |
344 | case T_MINUS: |
345 | case T_MINUSMINUS: | |
346 | case T_MINUSASSIGN: | |
347 | if (T_MINUS == prev || T_MINUSMINUS == prev) | |
348 | return true; | |
349 | if (!impl::handle_parens(prev)) | |
350 | return false; | |
351 | if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) | |
352 | return true; | |
353 | break; | |
b32b8144 | 354 | |
7c673cae FG |
355 | case T_PLUS: |
356 | case T_PLUSPLUS: | |
357 | case T_PLUSASSIGN: | |
358 | if (T_PLUS == prev || T_PLUSPLUS == prev) | |
359 | return true; | |
360 | if (!impl::handle_parens(prev)) | |
361 | return false; | |
362 | if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) | |
363 | return true; | |
364 | break; | |
b32b8144 | 365 | |
7c673cae FG |
366 | case T_DIVIDE: |
367 | case T_DIVIDEASSIGN: | |
368 | if (T_DIVIDE == prev) | |
369 | return true; | |
370 | if (!impl::handle_parens(prev)) | |
371 | return false; | |
372 | if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) | |
373 | return true; | |
374 | break; | |
b32b8144 | 375 | |
7c673cae FG |
376 | case T_EQUAL: |
377 | case T_ASSIGN: | |
b32b8144 | 378 | switch (prev) { |
7c673cae FG |
379 | case T_PLUSASSIGN: |
380 | case T_MINUSASSIGN: | |
381 | case T_DIVIDEASSIGN: | |
382 | case T_STARASSIGN: | |
383 | case T_SHIFTRIGHTASSIGN: | |
384 | case T_SHIFTLEFTASSIGN: | |
385 | case T_EQUAL: | |
386 | case T_NOTEQUAL: | |
387 | case T_LESSEQUAL: | |
388 | case T_GREATEREQUAL: | |
389 | case T_LESS: | |
390 | case T_GREATER: | |
391 | case T_PLUS: | |
392 | case T_MINUS: | |
393 | case T_STAR: | |
394 | case T_DIVIDE: | |
395 | case T_ORASSIGN: | |
396 | case T_ANDASSIGN: | |
397 | case T_XORASSIGN: | |
398 | case T_OR: | |
399 | case T_AND: | |
400 | case T_XOR: | |
401 | case T_OROR: | |
402 | case T_ANDAND: | |
403 | return true; | |
404 | ||
405 | case T_QUESTION_MARK: | |
406 | if (T_QUESTION_MARK == beforeprev) | |
407 | return true; | |
408 | break; | |
b32b8144 | 409 | |
7c673cae FG |
410 | default: |
411 | if (!impl::handle_parens(prev)) | |
412 | return false; | |
413 | break; | |
414 | } | |
415 | break; | |
416 | ||
417 | case T_GREATER: | |
418 | if (T_MINUS == prev || T_GREATER == prev) | |
419 | return true; // prevent -> or >> | |
420 | if (!impl::handle_parens(prev)) | |
421 | return false; | |
422 | if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) | |
423 | return true; | |
424 | break; | |
425 | ||
426 | case T_LESS: | |
427 | if (T_LESS == prev) | |
428 | return true; // prevent << | |
429 | // fall through | |
430 | case T_CHARLIT: | |
431 | case T_NOT: | |
432 | case T_NOTEQUAL: | |
433 | if (!impl::handle_parens(prev)) | |
434 | return false; | |
435 | if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) | |
436 | return true; | |
437 | break; | |
438 | ||
439 | case T_AND: | |
440 | case T_ANDAND: | |
441 | if (!impl::handle_parens(prev)) | |
442 | return false; | |
443 | if (T_AND == prev || T_ANDAND == prev) | |
444 | return true; | |
445 | break; | |
b32b8144 | 446 | |
7c673cae FG |
447 | case T_OR: |
448 | if (!impl::handle_parens(prev)) | |
449 | return false; | |
450 | if (T_OR == prev) | |
451 | return true; | |
452 | break; | |
b32b8144 | 453 | |
7c673cae FG |
454 | case T_XOR: |
455 | if (!impl::handle_parens(prev)) | |
456 | return false; | |
457 | if (T_XOR == prev) | |
458 | return true; | |
459 | break; | |
b32b8144 | 460 | |
7c673cae FG |
461 | case T_COMPL_ALT: |
462 | case T_OR_ALT: | |
463 | case T_AND_ALT: | |
464 | case T_NOT_ALT: | |
465 | case T_XOR_ALT: | |
466 | case T_ANDASSIGN_ALT: | |
467 | case T_ORASSIGN_ALT: | |
468 | case T_XORASSIGN_ALT: | |
469 | case T_NOTEQUAL_ALT: | |
b32b8144 | 470 | switch (prev) { |
7c673cae FG |
471 | case T_LEFTPAREN: |
472 | case T_RIGHTPAREN: | |
473 | case T_LEFTBRACKET: | |
474 | case T_RIGHTBRACKET: | |
475 | case T_LEFTBRACE: | |
476 | case T_RIGHTBRACE: | |
477 | case T_SEMICOLON: | |
478 | case T_COMMA: | |
479 | case T_COLON: | |
480 | // no insertion between parens/brackets/braces and operators | |
b32b8144 | 481 | return false; |
7c673cae FG |
482 | |
483 | case T_IDENTIFIER: | |
484 | if (T_NONREPLACABLE_IDENTIFIER == prev || | |
485 | IS_CATEGORY(prev, KeywordTokenType)) | |
486 | { | |
487 | return true; | |
488 | } | |
489 | break; | |
b32b8144 | 490 | |
7c673cae FG |
491 | default: |
492 | break; | |
493 | } | |
494 | break; | |
b32b8144 | 495 | |
7c673cae FG |
496 | case T_STAR: |
497 | if (T_STAR == prev) | |
498 | return false; // '*****' do not need to be separated | |
b32b8144 | 499 | if (T_GREATER== prev && |
7c673cae FG |
500 | (T_MINUS == beforeprev || T_MINUSMINUS == beforeprev) |
501 | ) | |
502 | { | |
503 | return true; // prevent ->* | |
504 | } | |
505 | break; | |
506 | ||
507 | case T_POUND: | |
508 | if (T_POUND == prev) | |
509 | return true; | |
510 | break; | |
b32b8144 FG |
511 | |
512 | default: | |
513 | break; | |
7c673cae FG |
514 | } |
515 | ||
516 | // FIXME: else, handle operators separately (will catch to many cases) | |
b32b8144 | 517 | // if (IS_CATEGORY(current, OperatorTokenType) && |
7c673cae FG |
518 | // IS_CATEGORY(prev, OperatorTokenType)) |
519 | // { | |
520 | // return true; // operators must be delimited always | |
521 | // } | |
522 | return false; | |
523 | } | |
524 | void shift_tokens (boost::wave::token_id next_id) | |
525 | { | |
526 | if (insert_whitespace) { | |
527 | beforeprev = prev; | |
528 | prev = next_id; | |
529 | } | |
530 | } | |
b32b8144 | 531 | |
7c673cae FG |
532 | private: |
533 | bool insert_whitespace; // enable this component | |
534 | boost::wave::token_id prev; // the previous analyzed token | |
535 | boost::wave::token_id beforeprev; // the token before the previous | |
536 | }; | |
537 | ||
538 | /////////////////////////////////////////////////////////////////////////////// | |
539 | } // namespace util | |
b32b8144 | 540 | } // namespace wave |
7c673cae FG |
541 | } // namespace boost |
542 | ||
543 | // the suffix header occurs after all of the code | |
544 | #ifdef BOOST_HAS_ABI_HEADERS | |
545 | #include BOOST_ABI_SUFFIX | |
546 | #endif | |
547 | ||
548 | #endif // !defined(INSERT_WHITESPACE_DETECTION_HPP_765EF77B_0513_4967_BDD6_6A38148C4C96_INCLUDED) |