annotate DEPENDENCIES/generic/include/boost/wave/grammars/cpp_expression_value.hpp @ 133:4acb5d8d80b6 tip

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