Chris@16: /*============================================================================= Chris@16: Boost.Wave: A Standard compliant C++ preprocessor library Chris@16: Chris@16: http://www.boost.org/ Chris@16: Chris@16: Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost Chris@16: Software License, Version 1.0. (See accompanying file Chris@16: LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: =============================================================================*/ Chris@16: Chris@16: #if !defined(CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED) Chris@16: #define CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED Chris@16: Chris@16: #if defined (BOOST_SPIRIT_DEBUG) Chris@16: #include Chris@16: #endif // defined(BOOST_SPIRIT_DEBUG) Chris@16: Chris@16: #include Chris@16: #include // value_error Chris@16: Chris@16: // this must occur after all of the includes and before any code appears Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_PREFIX Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { Chris@16: namespace wave { Chris@16: namespace grammars { Chris@16: namespace closures { Chris@16: Chris@16: class closure_value; Chris@16: inline bool as_bool(closure_value const& v); Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // The closure_value class represents the closure type, which is used for the Chris@16: // expression grammar. Chris@16: // Chris@16: // This class was introduced to allow the expression grammar to respect Chris@16: // the numeric type of a numeric literal or expression result. Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: class closure_value { Chris@16: public: Chris@16: Chris@16: enum value_type { Chris@16: is_int = 1, Chris@16: is_uint = 2, Chris@16: is_bool = 3 Chris@16: }; Chris@16: Chris@16: closure_value(value_error valid_ = error_noerror) Chris@16: : type(is_int), valid(valid_) Chris@16: { value.i = 0; } Chris@16: explicit closure_value(int i, value_error valid_ = error_noerror) Chris@16: : type(is_int), valid(valid_) Chris@16: { value.i = i; } Chris@16: explicit closure_value(unsigned int ui, value_error valid_ = error_noerror) Chris@16: : type(is_uint), valid(valid_) Chris@16: { value.ui = ui; } Chris@16: explicit closure_value(int_literal_type i, value_error valid_ = error_noerror) Chris@16: : type(is_int), valid(valid_) Chris@16: { value.i = i; } Chris@16: explicit closure_value(uint_literal_type ui, value_error valid_ = error_noerror) Chris@16: : type(is_uint), valid(valid_) Chris@16: { value.ui = ui; } Chris@16: explicit closure_value(bool b, value_error valid_ = error_noerror) Chris@16: : type(is_bool), valid(valid_) Chris@16: { value.b = b; } Chris@16: Chris@16: value_type get_type() const { return type; } Chris@16: value_error is_valid() const { return valid; } Chris@16: Chris@16: // explicit conversion Chris@16: friend int_literal_type as_int(closure_value const& v) Chris@16: { Chris@16: switch (v.type) { Chris@16: case is_uint: return v.value.ui; Chris@16: case is_bool: return v.value.b ? 1 : 0; Chris@16: case is_int: break; Chris@16: } Chris@16: return v.value.i; Chris@16: } Chris@16: friend uint_literal_type as_uint(closure_value const& v) Chris@16: { Chris@16: switch (v.type) { Chris@16: case is_uint: return v.value.ui; Chris@16: case is_bool: return v.value.b ? 1 : 0; Chris@16: case is_int: break; Chris@16: } Chris@16: return v.value.i; Chris@16: } Chris@16: friend int_literal_type as_long(closure_value const& v) Chris@16: { Chris@16: switch (v.type) { Chris@16: case is_uint: return v.value.ui; Chris@16: case is_bool: return v.value.b ? 1 : 0; Chris@16: case is_int: break; Chris@16: } Chris@16: return v.value.i; Chris@16: } Chris@16: friend uint_literal_type as_ulong(closure_value const& v) Chris@16: { Chris@16: switch (v.type) { Chris@16: case is_uint: return v.value.ui; Chris@16: case is_bool: return v.value.b ? 1 : 0; Chris@16: case is_int: break; Chris@16: } Chris@16: return v.value.i; Chris@16: } Chris@16: friend bool as_bool(closure_value const& v) Chris@16: { Chris@16: switch (v.type) { Chris@16: case is_uint: return v.value.ui != 0; Chris@16: case is_bool: return v.value.b; Chris@16: case is_int: break; Chris@16: } Chris@16: return v.value.i != 0.0; Chris@16: } Chris@16: Chris@16: // assignment Chris@16: closure_value &operator= (closure_value const &rhs) Chris@16: { Chris@16: switch (rhs.get_type()) { Chris@16: case is_int: Chris@16: value.i = as_long(rhs); Chris@16: type = is_int; Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: value.ui = as_ulong(rhs); Chris@16: type = is_uint; Chris@16: break; Chris@16: Chris@16: case is_bool: Chris@16: value.b = as_bool(rhs); Chris@16: type = is_bool; Chris@16: break; Chris@16: } Chris@16: valid = rhs.valid; Chris@16: return *this; Chris@16: } Chris@16: closure_value &operator= (int rhs) Chris@16: { Chris@16: type = is_int; Chris@16: value.i = rhs; Chris@16: valid = error_noerror; Chris@16: return *this; Chris@16: } Chris@16: closure_value &operator= (unsigned int rhs) Chris@16: { Chris@16: type = is_uint; Chris@16: value.ui = rhs; Chris@16: valid = error_noerror; Chris@16: return *this; Chris@16: } Chris@16: closure_value &operator= (int_literal_type rhs) Chris@16: { Chris@16: type = is_int; Chris@16: value.i = rhs; Chris@16: valid = error_noerror; Chris@16: return *this; Chris@16: } Chris@16: closure_value &operator= (uint_literal_type rhs) Chris@16: { Chris@16: type = is_uint; Chris@16: value.ui = rhs; Chris@16: valid = error_noerror; Chris@16: return *this; Chris@16: } Chris@16: closure_value &operator= (bool rhs) Chris@16: { Chris@16: type = is_bool; Chris@16: value.b = rhs; Chris@16: valid = error_noerror; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // arithmetics Chris@16: closure_value &operator+= (closure_value const &rhs) Chris@16: { Chris@16: switch (type) { Chris@16: case is_int: Chris@16: switch(rhs.type) { Chris@16: case is_bool: Chris@16: { Chris@16: int_literal_type result = value.i + as_long(rhs); Chris@16: if ((rhs.value.i > 0L && value.i > result) || Chris@16: (rhs.value.i < 0L && value.i < result)) Chris@16: { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.i = result; Chris@16: } Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_int: Chris@16: { Chris@16: int_literal_type result = value.i + rhs.value.i; Chris@16: if ((rhs.value.i > 0L && value.i > result) || Chris@16: (rhs.value.i < 0L && value.i < result)) Chris@16: { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.i = result; Chris@16: } Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: { Chris@16: uint_literal_type result = value.ui + rhs.value.ui; Chris@16: if (result < value.ui) { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.ui = result; Chris@16: type = is_uint; Chris@16: } Chris@16: } Chris@16: break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: { Chris@16: uint_literal_type result = value.ui + as_ulong(rhs); Chris@16: if (result < value.ui) { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.ui = result; Chris@16: } Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_bool: Chris@16: value.i = value.b + as_bool(rhs); Chris@16: type = is_int; Chris@16: } Chris@16: valid = (value_error)(valid | rhs.valid); Chris@16: return *this; Chris@16: } Chris@16: closure_value &operator-= (closure_value const &rhs) Chris@16: { Chris@16: switch (type) { Chris@16: case is_int: Chris@16: switch(rhs.type) { Chris@16: case is_bool: Chris@16: { Chris@16: int_literal_type result = value.i - as_long(rhs); Chris@16: if ((rhs.value.i > 0L && result > value.i) || Chris@16: (rhs.value.i < 0L && result < value.i)) Chris@16: { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.i = result; Chris@16: } Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_int: Chris@16: { Chris@16: int_literal_type result = value.i - rhs.value.i; Chris@16: if ((rhs.value.i > 0L && result > value.i) || Chris@16: (rhs.value.i < 0L && result < value.i)) Chris@16: { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.i = result; Chris@16: } Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: { Chris@16: uint_literal_type result = value.ui - rhs.value.ui; Chris@16: if (result > value.ui) { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.ui = result; Chris@16: type = is_uint; Chris@16: } Chris@16: } Chris@16: break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: switch(rhs.type) { Chris@16: case is_bool: Chris@16: { Chris@16: uint_literal_type result = value.ui - as_ulong(rhs); Chris@16: if (result > value.ui) Chris@16: { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.ui = result; Chris@16: } Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_int: Chris@16: { Chris@16: uint_literal_type result = value.ui - rhs.value.i; Chris@16: if ((rhs.value.i > 0L && result > value.ui) || Chris@16: (rhs.value.i < 0L && result < value.ui)) Chris@16: { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.ui = result; Chris@16: } Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: { Chris@16: uint_literal_type result = value.ui - rhs.value.ui; Chris@16: if (result > value.ui) { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.ui = result; Chris@16: } Chris@16: } Chris@16: break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_bool: Chris@16: value.i = value.b - as_bool(rhs); Chris@16: type = is_int; Chris@16: } Chris@16: valid = (value_error)(valid | rhs.valid); Chris@16: return *this; Chris@16: } Chris@16: closure_value &operator*= (closure_value const &rhs) Chris@16: { Chris@16: switch (type) { Chris@16: case is_int: Chris@16: switch(rhs.type) { Chris@16: case is_bool: value.i *= as_long(rhs); break; Chris@16: case is_int: Chris@16: { Chris@16: int_literal_type result = value.i * rhs.value.i; Chris@16: if (0 != value.i && 0 != rhs.value.i && Chris@16: (result / value.i != rhs.value.i || Chris@16: result / rhs.value.i != value.i) Chris@16: ) Chris@16: { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.i = result; Chris@16: } Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: { Chris@16: uint_literal_type result = value.ui * rhs.value.ui; Chris@16: if (0 != value.ui && 0 != rhs.value.ui && Chris@16: (result / value.ui != rhs.value.ui || Chris@16: result / rhs.value.ui != value.ui) Chris@16: ) Chris@16: { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.ui = result; Chris@16: type = is_uint; Chris@16: } Chris@16: } Chris@16: break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: { Chris@16: uint_literal_type rhs_val = as_ulong(rhs); Chris@16: uint_literal_type result = value.ui * rhs_val; Chris@16: if (0 != value.ui && 0 != rhs_val && Chris@16: (result / value.ui != rhs_val || Chris@16: result / rhs_val != value.ui) Chris@16: ) Chris@16: { Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.ui = result; Chris@16: type = is_uint; Chris@16: } Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_bool: Chris@16: switch (rhs.type) { Chris@16: case is_int: Chris@16: value.i = (value.b ? 1 : 0) * rhs.value.i; Chris@16: type = is_int; Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: value.ui = (value.b ? 1 : 0) * rhs.value.ui; Chris@16: type = is_uint; Chris@16: break; Chris@16: Chris@16: case is_bool: Chris@16: value.b = 0 != ((value.b ? 1 : 0) * (rhs.value.b ? 1 : 0)); Chris@16: break; Chris@16: } Chris@16: } Chris@16: valid = (value_error)(valid | rhs.valid); Chris@16: return *this; Chris@16: } Chris@16: closure_value &operator/= (closure_value const &rhs) Chris@16: { Chris@16: switch (type) { Chris@16: case is_int: Chris@16: switch(rhs.type) { Chris@16: case is_bool: Chris@16: case is_int: Chris@16: if (as_long(rhs) != 0) { Chris@16: if (value.i == -value.i && -1 == rhs.value.i) { Chris@16: // LONG_MIN / -1 on two's complement Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.i /= as_long(rhs); Chris@16: } Chris@16: } Chris@16: else { Chris@16: valid = error_division_by_zero; // division by zero Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: if (rhs.value.ui != 0) { Chris@16: value.ui /= rhs.value.ui; Chris@16: type = is_uint; Chris@16: } Chris@16: else { Chris@16: valid = error_division_by_zero; // division by zero Chris@16: } Chris@16: break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: if (as_ulong(rhs) != 0) Chris@16: value.ui /= as_ulong(rhs); Chris@16: else Chris@16: valid = error_division_by_zero; // division by zero Chris@16: break; Chris@16: Chris@16: case is_bool: Chris@16: if (as_bool(rhs)) { Chris@16: switch(rhs.type) { Chris@16: case is_int: Chris@16: value.i = (value.b ? 1 : 0) / rhs.value.i; Chris@16: type = is_int; Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: value.i = (value.b ? 1 : 0) / rhs.value.ui; Chris@16: type = is_int; Chris@16: break; Chris@16: Chris@16: case is_bool: Chris@16: break; Chris@16: } Chris@16: } Chris@16: else { Chris@16: valid = error_division_by_zero; // division by zero Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: closure_value &operator%= (closure_value const &rhs) Chris@16: { Chris@16: switch (type) { Chris@16: case is_int: Chris@16: switch(rhs.type) { Chris@16: case is_bool: Chris@16: case is_int: Chris@16: if (as_long(rhs) != 0) { Chris@16: if (value.i == -value.i && -1 == rhs.value.i) { Chris@16: // LONG_MIN % -1 on two's complement Chris@16: valid = error_integer_overflow; Chris@16: } Chris@16: else { Chris@16: value.i %= as_long(rhs); Chris@16: } Chris@16: } Chris@16: else { Chris@16: valid = error_division_by_zero; // division by zero Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: if (rhs.value.ui != 0) { Chris@16: value.ui %= rhs.value.ui; Chris@16: type = is_uint; Chris@16: } Chris@16: else { Chris@16: valid = error_division_by_zero; // division by zero Chris@16: } Chris@16: break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: if (as_ulong(rhs) != 0) Chris@16: value.ui %= as_ulong(rhs); Chris@16: else Chris@16: valid = error_division_by_zero; // division by zero Chris@16: break; Chris@16: Chris@16: case is_bool: Chris@16: if (as_bool(rhs)) { Chris@16: switch(rhs.type) { Chris@16: case is_int: Chris@16: value.i = (value.b ? 1 : 0) % rhs.value.i; Chris@16: type = is_int; Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: value.i = (value.b ? 1 : 0) % rhs.value.ui; Chris@16: type = is_int; Chris@16: break; Chris@16: Chris@16: case is_bool: Chris@16: break; Chris@16: } Chris@16: } Chris@16: else { Chris@16: valid = error_division_by_zero; // division by zero Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: friend closure_value Chris@16: operator- (closure_value const &rhs) Chris@16: { Chris@16: switch (rhs.type) { Chris@16: case is_int: Chris@16: { Chris@16: int_literal_type value = as_long(rhs); Chris@16: if (value != 0 && value == -value) Chris@16: return closure_value(-value, error_integer_overflow); Chris@16: return closure_value(-value, rhs.valid); Chris@16: } Chris@16: Chris@16: case is_bool: return closure_value(-as_long(rhs), rhs.valid); Chris@16: case is_uint: break; Chris@16: } Chris@16: Chris@16: int_literal_type value = as_ulong(rhs); Chris@16: if (value != 0 && value == -value) Chris@16: return closure_value(-value, error_integer_overflow); Chris@16: return closure_value(-value, rhs.valid); Chris@16: } Chris@16: friend closure_value Chris@16: operator~ (closure_value const &rhs) Chris@16: { Chris@16: return closure_value(~as_ulong(rhs), rhs.valid); Chris@16: } Chris@16: friend closure_value Chris@16: operator! (closure_value const &rhs) Chris@16: { Chris@16: switch (rhs.type) { Chris@16: case is_int: return closure_value(!as_long(rhs), rhs.valid); Chris@16: case is_bool: return closure_value(!as_bool(rhs), rhs.valid); Chris@16: case is_uint: break; Chris@16: } Chris@16: return closure_value(!as_ulong(rhs), rhs.valid); Chris@16: } Chris@16: Chris@16: // comparison Chris@16: friend closure_value Chris@16: operator== (closure_value const &lhs, closure_value const &rhs) Chris@16: { Chris@16: bool cmp = false; Chris@16: switch (lhs.type) { Chris@16: case is_int: Chris@16: switch(rhs.type) { Chris@16: case is_bool: cmp = as_bool(lhs) == rhs.value.b; break; Chris@16: case is_int: cmp = lhs.value.i == rhs.value.i; break; Chris@16: case is_uint: cmp = lhs.value.ui == rhs.value.ui; break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: cmp = lhs.value.ui == as_ulong(rhs); break; Chris@16: case is_bool: cmp = lhs.value.b == as_bool(rhs); break; Chris@16: } Chris@16: return closure_value(cmp, (value_error)(lhs.valid | rhs.valid)); Chris@16: } Chris@16: friend closure_value Chris@16: operator!= (closure_value const &lhs, closure_value const &rhs) Chris@16: { Chris@16: return closure_value(!as_bool(lhs == rhs), (value_error)(lhs.valid | rhs.valid)); Chris@16: } Chris@16: friend closure_value Chris@16: operator> (closure_value const &lhs, closure_value const &rhs) Chris@16: { Chris@16: bool cmp = false; Chris@16: switch (lhs.type) { Chris@16: case is_int: Chris@16: switch(rhs.type) { Chris@16: case is_bool: cmp = lhs.value.i > as_long(rhs); break; Chris@16: case is_int: cmp = lhs.value.i > rhs.value.i; break; Chris@16: case is_uint: cmp = lhs.value.ui > rhs.value.ui; break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: cmp = lhs.value.ui > as_ulong(rhs); break; Chris@16: case is_bool: cmp = lhs.value.b > as_bool(rhs); break; Chris@16: } Chris@16: return closure_value(cmp, (value_error)(lhs.valid | rhs.valid)); Chris@16: } Chris@16: friend closure_value Chris@16: operator< (closure_value const &lhs, closure_value const &rhs) Chris@16: { Chris@16: bool cmp = false; Chris@16: switch (lhs.type) { Chris@16: case is_int: Chris@16: switch(rhs.type) { Chris@16: case is_bool: cmp = lhs.value.i < as_long(rhs); break; Chris@16: case is_int: cmp = lhs.value.i < rhs.value.i; break; Chris@16: case is_uint: cmp = lhs.value.ui < rhs.value.ui; break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: cmp = lhs.value.ui < as_ulong(rhs); break; Chris@16: case is_bool: cmp = as_bool(lhs) < as_bool(rhs); break; Chris@16: } Chris@16: return closure_value(cmp, (value_error)(lhs.valid | rhs.valid)); Chris@16: } Chris@16: friend closure_value Chris@16: operator<= (closure_value const &lhs, closure_value const &rhs) Chris@16: { Chris@16: return closure_value(!as_bool(lhs > rhs), (value_error)(lhs.valid | rhs.valid)); Chris@16: } Chris@16: friend closure_value Chris@16: operator>= (closure_value const &lhs, closure_value const &rhs) Chris@16: { Chris@16: return closure_value(!as_bool(lhs < rhs), (value_error)(lhs.valid | rhs.valid)); Chris@16: } Chris@16: Chris@16: closure_value & Chris@16: operator<<= (closure_value const &rhs) Chris@16: { Chris@16: switch (type) { Chris@16: case is_bool: Chris@16: case is_int: Chris@16: switch (rhs.type) { Chris@16: case is_bool: Chris@16: case is_int: Chris@16: { Chris@16: int_literal_type shift_by = as_long(rhs); Chris@16: Chris@16: if (shift_by > 64) Chris@16: shift_by = 64; Chris@16: else if (shift_by < -64) Chris@16: shift_by = -64; Chris@16: value.i <<= shift_by; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: { Chris@16: uint_literal_type shift_by = as_ulong(rhs); Chris@16: Chris@16: if (shift_by > 64) Chris@16: shift_by = 64; Chris@16: value.ui <<= shift_by; Chris@16: Chris@16: // Note: The usual arithmetic conversions are not performed on Chris@16: // bit shift operations. Chris@16: } Chris@16: break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: switch (rhs.type) { Chris@16: case is_bool: Chris@16: case is_int: Chris@16: { Chris@16: int_literal_type shift_by = as_long(rhs); Chris@16: Chris@16: if (shift_by > 64) Chris@16: shift_by = 64; Chris@16: else if (shift_by < -64) Chris@16: shift_by = -64; Chris@16: value.ui <<= shift_by; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: { Chris@16: uint_literal_type shift_by = as_ulong(rhs); Chris@16: Chris@16: if (shift_by > 64) Chris@16: shift_by = 64; Chris@16: value.ui <<= shift_by; Chris@16: } Chris@16: break; Chris@16: } Chris@16: } Chris@16: valid = (value_error)(valid | rhs.valid); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: closure_value & Chris@16: operator>>= (closure_value const &rhs) Chris@16: { Chris@16: switch (type) { Chris@16: case is_bool: Chris@16: case is_int: Chris@16: switch (rhs.type) { Chris@16: case is_bool: Chris@16: case is_int: Chris@16: { Chris@16: int_literal_type shift_by = as_long(rhs); Chris@16: Chris@16: if (shift_by > 64) Chris@16: shift_by = 64; Chris@16: else if (shift_by < -64) Chris@16: shift_by = -64; Chris@16: value.i >>= shift_by; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: { Chris@16: uint_literal_type shift_by = as_ulong(rhs); Chris@16: Chris@16: if (shift_by > 64) Chris@16: shift_by = 64; Chris@16: value.ui >>= shift_by; Chris@16: Chris@16: // Note: The usual arithmetic conversions are not performed on Chris@16: // bit shift operations. Chris@16: } Chris@16: break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: switch (rhs.type) { Chris@16: case is_bool: Chris@16: case is_int: Chris@16: { Chris@16: int_literal_type shift_by = as_long(rhs); Chris@16: Chris@16: if (shift_by > 64) Chris@16: shift_by = 64; Chris@16: else if (shift_by < -64) Chris@16: shift_by = -64; Chris@16: value.ui >>= shift_by; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: Chris@16: { Chris@16: uint_literal_type shift_by = as_ulong(rhs); Chris@16: Chris@16: if (shift_by > 64) Chris@16: shift_by = 64; Chris@16: value.ui >>= shift_by; Chris@16: } Chris@16: break; Chris@16: } Chris@16: break; Chris@16: } Chris@16: valid = (value_error)(valid | rhs.valid); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: friend closure_value Chris@16: operator|| (closure_value const &lhs, closure_value const &rhs) Chris@16: { Chris@16: bool result = as_bool(lhs) || as_bool(rhs); Chris@16: return closure_value(result, (value_error)(lhs.valid | rhs.valid)); Chris@16: } Chris@16: Chris@16: friend closure_value Chris@16: operator&& (closure_value const &lhs, closure_value const &rhs) Chris@16: { Chris@16: bool result = as_bool(lhs) && as_bool(rhs); Chris@16: return closure_value(result, (value_error)(lhs.valid | rhs.valid)); Chris@16: } Chris@16: Chris@16: friend closure_value Chris@16: operator| (closure_value const &lhs, closure_value const &rhs) Chris@16: { Chris@16: uint_literal_type result = as_ulong(lhs) | as_ulong(rhs); Chris@16: return closure_value(result, (value_error)(lhs.valid | rhs.valid)); Chris@16: } Chris@16: Chris@16: friend closure_value Chris@16: operator& (closure_value const &lhs, closure_value const &rhs) Chris@16: { Chris@16: uint_literal_type result = as_ulong(lhs) & as_ulong(rhs); Chris@16: return closure_value(result, (value_error)(lhs.valid | rhs.valid)); Chris@16: } Chris@16: Chris@16: friend closure_value Chris@16: operator^ (closure_value const &lhs, closure_value const &rhs) Chris@16: { Chris@16: uint_literal_type result = as_ulong(lhs) ^ as_ulong(rhs); Chris@16: return closure_value(result, (value_error)(lhs.valid | rhs.valid)); Chris@16: } Chris@16: Chris@16: // handle the ?: operator Chris@16: closure_value & Chris@16: handle_questionmark(closure_value const &cond, closure_value const &val2) Chris@16: { Chris@16: switch (type) { Chris@16: case is_int: Chris@16: switch (val2.type) { Chris@16: case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break; Chris@16: case is_int: value.i = as_bool(cond) ? value.i : as_long(val2); break; Chris@16: case is_uint: Chris@16: value.ui = as_bool(cond) ? value.ui : as_ulong(val2); Chris@16: type = is_uint; // changing type! Chris@16: break; Chris@16: } Chris@16: break; Chris@16: Chris@16: case is_uint: value.ui = as_bool(cond) ? value.ui : as_ulong(val2); break; Chris@16: case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break; Chris@16: } Chris@16: valid = as_bool(cond) ? valid : val2.valid; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #if defined (BOOST_SPIRIT_DEBUG) Chris@16: friend std::ostream& Chris@16: operator<< (std::ostream &o, closure_value const &val) Chris@16: { Chris@16: switch (val.type) { Chris@16: case is_int: o << "int(" << as_long(val) << ")"; break; Chris@16: case is_uint: o << "unsigned int(" << as_ulong(val) << ")"; break; Chris@16: case is_bool: o << "bool(" << as_bool(val) << ")"; break; Chris@16: } Chris@16: return o; Chris@16: } Chris@16: #endif // defined(BOOST_SPIRIT_DEBUG) Chris@16: Chris@16: private: Chris@16: value_type type; Chris@16: union { Chris@16: int_literal_type i; Chris@16: uint_literal_type ui; Chris@16: bool b; Chris@16: } value; Chris@16: value_error valid; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: } // namespace closures Chris@16: } // namespace grammars Chris@16: } // namespace wave Chris@16: } // namespace boost Chris@16: Chris@16: // the suffix header occurs after all of the code Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_SUFFIX Chris@16: #endif Chris@16: Chris@16: #endif // !defined(CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED)