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