1 /*============================================================================= 2 Boost.Wave: A Standard compliant C++ preprocessor library 3 4 http://www.boost.org/ 5 6 Copyright (c) 2001-2012 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_CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED) 12 #define BOOST_CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED 13 14 #if defined (BOOST_SPIRIT_DEBUG) 15 #include <iostream> 16 #endif // defined(BOOST_SPIRIT_DEBUG) 17 18 #include <boost/wave/wave_config.hpp> 19 #include <boost/wave/grammars/cpp_value_error.hpp> // value_error 20 21 // this must occur after all of the includes and before any code appears 22 #ifdef BOOST_HAS_ABI_HEADERS 23 #include BOOST_ABI_PREFIX 24 #endif 25 26 /////////////////////////////////////////////////////////////////////////////// 27 namespace boost { 28 namespace wave { 29 namespace grammars { 30 namespace closures { 31 32 class closure_value; 33 inline bool as_bool(closure_value const& v); 34 35 /////////////////////////////////////////////////////////////////////////////// 36 // 37 // The closure_value class represents the closure type, which is used for the 38 // expression grammar. 39 // 40 // This class was introduced to allow the expression grammar to respect 41 // the numeric type of a numeric literal or expression result. 42 // 43 /////////////////////////////////////////////////////////////////////////////// 44 class closure_value { 45 public: 46 47 enum value_type { 48 is_int = 1, 49 is_uint = 2, 50 is_bool = 3 51 }; 52 closure_value(value_error valid_=error_noerror)53 closure_value(value_error valid_ = error_noerror) 54 : type(is_int), valid(valid_) 55 { value.i = 0; } closure_value(int i,value_error valid_=error_noerror)56 explicit closure_value(int i, value_error valid_ = error_noerror) 57 : type(is_int), valid(valid_) 58 { value.i = i; } closure_value(unsigned int ui,value_error valid_=error_noerror)59 explicit closure_value(unsigned int ui, value_error valid_ = error_noerror) 60 : type(is_uint), valid(valid_) 61 { value.ui = ui; } closure_value(int_literal_type i,value_error valid_=error_noerror)62 explicit closure_value(int_literal_type i, value_error valid_ = error_noerror) 63 : type(is_int), valid(valid_) 64 { value.i = i; } closure_value(uint_literal_type ui,value_error valid_=error_noerror)65 explicit closure_value(uint_literal_type ui, value_error valid_ = error_noerror) 66 : type(is_uint), valid(valid_) 67 { value.ui = ui; } closure_value(bool b,value_error valid_=error_noerror)68 explicit closure_value(bool b, value_error valid_ = error_noerror) 69 : type(is_bool), valid(valid_) 70 { value.b = b; } 71 get_type() const72 value_type get_type() const { return type; } is_valid() const73 value_error is_valid() const { return valid; } 74 75 // explicit conversion as_int(closure_value const & v)76 friend int_literal_type as_int(closure_value const& v) 77 { 78 switch (v.type) { 79 case is_uint: return v.value.ui; 80 case is_bool: return v.value.b ? 1 : 0; 81 case is_int: break; 82 } 83 return v.value.i; 84 } as_uint(closure_value const & v)85 friend uint_literal_type as_uint(closure_value const& v) 86 { 87 switch (v.type) { 88 case is_uint: return v.value.ui; 89 case is_bool: return v.value.b ? 1 : 0; 90 case is_int: break; 91 } 92 return v.value.i; 93 } as_long(closure_value const & v)94 friend int_literal_type as_long(closure_value const& v) 95 { 96 switch (v.type) { 97 case is_uint: return v.value.ui; 98 case is_bool: return v.value.b ? 1 : 0; 99 case is_int: break; 100 } 101 return v.value.i; 102 } as_ulong(closure_value const & v)103 friend uint_literal_type as_ulong(closure_value const& v) 104 { 105 switch (v.type) { 106 case is_uint: return v.value.ui; 107 case is_bool: return v.value.b ? 1 : 0; 108 case is_int: break; 109 } 110 return v.value.i; 111 } as_bool(closure_value const & v)112 friend bool as_bool(closure_value const& v) 113 { 114 switch (v.type) { 115 case is_uint: return v.value.ui != 0; 116 case is_bool: return v.value.b; 117 case is_int: break; 118 } 119 return v.value.i != 0.0; 120 } 121 122 // assignment operator =(closure_value const & rhs)123 closure_value &operator= (closure_value const &rhs) 124 { 125 switch (rhs.get_type()) { 126 case is_int: 127 value.i = as_long(rhs); 128 type = is_int; 129 break; 130 131 case is_uint: 132 value.ui = as_ulong(rhs); 133 type = is_uint; 134 break; 135 136 case is_bool: 137 value.b = as_bool(rhs); 138 type = is_bool; 139 break; 140 } 141 valid = rhs.valid; 142 return *this; 143 } operator =(int rhs)144 closure_value &operator= (int rhs) 145 { 146 type = is_int; 147 value.i = rhs; 148 valid = error_noerror; 149 return *this; 150 } operator =(unsigned int rhs)151 closure_value &operator= (unsigned int rhs) 152 { 153 type = is_uint; 154 value.ui = rhs; 155 valid = error_noerror; 156 return *this; 157 } operator =(int_literal_type rhs)158 closure_value &operator= (int_literal_type rhs) 159 { 160 type = is_int; 161 value.i = rhs; 162 valid = error_noerror; 163 return *this; 164 } operator =(uint_literal_type rhs)165 closure_value &operator= (uint_literal_type rhs) 166 { 167 type = is_uint; 168 value.ui = rhs; 169 valid = error_noerror; 170 return *this; 171 } operator =(bool rhs)172 closure_value &operator= (bool rhs) 173 { 174 type = is_bool; 175 value.b = rhs; 176 valid = error_noerror; 177 return *this; 178 } 179 180 // arithmetics operator +=(closure_value const & rhs)181 closure_value &operator+= (closure_value const &rhs) 182 { 183 switch (type) { 184 case is_int: 185 switch(rhs.type) { 186 case is_bool: 187 { 188 int_literal_type result = value.i + as_long(rhs); 189 if ((rhs.value.i > 0L && value.i > result) || 190 (rhs.value.i < 0L && value.i < result)) 191 { 192 valid = error_integer_overflow; 193 } 194 else { 195 value.i = result; 196 } 197 } 198 break; 199 200 case is_int: 201 { 202 int_literal_type result = value.i + rhs.value.i; 203 if ((rhs.value.i > 0L && value.i > result) || 204 (rhs.value.i < 0L && value.i < result)) 205 { 206 valid = error_integer_overflow; 207 } 208 else { 209 value.i = result; 210 } 211 } 212 break; 213 214 case is_uint: 215 { 216 uint_literal_type result = value.ui + rhs.value.ui; 217 if (result < value.ui) { 218 valid = error_integer_overflow; 219 } 220 else { 221 value.ui = result; 222 type = is_uint; 223 } 224 } 225 break; 226 } 227 break; 228 229 case is_uint: 230 { 231 uint_literal_type result = value.ui + as_ulong(rhs); 232 if (result < value.ui) { 233 valid = error_integer_overflow; 234 } 235 else { 236 value.ui = result; 237 } 238 } 239 break; 240 241 case is_bool: 242 value.i = value.b + as_bool(rhs); 243 type = is_int; 244 } 245 valid = (value_error)(valid | rhs.valid); 246 return *this; 247 } operator -=(closure_value const & rhs)248 closure_value &operator-= (closure_value const &rhs) 249 { 250 switch (type) { 251 case is_int: 252 switch(rhs.type) { 253 case is_bool: 254 { 255 int_literal_type result = value.i - as_long(rhs); 256 if ((rhs.value.i > 0L && result > value.i) || 257 (rhs.value.i < 0L && result < value.i)) 258 { 259 valid = error_integer_overflow; 260 } 261 else { 262 value.i = result; 263 } 264 } 265 break; 266 267 case is_int: 268 { 269 int_literal_type result = value.i - rhs.value.i; 270 if ((rhs.value.i > 0L && result > value.i) || 271 (rhs.value.i < 0L && result < value.i)) 272 { 273 valid = error_integer_overflow; 274 } 275 else { 276 value.i = result; 277 } 278 } 279 break; 280 281 case is_uint: 282 { 283 uint_literal_type result = value.ui - rhs.value.ui; 284 if (result > value.ui) { 285 valid = error_integer_overflow; 286 } 287 else { 288 value.ui = result; 289 type = is_uint; 290 } 291 } 292 break; 293 } 294 break; 295 296 case is_uint: 297 switch(rhs.type) { 298 case is_bool: 299 { 300 uint_literal_type result = value.ui - as_ulong(rhs); 301 if (result > value.ui) 302 { 303 valid = error_integer_overflow; 304 } 305 else { 306 value.ui = result; 307 } 308 } 309 break; 310 311 case is_int: 312 { 313 uint_literal_type result = value.ui - rhs.value.i; 314 if ((rhs.value.i > 0L && result > value.ui) || 315 (rhs.value.i < 0L && result < value.ui)) 316 { 317 valid = error_integer_overflow; 318 } 319 else { 320 value.ui = result; 321 } 322 } 323 break; 324 325 case is_uint: 326 { 327 uint_literal_type result = value.ui - rhs.value.ui; 328 if (result > value.ui) { 329 valid = error_integer_overflow; 330 } 331 else { 332 value.ui = result; 333 } 334 } 335 break; 336 } 337 break; 338 339 case is_bool: 340 value.i = value.b - as_bool(rhs); 341 type = is_int; 342 } 343 valid = (value_error)(valid | rhs.valid); 344 return *this; 345 } operator *=(closure_value const & rhs)346 closure_value &operator*= (closure_value const &rhs) 347 { 348 switch (type) { 349 case is_int: 350 switch(rhs.type) { 351 case is_bool: value.i *= as_long(rhs); break; 352 case is_int: 353 { 354 int_literal_type result = value.i * rhs.value.i; 355 if (0 != value.i && 0 != rhs.value.i && 356 (result / value.i != rhs.value.i || 357 result / rhs.value.i != value.i) 358 ) 359 { 360 valid = error_integer_overflow; 361 } 362 else { 363 value.i = result; 364 } 365 } 366 break; 367 368 case is_uint: 369 { 370 uint_literal_type result = value.ui * rhs.value.ui; 371 if (0 != value.ui && 0 != rhs.value.ui && 372 (result / value.ui != rhs.value.ui || 373 result / rhs.value.ui != value.ui) 374 ) 375 { 376 valid = error_integer_overflow; 377 } 378 else { 379 value.ui = result; 380 type = is_uint; 381 } 382 } 383 break; 384 } 385 break; 386 387 case is_uint: 388 { 389 uint_literal_type rhs_val = as_ulong(rhs); 390 uint_literal_type result = value.ui * rhs_val; 391 if (0 != value.ui && 0 != rhs_val && 392 (result / value.ui != rhs_val || 393 result / rhs_val != value.ui) 394 ) 395 { 396 valid = error_integer_overflow; 397 } 398 else { 399 value.ui = result; 400 type = is_uint; 401 } 402 } 403 break; 404 405 case is_bool: 406 switch (rhs.type) { 407 case is_int: 408 value.i = (value.b ? 1 : 0) * rhs.value.i; 409 type = is_int; 410 break; 411 412 case is_uint: 413 value.ui = (value.b ? 1 : 0) * rhs.value.ui; 414 type = is_uint; 415 break; 416 417 case is_bool: 418 value.b = 0 != ((value.b ? 1 : 0) * (rhs.value.b ? 1 : 0)); 419 break; 420 } 421 } 422 valid = (value_error)(valid | rhs.valid); 423 return *this; 424 } operator /=(closure_value const & rhs)425 closure_value &operator/= (closure_value const &rhs) 426 { 427 switch (type) { 428 case is_int: 429 switch(rhs.type) { 430 case is_bool: 431 case is_int: 432 if (as_long(rhs) != 0) { 433 if (value.i == -value.i && -1 == rhs.value.i) { 434 // LONG_MIN / -1 on two's complement 435 valid = error_integer_overflow; 436 } 437 else { 438 value.i /= as_long(rhs); 439 } 440 } 441 else { 442 valid = error_division_by_zero; // division by zero 443 } 444 break; 445 446 case is_uint: 447 if (rhs.value.ui != 0) { 448 value.ui /= rhs.value.ui; 449 type = is_uint; 450 } 451 else { 452 valid = error_division_by_zero; // division by zero 453 } 454 break; 455 } 456 break; 457 458 case is_uint: 459 if (as_ulong(rhs) != 0) 460 value.ui /= as_ulong(rhs); 461 else 462 valid = error_division_by_zero; // division by zero 463 break; 464 465 case is_bool: 466 if (as_bool(rhs)) { 467 switch(rhs.type) { 468 case is_int: 469 value.i = (value.b ? 1 : 0) / rhs.value.i; 470 type = is_int; 471 break; 472 473 case is_uint: 474 value.i = (value.b ? 1 : 0) / rhs.value.ui; 475 type = is_int; 476 break; 477 478 case is_bool: 479 break; 480 } 481 } 482 else { 483 valid = error_division_by_zero; // division by zero 484 } 485 } 486 return *this; 487 } operator %=(closure_value const & rhs)488 closure_value &operator%= (closure_value const &rhs) 489 { 490 switch (type) { 491 case is_int: 492 switch(rhs.type) { 493 case is_bool: 494 case is_int: 495 if (as_long(rhs) != 0) { 496 if (value.i == -value.i && -1 == rhs.value.i) { 497 // LONG_MIN % -1 on two's complement 498 valid = error_integer_overflow; 499 } 500 else { 501 value.i %= as_long(rhs); 502 } 503 } 504 else { 505 valid = error_division_by_zero; // division by zero 506 } 507 break; 508 509 case is_uint: 510 if (rhs.value.ui != 0) { 511 value.ui %= rhs.value.ui; 512 type = is_uint; 513 } 514 else { 515 valid = error_division_by_zero; // division by zero 516 } 517 break; 518 } 519 break; 520 521 case is_uint: 522 if (as_ulong(rhs) != 0) 523 value.ui %= as_ulong(rhs); 524 else 525 valid = error_division_by_zero; // division by zero 526 break; 527 528 case is_bool: 529 if (as_bool(rhs)) { 530 switch(rhs.type) { 531 case is_int: 532 value.i = (value.b ? 1 : 0) % rhs.value.i; 533 type = is_int; 534 break; 535 536 case is_uint: 537 value.i = (value.b ? 1 : 0) % rhs.value.ui; 538 type = is_int; 539 break; 540 541 case is_bool: 542 break; 543 } 544 } 545 else { 546 valid = error_division_by_zero; // division by zero 547 } 548 } 549 return *this; 550 } 551 552 friend closure_value operator -(closure_value const & rhs)553 operator- (closure_value const &rhs) 554 { 555 switch (rhs.type) { 556 case is_int: 557 { 558 int_literal_type value = as_long(rhs); 559 if (value != 0 && value == -value) 560 return closure_value(-value, error_integer_overflow); 561 return closure_value(-value, rhs.valid); 562 } 563 564 case is_bool: return closure_value(-as_long(rhs), rhs.valid); 565 case is_uint: break; 566 } 567 568 int_literal_type value = as_ulong(rhs); 569 if (value != 0 && value == -value) 570 return closure_value(-value, error_integer_overflow); 571 return closure_value(-value, rhs.valid); 572 } 573 friend closure_value operator ~(closure_value const & rhs)574 operator~ (closure_value const &rhs) 575 { 576 return closure_value(~as_ulong(rhs), rhs.valid); 577 } 578 friend closure_value operator !(closure_value const & rhs)579 operator! (closure_value const &rhs) 580 { 581 switch (rhs.type) { 582 case is_int: return closure_value(!as_long(rhs), rhs.valid); 583 case is_bool: return closure_value(!as_bool(rhs), rhs.valid); 584 case is_uint: break; 585 } 586 return closure_value(!as_ulong(rhs), rhs.valid); 587 } 588 589 // comparison 590 friend closure_value operator ==(closure_value const & lhs,closure_value const & rhs)591 operator== (closure_value const &lhs, closure_value const &rhs) 592 { 593 bool cmp = false; 594 switch (lhs.type) { 595 case is_int: 596 switch(rhs.type) { 597 case is_bool: cmp = as_bool(lhs) == rhs.value.b; break; 598 case is_int: cmp = lhs.value.i == rhs.value.i; break; 599 case is_uint: cmp = lhs.value.ui == rhs.value.ui; break; 600 } 601 break; 602 603 case is_uint: cmp = lhs.value.ui == as_ulong(rhs); break; 604 case is_bool: cmp = lhs.value.b == as_bool(rhs); break; 605 } 606 return closure_value(cmp, (value_error)(lhs.valid | rhs.valid)); 607 } 608 friend closure_value operator !=(closure_value const & lhs,closure_value const & rhs)609 operator!= (closure_value const &lhs, closure_value const &rhs) 610 { 611 return closure_value(!as_bool(lhs == rhs), (value_error)(lhs.valid | rhs.valid)); 612 } 613 friend closure_value operator >(closure_value const & lhs,closure_value const & rhs)614 operator> (closure_value const &lhs, closure_value const &rhs) 615 { 616 bool cmp = false; 617 switch (lhs.type) { 618 case is_int: 619 switch(rhs.type) { 620 case is_bool: cmp = lhs.value.i > as_long(rhs); break; 621 case is_int: cmp = lhs.value.i > rhs.value.i; break; 622 case is_uint: cmp = lhs.value.ui > rhs.value.ui; break; 623 } 624 break; 625 626 case is_uint: cmp = lhs.value.ui > as_ulong(rhs); break; 627 case is_bool: cmp = lhs.value.b > as_bool(rhs); break; 628 } 629 return closure_value(cmp, (value_error)(lhs.valid | rhs.valid)); 630 } 631 friend closure_value operator <(closure_value const & lhs,closure_value const & rhs)632 operator< (closure_value const &lhs, closure_value const &rhs) 633 { 634 bool cmp = false; 635 switch (lhs.type) { 636 case is_int: 637 switch(rhs.type) { 638 case is_bool: cmp = lhs.value.i < as_long(rhs); break; 639 case is_int: cmp = lhs.value.i < rhs.value.i; break; 640 case is_uint: cmp = lhs.value.ui < rhs.value.ui; break; 641 } 642 break; 643 644 case is_uint: cmp = lhs.value.ui < as_ulong(rhs); break; 645 case is_bool: cmp = as_bool(lhs) < as_bool(rhs); break; 646 } 647 return closure_value(cmp, (value_error)(lhs.valid | rhs.valid)); 648 } 649 friend closure_value operator <=(closure_value const & lhs,closure_value const & rhs)650 operator<= (closure_value const &lhs, closure_value const &rhs) 651 { 652 return closure_value(!as_bool(lhs > rhs), (value_error)(lhs.valid | rhs.valid)); 653 } 654 friend closure_value operator >=(closure_value const & lhs,closure_value const & rhs)655 operator>= (closure_value const &lhs, closure_value const &rhs) 656 { 657 return closure_value(!as_bool(lhs < rhs), (value_error)(lhs.valid | rhs.valid)); 658 } 659 660 closure_value & operator <<=(closure_value const & rhs)661 operator<<= (closure_value const &rhs) 662 { 663 switch (type) { 664 case is_bool: 665 case is_int: 666 switch (rhs.type) { 667 case is_bool: 668 case is_int: 669 { 670 int_literal_type shift_by = as_long(rhs); 671 672 if (shift_by > 64) 673 shift_by = 64; 674 else if (shift_by < -64) 675 shift_by = -64; 676 value.i <<= shift_by; 677 } 678 break; 679 680 case is_uint: 681 { 682 uint_literal_type shift_by = as_ulong(rhs); 683 684 if (shift_by > 64) 685 shift_by = 64; 686 value.ui <<= shift_by; 687 688 // Note: The usual arithmetic conversions are not performed on 689 // bit shift operations. 690 } 691 break; 692 } 693 break; 694 695 case is_uint: 696 switch (rhs.type) { 697 case is_bool: 698 case is_int: 699 { 700 int_literal_type shift_by = as_long(rhs); 701 702 if (shift_by > 64) 703 shift_by = 64; 704 else if (shift_by < -64) 705 shift_by = -64; 706 value.ui <<= shift_by; 707 } 708 break; 709 710 case is_uint: 711 { 712 uint_literal_type shift_by = as_ulong(rhs); 713 714 if (shift_by > 64) 715 shift_by = 64; 716 value.ui <<= shift_by; 717 } 718 break; 719 } 720 } 721 valid = (value_error)(valid | rhs.valid); 722 return *this; 723 } 724 725 closure_value & operator >>=(closure_value const & rhs)726 operator>>= (closure_value const &rhs) 727 { 728 switch (type) { 729 case is_bool: 730 case is_int: 731 switch (rhs.type) { 732 case is_bool: 733 case is_int: 734 { 735 int_literal_type shift_by = as_long(rhs); 736 737 if (shift_by > 64) 738 shift_by = 64; 739 else if (shift_by < -64) 740 shift_by = -64; 741 value.i >>= shift_by; 742 } 743 break; 744 745 case is_uint: 746 { 747 uint_literal_type shift_by = as_ulong(rhs); 748 749 if (shift_by > 64) 750 shift_by = 64; 751 value.ui >>= shift_by; 752 753 // Note: The usual arithmetic conversions are not performed on 754 // bit shift operations. 755 } 756 break; 757 } 758 break; 759 760 case is_uint: 761 switch (rhs.type) { 762 case is_bool: 763 case is_int: 764 { 765 int_literal_type shift_by = as_long(rhs); 766 767 if (shift_by > 64) 768 shift_by = 64; 769 else if (shift_by < -64) 770 shift_by = -64; 771 value.ui >>= shift_by; 772 } 773 break; 774 775 case is_uint: 776 { 777 uint_literal_type shift_by = as_ulong(rhs); 778 779 if (shift_by > 64) 780 shift_by = 64; 781 value.ui >>= shift_by; 782 } 783 break; 784 } 785 break; 786 } 787 valid = (value_error)(valid | rhs.valid); 788 return *this; 789 } 790 791 friend closure_value operator ||(closure_value const & lhs,closure_value const & rhs)792 operator|| (closure_value const &lhs, closure_value const &rhs) 793 { 794 bool result = as_bool(lhs) || as_bool(rhs); 795 return closure_value(result, (value_error)(lhs.valid | rhs.valid)); 796 } 797 798 friend closure_value operator &&(closure_value const & lhs,closure_value const & rhs)799 operator&& (closure_value const &lhs, closure_value const &rhs) 800 { 801 bool result = as_bool(lhs) && as_bool(rhs); 802 return closure_value(result, (value_error)(lhs.valid | rhs.valid)); 803 } 804 805 friend closure_value operator |(closure_value const & lhs,closure_value const & rhs)806 operator| (closure_value const &lhs, closure_value const &rhs) 807 { 808 uint_literal_type result = as_ulong(lhs) | as_ulong(rhs); 809 return closure_value(result, (value_error)(lhs.valid | rhs.valid)); 810 } 811 812 friend closure_value operator &(closure_value const & lhs,closure_value const & rhs)813 operator& (closure_value const &lhs, closure_value const &rhs) 814 { 815 uint_literal_type result = as_ulong(lhs) & as_ulong(rhs); 816 return closure_value(result, (value_error)(lhs.valid | rhs.valid)); 817 } 818 819 friend closure_value operator ^(closure_value const & lhs,closure_value const & rhs)820 operator^ (closure_value const &lhs, closure_value const &rhs) 821 { 822 uint_literal_type result = as_ulong(lhs) ^ as_ulong(rhs); 823 return closure_value(result, (value_error)(lhs.valid | rhs.valid)); 824 } 825 826 // handle the ?: operator 827 closure_value & handle_questionmark(closure_value const & cond,closure_value const & val2)828 handle_questionmark(closure_value const &cond, closure_value const &val2) 829 { 830 switch (type) { 831 case is_int: 832 switch (val2.type) { 833 case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break; 834 case is_int: value.i = as_bool(cond) ? value.i : as_long(val2); break; 835 case is_uint: 836 value.ui = as_bool(cond) ? value.ui : as_ulong(val2); 837 type = is_uint; // changing type! 838 break; 839 } 840 break; 841 842 case is_uint: value.ui = as_bool(cond) ? value.ui : as_ulong(val2); break; 843 case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break; 844 } 845 valid = as_bool(cond) ? valid : val2.valid; 846 return *this; 847 } 848 849 #if defined (BOOST_SPIRIT_DEBUG) 850 friend std::ostream& operator <<(std::ostream & o,closure_value const & val)851 operator<< (std::ostream &o, closure_value const &val) 852 { 853 switch (val.type) { 854 case is_int: o << "int(" << as_long(val) << ")"; break; 855 case is_uint: o << "unsigned int(" << as_ulong(val) << ")"; break; 856 case is_bool: o << "bool(" << as_bool(val) << ")"; break; 857 } 858 return o; 859 } 860 #endif // defined(BOOST_SPIRIT_DEBUG) 861 862 private: 863 value_type type; 864 union { 865 int_literal_type i; 866 uint_literal_type ui; 867 bool b; 868 } value; 869 value_error valid; 870 }; 871 872 /////////////////////////////////////////////////////////////////////////////// 873 } // namespace closures 874 } // namespace grammars 875 } // namespace wave 876 } // namespace boost 877 878 // the suffix header occurs after all of the code 879 #ifdef BOOST_HAS_ABI_HEADERS 880 #include BOOST_ABI_SUFFIX 881 #endif 882 883 #endif // !defined(BOOST_CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED) 884