Line data Source code
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-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 : 15 : #include <boost/wave/wave_config.hpp> 16 : #include <boost/wave/token_ids.hpp> 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 0 : would_form_universal_char (StringT const &value) 34 : { 35 0 : if ('u' != value[0] && 'U' != value[0]) 36 : return false; 37 0 : if ('u' == value[0] && value.size() < 5) 38 : return false; 39 0 : if ('U' == value[0] && value.size() < 9) 40 : return false; 41 : 42 0 : typename StringT::size_type pos = 43 : value.find_first_not_of("0123456789abcdefABCDEF", 1); 44 : 45 0 : if (StringT::npos == pos || 46 0 : ('u' == value[0] && pos > 5) || 47 0 : ('U' == value[0] && pos > 9)) 48 : { 49 0 : return true; // would form an universal char 50 : } 51 : return false; 52 : } 53 : template <typename StringT> 54 : inline bool 55 0 : handle_identifier(boost::wave::token_id prev, 56 : boost::wave::token_id before, StringT const &value) 57 : { 58 : using namespace boost::wave; 59 0 : switch (prev) { 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 0 : case T_FLOATLIT: 75 : case T_INTLIT: 76 : case T_PP_NUMBER: 77 0 : return (value.size() > 1 || (value[0] != 'e' && value[0] != 'E')); 78 : 79 : // avoid constructing universal characters (\u1234) 80 0 : case T_UNKNOWN_UNIVERSALCHAR: 81 0 : return would_form_universal_char(value); 82 : 83 : default: 84 : break; 85 : } 86 0 : return false; 87 : } 88 : // T_INTLIT 89 : inline bool 90 0 : handle_intlit(boost::wave::token_id prev, boost::wave::token_id /*before*/) 91 : { 92 0 : using namespace boost::wave; 93 0 : switch (prev) { 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; 101 : 102 0 : default: 103 0 : break; 104 : } 105 0 : return false; 106 : } 107 : // T_FLOATLIT 108 : inline bool 109 0 : handle_floatlit(boost::wave::token_id prev, 110 : boost::wave::token_id /*before*/) 111 : { 112 0 : using namespace boost::wave; 113 0 : switch (prev) { 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; 121 : 122 0 : default: 123 0 : break; 124 : } 125 0 : return false; 126 : } 127 : // <% T_LEFTBRACE 128 : inline bool 129 0 : handle_alt_leftbrace(boost::wave::token_id prev, 130 : boost::wave::token_id /*before*/) 131 : { 132 0 : using namespace boost::wave; 133 0 : switch (prev) { 134 : case T_LESS: // <<% 135 : case T_SHIFTLEFT: // <<<% 136 : return true; 137 : 138 0 : default: 139 0 : break; 140 : } 141 0 : return false; 142 : } 143 : // <: T_LEFTBRACKET 144 : inline bool 145 0 : handle_alt_leftbracket(boost::wave::token_id prev, 146 : boost::wave::token_id /*before*/) 147 : { 148 0 : using namespace boost::wave; 149 0 : switch (prev) { 150 : case T_LESS: // <<: 151 : case T_SHIFTLEFT: // <<<: 152 : return true; 153 : 154 0 : default: 155 0 : break; 156 : } 157 0 : return false; 158 : } 159 : // T_FIXEDPOINTLIT 160 : inline bool 161 0 : handle_fixedpointlit(boost::wave::token_id prev, 162 : boost::wave::token_id /*before*/) 163 : { 164 0 : using namespace boost::wave; 165 0 : switch (prev) { 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; 173 : 174 0 : default: 175 0 : break; 176 : } 177 0 : return false; 178 : } 179 : // T_DOT 180 : inline bool 181 0 : handle_dot(boost::wave::token_id prev, boost::wave::token_id before) 182 : { 183 0 : using namespace boost::wave; 184 0 : switch (prev) { 185 0 : case T_DOT: 186 0 : if (T_DOT == before) 187 0 : return true; // ... 188 : break; 189 : 190 : default: 191 : break; 192 : } 193 : return false; 194 : } 195 : // T_QUESTION_MARK 196 : inline bool 197 0 : handle_questionmark(boost::wave::token_id prev, 198 : boost::wave::token_id /*before*/) 199 : { 200 0 : using namespace boost::wave; 201 0 : switch(prev) { 202 : case T_UNKNOWN_UNIVERSALCHAR: // \? 203 : case T_QUESTION_MARK: // ?? 204 : return true; 205 : 206 0 : default: 207 0 : break; 208 : } 209 0 : return false; 210 : } 211 : // T_NEWLINE 212 : inline bool 213 0 : handle_newline(boost::wave::token_id prev, 214 : boost::wave::token_id before) 215 : { 216 0 : using namespace boost::wave; 217 0 : switch(prev) { 218 0 : case TOKEN_FROM_ID('\\', UnknownTokenType): // \ \n 219 0 : case T_DIVIDE: 220 0 : if (T_QUESTION_MARK == before) 221 0 : return true; // ?/\n // may be \\n 222 : break; 223 : 224 : default: 225 : break; 226 : } 227 : return false; 228 : } 229 : 230 : inline bool 231 0 : handle_parens(boost::wave::token_id prev) 232 : { 233 0 : switch (prev) { 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 244 : return false; 245 : 246 0 : default: 247 0 : break; 248 : } 249 0 : return true; 250 : } 251 : 252 : } // namespace impl 253 : 254 : class insert_whitespace_detection 255 : { 256 : public: 257 0 : insert_whitespace_detection(bool insert_whitespace_ = true) 258 0 : : insert_whitespace(insert_whitespace_), 259 0 : prev(boost::wave::T_EOF), beforeprev(boost::wave::T_EOF) 260 : {} 261 : 262 : template <typename StringT> 263 0 : bool must_insert(boost::wave::token_id current, StringT const &value) 264 : { 265 0 : if (!insert_whitespace) 266 : return false; // skip whitespace insertion alltogether 267 : 268 : using namespace boost::wave; 269 0 : switch (current) { 270 0 : case T_NONREPLACABLE_IDENTIFIER: 271 : case T_IDENTIFIER: 272 0 : return impl::handle_identifier(prev, beforeprev, value); 273 0 : case T_PP_NUMBER: 274 : case T_INTLIT: 275 0 : return impl::handle_intlit(prev, beforeprev); 276 0 : case T_FLOATLIT: 277 0 : return impl::handle_floatlit(prev, beforeprev); 278 0 : case T_STRINGLIT: 279 0 : if (TOKEN_FROM_ID('L', IdentifierTokenType) == prev) // 'L' 280 0 : return true; 281 : break; 282 0 : case T_LEFTBRACE_ALT: 283 0 : return impl::handle_alt_leftbrace(prev, beforeprev); 284 0 : case T_LEFTBRACKET_ALT: 285 0 : return impl::handle_alt_leftbracket(prev, beforeprev); 286 0 : case T_FIXEDPOINTLIT: 287 0 : return impl::handle_fixedpointlit(prev, beforeprev); 288 0 : case T_DOT: 289 0 : return impl::handle_dot(prev, beforeprev); 290 0 : case T_QUESTION_MARK: 291 0 : return impl::handle_questionmark(prev, beforeprev); 292 0 : case T_NEWLINE: 293 0 : return impl::handle_newline(prev, beforeprev); 294 : 295 0 : 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: 302 0 : switch (prev) { 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 0 : default: 312 0 : if (IS_CATEGORY(prev, OperatorTokenType)) 313 : return false; 314 : break; 315 : } 316 : break; 317 : 318 0 : case T_LEFTBRACE: 319 : case T_RIGHTBRACE: 320 0 : switch (prev) { 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 0 : case T_QUESTION_MARK: 333 0 : if (T_QUESTION_MARK == beforeprev) 334 : return true; 335 0 : if (IS_CATEGORY(prev, OperatorTokenType)) 336 : return false; 337 : break; 338 : 339 : default: 340 : break; 341 : } 342 : break; 343 : 344 0 : case T_MINUS: 345 : case T_MINUSMINUS: 346 : case T_MINUSASSIGN: 347 0 : if (T_MINUS == prev || T_MINUSMINUS == prev) 348 : return true; 349 0 : if (!impl::handle_parens(prev)) 350 : return false; 351 0 : if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) 352 0 : return true; 353 : break; 354 : 355 0 : case T_PLUS: 356 : case T_PLUSPLUS: 357 : case T_PLUSASSIGN: 358 0 : if (T_PLUS == prev || T_PLUSPLUS == prev) 359 : return true; 360 0 : if (!impl::handle_parens(prev)) 361 : return false; 362 0 : if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) 363 0 : return true; 364 : break; 365 : 366 0 : case T_DIVIDE: 367 : case T_DIVIDEASSIGN: 368 0 : if (T_DIVIDE == prev) 369 : return true; 370 0 : if (!impl::handle_parens(prev)) 371 : return false; 372 0 : if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) 373 0 : return true; 374 : break; 375 : 376 0 : case T_EQUAL: 377 : case T_ASSIGN: 378 0 : switch (prev) { 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 0 : case T_QUESTION_MARK: 406 0 : if (T_QUESTION_MARK == beforeprev) 407 0 : return true; 408 : break; 409 : 410 0 : default: 411 0 : if (!impl::handle_parens(prev)) 412 : return false; 413 : break; 414 : } 415 : break; 416 : 417 0 : case T_GREATER: 418 0 : if (T_MINUS == prev || T_GREATER == prev) 419 : return true; // prevent -> or >> 420 0 : if (!impl::handle_parens(prev)) 421 : return false; 422 0 : if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) 423 0 : return true; 424 : break; 425 : 426 0 : case T_LESS: 427 0 : if (T_LESS == prev) 428 : return true; // prevent << 429 : // fall through 430 : case T_CHARLIT: 431 : case T_NOT: 432 : case T_NOTEQUAL: 433 0 : if (!impl::handle_parens(prev)) 434 : return false; 435 0 : if (T_QUESTION_MARK == prev && T_QUESTION_MARK == beforeprev) 436 0 : return true; 437 : break; 438 : 439 0 : case T_AND: 440 : case T_ANDAND: 441 0 : if (!impl::handle_parens(prev)) 442 : return false; 443 0 : if (T_AND == prev || T_ANDAND == prev) 444 0 : return true; 445 : break; 446 : 447 0 : case T_OR: 448 0 : if (!impl::handle_parens(prev)) 449 : return false; 450 0 : if (T_OR == prev) 451 0 : return true; 452 : break; 453 : 454 0 : case T_XOR: 455 0 : if (!impl::handle_parens(prev)) 456 : return false; 457 0 : if (T_XOR == prev) 458 0 : return true; 459 : break; 460 : 461 0 : 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: 470 0 : switch (prev) { 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 481 : return false; 482 : 483 0 : case T_IDENTIFIER: 484 0 : if (T_NONREPLACABLE_IDENTIFIER == prev || 485 0 : IS_CATEGORY(prev, KeywordTokenType)) 486 : { 487 0 : return true; 488 : } 489 : break; 490 : 491 : default: 492 : break; 493 : } 494 : break; 495 : 496 0 : case T_STAR: 497 0 : if (T_STAR == prev) 498 : return false; // '*****' do not need to be separated 499 0 : if (T_GREATER== prev && 500 0 : (T_MINUS == beforeprev || T_MINUSMINUS == beforeprev) 501 : ) 502 : { 503 0 : return true; // prevent ->* 504 : } 505 : break; 506 : 507 0 : case T_POUND: 508 0 : if (T_POUND == prev) 509 0 : return true; 510 : break; 511 : 512 : default: 513 : break; 514 : } 515 : 516 : // FIXME: else, handle operators separately (will catch to many cases) 517 : // if (IS_CATEGORY(current, OperatorTokenType) && 518 : // IS_CATEGORY(prev, OperatorTokenType)) 519 : // { 520 : // return true; // operators must be delimited always 521 : // } 522 : return false; 523 : } 524 0 : void shift_tokens (boost::wave::token_id next_id) 525 : { 526 0 : if (insert_whitespace) { 527 0 : beforeprev = prev; 528 0 : prev = next_id; 529 : } 530 : } 531 : 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 540 : } // namespace wave 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)