Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:39

0001 /*=============================================================================
0002     Boost.Wave: A Standard compliant C++ preprocessor library
0003 
0004     http://www.boost.org/
0005 
0006     Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
0007     Software License, Version 1.0. (See accompanying file
0008     LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 =============================================================================*/
0010 
0011 #if !defined(BOOST_CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED)
0012 #define BOOST_CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED
0013 
0014 #if defined (BOOST_SPIRIT_DEBUG)
0015 #include <iostream>
0016 #endif // defined(BOOST_SPIRIT_DEBUG)
0017 
0018 #include <boost/wave/wave_config.hpp>
0019 #include <boost/wave/grammars/cpp_value_error.hpp> // value_error
0020 
0021 // this must occur after all of the includes and before any code appears
0022 #ifdef BOOST_HAS_ABI_HEADERS
0023 #include BOOST_ABI_PREFIX
0024 #endif
0025 
0026 ///////////////////////////////////////////////////////////////////////////////
0027 namespace boost {
0028 namespace wave {
0029 namespace grammars {
0030 namespace closures {
0031 
0032 class closure_value;
0033 inline bool as_bool(closure_value const& v);
0034 
0035 ///////////////////////////////////////////////////////////////////////////////
0036 //
0037 //  The closure_value class represents the closure type, which is used for the
0038 //  expression grammar.
0039 //
0040 //      This class was introduced to allow the expression grammar to respect
0041 //      the numeric type of a numeric literal or expression result.
0042 //
0043 ///////////////////////////////////////////////////////////////////////////////
0044 class closure_value {
0045 public:
0046 
0047     enum value_type {
0048         is_int = 1,
0049         is_uint = 2,
0050         is_bool = 3
0051     };
0052 
0053     closure_value(value_error valid_ = error_noerror)
0054     : type(is_int), valid(valid_)
0055     { value.i = 0; }
0056     explicit closure_value(int i, value_error valid_ = error_noerror)
0057     : type(is_int), valid(valid_)
0058     { value.i = i; }
0059     explicit closure_value(unsigned int ui, value_error valid_ = error_noerror)
0060     : type(is_uint), valid(valid_)
0061     { value.ui = ui; }
0062     explicit closure_value(int_literal_type i, value_error valid_ = error_noerror)
0063     : type(is_int), valid(valid_)
0064     { value.i = i; }
0065     explicit closure_value(uint_literal_type ui, value_error valid_ = error_noerror)
0066     : type(is_uint), valid(valid_)
0067     { value.ui = ui; }
0068     explicit closure_value(bool b, value_error valid_ = error_noerror)
0069     : type(is_bool), valid(valid_)
0070     { value.b = b; }
0071 
0072     value_type get_type() const { return type; }
0073     value_error is_valid() const { return valid; }
0074 
0075     // explicit conversion
0076     friend int_literal_type as_int(closure_value const& v)
0077     {
0078         switch (v.type) {
0079         case is_uint:   return v.value.ui;
0080         case is_bool:   return v.value.b ? 1 : 0;
0081         case is_int:    break;
0082         }
0083         return v.value.i;
0084     }
0085     friend uint_literal_type as_uint(closure_value const& v)
0086     {
0087         switch (v.type) {
0088         case is_uint:   return v.value.ui;
0089         case is_bool:   return v.value.b ? 1 : 0;
0090         case is_int:    break;
0091         }
0092         return v.value.i;
0093     }
0094     friend int_literal_type as_long(closure_value const& v)
0095     {
0096         switch (v.type) {
0097         case is_uint:   return v.value.ui;
0098         case is_bool:   return v.value.b ? 1 : 0;
0099         case is_int:    break;
0100         }
0101         return v.value.i;
0102     }
0103     friend uint_literal_type as_ulong(closure_value const& v)
0104     {
0105         switch (v.type) {
0106         case is_uint:   return v.value.ui;
0107         case is_bool:   return v.value.b ? 1 : 0;
0108         case is_int:    break;
0109         }
0110         return v.value.i;
0111     }
0112     friend bool as_bool(closure_value const& v)
0113     {
0114         switch (v.type) {
0115         case is_uint:   return v.value.ui != 0;
0116         case is_bool:   return v.value.b;
0117         case is_int:    break;
0118         }
0119         return v.value.i != 0.0;
0120     }
0121 
0122     // assignment
0123     closure_value &operator= (closure_value const &rhs)
0124     {
0125         switch (rhs.get_type()) {
0126         case is_int:
0127             value.i = as_long(rhs);
0128             type = is_int;
0129             break;
0130 
0131         case is_uint:
0132             value.ui = as_ulong(rhs);
0133             type = is_uint;
0134             break;
0135 
0136         case is_bool:
0137             value.b = as_bool(rhs);
0138             type = is_bool;
0139             break;
0140         }
0141         valid = rhs.valid;
0142         return *this;
0143     }
0144     closure_value &operator= (int rhs)
0145     {
0146         type = is_int;
0147         value.i = rhs;
0148         valid = error_noerror;
0149         return *this;
0150     }
0151     closure_value &operator= (unsigned int rhs)
0152     {
0153         type = is_uint;
0154         value.ui = rhs;
0155         valid = error_noerror;
0156         return *this;
0157     }
0158     closure_value &operator= (int_literal_type rhs)
0159     {
0160         type = is_int;
0161         value.i = rhs;
0162         valid = error_noerror;
0163         return *this;
0164     }
0165     closure_value &operator= (uint_literal_type rhs)
0166     {
0167         type = is_uint;
0168         value.ui = rhs;
0169         valid = error_noerror;
0170         return *this;
0171     }
0172     closure_value &operator= (bool rhs)
0173     {
0174         type = is_bool;
0175         value.b = rhs;
0176         valid = error_noerror;
0177         return *this;
0178     }
0179 
0180     // arithmetics
0181     closure_value &operator+= (closure_value const &rhs)
0182     {
0183         switch (type) {
0184         case is_int:
0185             switch(rhs.type) {
0186             case is_bool:
0187                 {
0188                     int_literal_type result = value.i + as_long(rhs);
0189                     if ((rhs.value.i > 0L && value.i > result) ||
0190                         (rhs.value.i < 0L && value.i < result))
0191                     {
0192                         valid = error_integer_overflow;
0193                     }
0194                     else {
0195                         value.i = result;
0196                     }
0197                 }
0198                 break;
0199 
0200             case is_int:
0201                 {
0202                     int_literal_type result = value.i + rhs.value.i;
0203                     if ((rhs.value.i > 0L && value.i > result) ||
0204                         (rhs.value.i < 0L && value.i < result))
0205                     {
0206                         valid = error_integer_overflow;
0207                     }
0208                     else {
0209                         value.i = result;
0210                     }
0211                 }
0212                 break;
0213 
0214             case is_uint:
0215                 {
0216                     uint_literal_type result = value.ui + rhs.value.ui;
0217                     if (result < value.ui) {
0218                         valid = error_integer_overflow;
0219                     }
0220                     else {
0221                         value.ui = result;
0222                         type = is_uint;
0223                     }
0224                 }
0225                 break;
0226             }
0227             break;
0228 
0229         case is_uint:
0230             {
0231                 uint_literal_type result = value.ui + as_ulong(rhs);
0232                 if (result < value.ui) {
0233                     valid = error_integer_overflow;
0234                 }
0235                 else {
0236                     value.ui = result;
0237                 }
0238             }
0239             break;
0240 
0241         case is_bool:
0242             value.i = value.b + as_bool(rhs);
0243             type = is_int;
0244         }
0245         valid = (value_error)(valid | rhs.valid);
0246         return *this;
0247     }
0248     closure_value &operator-= (closure_value const &rhs)
0249     {
0250         switch (type) {
0251         case is_int:
0252             switch(rhs.type) {
0253             case is_bool:
0254                 {
0255                     int_literal_type result = value.i - as_long(rhs);
0256                     if ((rhs.value.i > 0L && result > value.i) ||
0257                         (rhs.value.i < 0L && result < value.i))
0258                     {
0259                         valid = error_integer_overflow;
0260                     }
0261                     else {
0262                         value.i = result;
0263                     }
0264                 }
0265                 break;
0266 
0267             case is_int:
0268                 {
0269                     int_literal_type result = value.i - rhs.value.i;
0270                     if ((rhs.value.i > 0L && result > value.i) ||
0271                         (rhs.value.i < 0L && result < value.i))
0272                     {
0273                         valid = error_integer_overflow;
0274                     }
0275                     else {
0276                         value.i = result;
0277                     }
0278                 }
0279                 break;
0280 
0281             case is_uint:
0282                 {
0283                     uint_literal_type result = value.ui - rhs.value.ui;
0284                     if (result > value.ui) {
0285                         valid = error_integer_overflow;
0286                     }
0287                     else {
0288                         value.ui = result;
0289                         type = is_uint;
0290                     }
0291                 }
0292                 break;
0293             }
0294             break;
0295 
0296         case is_uint:
0297             switch(rhs.type) {
0298             case is_bool:
0299                 {
0300                     uint_literal_type result = value.ui - as_ulong(rhs);
0301                     if (result > value.ui)
0302                     {
0303                         valid = error_integer_overflow;
0304                     }
0305                     else {
0306                         value.ui = result;
0307                     }
0308                 }
0309                 break;
0310 
0311             case is_int:
0312                 {
0313                     uint_literal_type result = value.ui - rhs.value.i;
0314                     if ((rhs.value.i > 0L && result > value.ui) ||
0315                         (rhs.value.i < 0L && result < value.ui))
0316                     {
0317                         valid = error_integer_overflow;
0318                     }
0319                     else {
0320                         value.ui = result;
0321                     }
0322                 }
0323                 break;
0324 
0325             case is_uint:
0326                 {
0327                     uint_literal_type result = value.ui - rhs.value.ui;
0328                     if (result > value.ui) {
0329                         valid = error_integer_overflow;
0330                     }
0331                     else {
0332                         value.ui = result;
0333                     }
0334                 }
0335                 break;
0336             }
0337             break;
0338 
0339         case is_bool:
0340             value.i = value.b - as_bool(rhs);
0341             type = is_int;
0342         }
0343         valid = (value_error)(valid | rhs.valid);
0344         return *this;
0345     }
0346     closure_value &operator*= (closure_value const &rhs)
0347     {
0348         switch (type) {
0349         case is_int:
0350             switch(rhs.type) {
0351             case is_bool:   value.i *= as_long(rhs); break;
0352             case is_int:
0353                 {
0354                     int_literal_type result = value.i * rhs.value.i;
0355                     if (0 != value.i && 0 != rhs.value.i &&
0356                         (result / value.i != rhs.value.i ||
0357                          result / rhs.value.i != value.i)
0358                        )
0359                     {
0360                         valid = error_integer_overflow;
0361                     }
0362                     else {
0363                         value.i = result;
0364                     }
0365                 }
0366                 break;
0367 
0368             case is_uint:
0369                 {
0370                     uint_literal_type result = value.ui * rhs.value.ui;
0371                     if (0 != value.ui && 0 != rhs.value.ui &&
0372                         (result / value.ui != rhs.value.ui ||
0373                          result / rhs.value.ui != value.ui)
0374                        )
0375                     {
0376                         valid = error_integer_overflow;
0377                     }
0378                     else {
0379                         value.ui = result;
0380                         type = is_uint;
0381                     }
0382                 }
0383                 break;
0384             }
0385             break;
0386 
0387         case is_uint:
0388             {
0389                 uint_literal_type rhs_val = as_ulong(rhs);
0390                 uint_literal_type result = value.ui * rhs_val;
0391                 if (0 != value.ui && 0 != rhs_val &&
0392                     (result / value.ui != rhs_val ||
0393                       result / rhs_val != value.ui)
0394                     )
0395                 {
0396                     valid = error_integer_overflow;
0397                 }
0398                 else {
0399                     value.ui = result;
0400                     type = is_uint;
0401                 }
0402             }
0403             break;
0404 
0405         case is_bool:
0406             switch (rhs.type) {
0407             case is_int:
0408                 value.i = (value.b ? 1 : 0) * rhs.value.i;
0409                 type = is_int;
0410                 break;
0411 
0412             case is_uint:
0413                 value.ui = (value.b ? 1 : 0) * rhs.value.ui;
0414                 type = is_uint;
0415                 break;
0416 
0417             case is_bool:
0418                 value.b = 0 != ((value.b ? 1 : 0) * (rhs.value.b ? 1 : 0));
0419                 break;
0420             }
0421         }
0422         valid = (value_error)(valid | rhs.valid);
0423         return *this;
0424     }
0425     closure_value &operator/= (closure_value const &rhs)
0426     {
0427         switch (type) {
0428         case is_int:
0429             switch(rhs.type) {
0430             case is_bool:
0431             case is_int:
0432                 if (as_long(rhs) != 0) {
0433                     if (value.i == -value.i && -1 == rhs.value.i) {
0434                         // LONG_MIN / -1 on two's complement
0435                         valid = error_integer_overflow;
0436                     }
0437                     else {
0438                         value.i /= as_long(rhs);
0439                     }
0440                 }
0441                 else {
0442                     valid = error_division_by_zero;   // division by zero
0443                 }
0444                 break;
0445 
0446             case is_uint:
0447                 if (rhs.value.ui != 0) {
0448                     value.ui /= rhs.value.ui;
0449                     type = is_uint;
0450                 }
0451                 else {
0452                     valid = error_division_by_zero;      // division by zero
0453                 }
0454                 break;
0455             }
0456             break;
0457 
0458         case is_uint:
0459             if (as_ulong(rhs) != 0)
0460                 value.ui /= as_ulong(rhs);
0461             else
0462                 valid = error_division_by_zero;         // division by zero
0463             break;
0464 
0465         case is_bool:
0466             if (as_bool(rhs)) {
0467                 switch(rhs.type) {
0468                 case is_int:
0469                     value.i = (value.b ? 1 : 0) / rhs.value.i;
0470                     type = is_int;
0471                     break;
0472 
0473                 case is_uint:
0474                     value.i = (value.b ? 1 : 0) / rhs.value.ui;
0475                     type = is_int;
0476                     break;
0477 
0478                 case is_bool:
0479                     break;
0480                 }
0481             }
0482             else {
0483                 valid = error_division_by_zero;         // division by zero
0484             }
0485         }
0486         return *this;
0487     }
0488     closure_value &operator%= (closure_value const &rhs)
0489     {
0490         switch (type) {
0491         case is_int:
0492             switch(rhs.type) {
0493             case is_bool:
0494             case is_int:
0495                 if (as_long(rhs) != 0) {
0496                     if (value.i == -value.i && -1 == rhs.value.i) {
0497                         // LONG_MIN % -1 on two's complement
0498                         valid = error_integer_overflow;
0499                     }
0500                     else {
0501                         value.i %= as_long(rhs);
0502                     }
0503                 }
0504                 else {
0505                     valid = error_division_by_zero;      // division by zero
0506                 }
0507                 break;
0508 
0509             case is_uint:
0510                 if (rhs.value.ui != 0) {
0511                     value.ui %= rhs.value.ui;
0512                     type = is_uint;
0513                 }
0514                 else {
0515                     valid = error_division_by_zero;      // division by zero
0516                 }
0517                 break;
0518             }
0519             break;
0520 
0521         case is_uint:
0522             if (as_ulong(rhs) != 0)
0523                 value.ui %= as_ulong(rhs);
0524             else
0525                 valid = error_division_by_zero;      // division by zero
0526             break;
0527 
0528         case is_bool:
0529             if (as_bool(rhs)) {
0530                 switch(rhs.type) {
0531                 case is_int:
0532                     value.i = (value.b ? 1 : 0) % rhs.value.i;
0533                     type = is_int;
0534                     break;
0535 
0536                 case is_uint:
0537                     value.i = (value.b ? 1 : 0) % rhs.value.ui;
0538                     type = is_int;
0539                     break;
0540 
0541                 case is_bool:
0542                     break;
0543                 }
0544             }
0545             else {
0546                 valid = error_division_by_zero;      // division by zero
0547             }
0548         }
0549         return *this;
0550     }
0551 
0552     friend closure_value
0553     operator- (closure_value const &rhs)
0554     {
0555         switch (rhs.type) {
0556         case is_int:
0557             {
0558                 int_literal_type value = as_long(rhs);
0559                 if (value != 0 && value == -value)
0560                     return closure_value(-value, error_integer_overflow);
0561                 return closure_value(-value, rhs.valid);
0562             }
0563 
0564         case is_bool:   return closure_value(-as_long(rhs), rhs.valid);
0565         case is_uint:   break;
0566         }
0567 
0568         int_literal_type value = as_ulong(rhs);
0569         if (value != 0 && value == -value)
0570             return closure_value(-value, error_integer_overflow);
0571         return closure_value(-value, rhs.valid);
0572     }
0573     friend closure_value
0574     operator~ (closure_value const &rhs)
0575     {
0576         return closure_value(~as_ulong(rhs), rhs.valid);
0577     }
0578     friend closure_value
0579     operator! (closure_value const &rhs)
0580     {
0581         switch (rhs.type) {
0582         case is_int:    return closure_value(!as_long(rhs), rhs.valid);
0583         case is_bool:   return closure_value(!as_bool(rhs), rhs.valid);
0584         case is_uint:   break;
0585         }
0586         return closure_value(!as_ulong(rhs), rhs.valid);
0587     }
0588 
0589     // comparison
0590     friend closure_value
0591     operator== (closure_value const &lhs, closure_value const &rhs)
0592     {
0593         bool cmp = false;
0594         switch (lhs.type) {
0595         case is_int:
0596             switch(rhs.type) {
0597             case is_bool:   cmp = as_bool(lhs) == rhs.value.b; break;
0598             case is_int:    cmp = lhs.value.i == rhs.value.i; break;
0599             case is_uint:   cmp = lhs.value.ui == rhs.value.ui; break;
0600             }
0601             break;
0602 
0603         case is_uint:   cmp = lhs.value.ui == as_ulong(rhs); break;
0604         case is_bool:   cmp = lhs.value.b == as_bool(rhs); break;
0605         }
0606         return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
0607     }
0608     friend closure_value
0609     operator!= (closure_value const &lhs, closure_value const &rhs)
0610     {
0611         return closure_value(!as_bool(lhs == rhs), (value_error)(lhs.valid | rhs.valid));
0612     }
0613     friend closure_value
0614     operator> (closure_value const &lhs, closure_value const &rhs)
0615     {
0616         bool cmp = false;
0617         switch (lhs.type) {
0618         case is_int:
0619             switch(rhs.type) {
0620             case is_bool:   cmp = lhs.value.i > as_long(rhs); break;
0621             case is_int:    cmp = lhs.value.i > rhs.value.i; break;
0622             case is_uint:   cmp = lhs.value.ui > rhs.value.ui; break;
0623             }
0624             break;
0625 
0626         case is_uint:   cmp = lhs.value.ui > as_ulong(rhs); break;
0627         case is_bool:   cmp = lhs.value.b > as_bool(rhs); break;
0628         }
0629         return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
0630     }
0631     friend closure_value
0632     operator< (closure_value const &lhs, closure_value const &rhs)
0633     {
0634         bool cmp = false;
0635         switch (lhs.type) {
0636         case is_int:
0637             switch(rhs.type) {
0638             case is_bool:   cmp = lhs.value.i < as_long(rhs); break;
0639             case is_int:    cmp = lhs.value.i < rhs.value.i; break;
0640             case is_uint:   cmp = lhs.value.ui < rhs.value.ui; break;
0641             }
0642             break;
0643 
0644         case is_uint:   cmp = lhs.value.ui < as_ulong(rhs); break;
0645         case is_bool:   cmp = as_bool(lhs) < as_bool(rhs); break;
0646         }
0647         return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
0648     }
0649     friend closure_value
0650     operator<= (closure_value const &lhs, closure_value const &rhs)
0651     {
0652         return closure_value(!as_bool(lhs > rhs), (value_error)(lhs.valid | rhs.valid));
0653     }
0654     friend closure_value
0655     operator>= (closure_value const &lhs, closure_value const &rhs)
0656     {
0657         return closure_value(!as_bool(lhs < rhs), (value_error)(lhs.valid | rhs.valid));
0658     }
0659 
0660     closure_value &
0661     operator<<= (closure_value const &rhs)
0662     {
0663         switch (type) {
0664         case is_bool:
0665         case is_int:
0666             switch (rhs.type) {
0667             case is_bool:
0668             case is_int:
0669                 {
0670                 int_literal_type shift_by = as_long(rhs);
0671 
0672                     if (shift_by > 64)
0673                         shift_by = 64;
0674                     else if (shift_by < -64)
0675                         shift_by = -64;
0676                     value.i <<= shift_by;
0677                 }
0678                 break;
0679 
0680             case is_uint:
0681                 {
0682                 uint_literal_type shift_by = as_ulong(rhs);
0683 
0684                     if (shift_by > 64)
0685                         shift_by = 64;
0686                     value.ui <<= shift_by;
0687 
0688                 // Note: The usual arithmetic conversions are not performed on
0689                 //       bit shift operations.
0690                 }
0691                 break;
0692             }
0693             break;
0694 
0695         case is_uint:
0696             switch (rhs.type) {
0697             case is_bool:
0698             case is_int:
0699                 {
0700                 int_literal_type shift_by = as_long(rhs);
0701 
0702                     if (shift_by > 64)
0703                         shift_by = 64;
0704                     else if (shift_by < -64)
0705                         shift_by = -64;
0706                     value.ui <<= shift_by;
0707                 }
0708                 break;
0709 
0710             case is_uint:
0711                 {
0712                 uint_literal_type shift_by = as_ulong(rhs);
0713 
0714                     if (shift_by > 64)
0715                         shift_by = 64;
0716                     value.ui <<= shift_by;
0717                 }
0718                 break;
0719             }
0720         }
0721         valid = (value_error)(valid | rhs.valid);
0722         return *this;
0723     }
0724 
0725     closure_value &
0726     operator>>= (closure_value const &rhs)
0727     {
0728         switch (type) {
0729         case is_bool:
0730         case is_int:
0731             switch (rhs.type) {
0732             case is_bool:
0733             case is_int:
0734                 {
0735                 int_literal_type shift_by = as_long(rhs);
0736 
0737                     if (shift_by > 64)
0738                         shift_by = 64;
0739                     else if (shift_by < -64)
0740                         shift_by = -64;
0741                     value.i >>= shift_by;
0742                 }
0743                 break;
0744 
0745             case is_uint:
0746                 {
0747                 uint_literal_type shift_by = as_ulong(rhs);
0748 
0749                     if (shift_by > 64)
0750                         shift_by = 64;
0751                     value.ui >>= shift_by;
0752 
0753                 // Note: The usual arithmetic conversions are not performed on
0754                 //       bit shift operations.
0755                 }
0756                 break;
0757             }
0758             break;
0759 
0760         case is_uint:
0761             switch (rhs.type) {
0762             case is_bool:
0763             case is_int:
0764                 {
0765                 int_literal_type shift_by = as_long(rhs);
0766 
0767                     if (shift_by > 64)
0768                         shift_by = 64;
0769                     else if (shift_by < -64)
0770                         shift_by = -64;
0771                     value.ui >>= shift_by;
0772                 }
0773                 break;
0774 
0775             case is_uint:
0776                 {
0777                 uint_literal_type shift_by = as_ulong(rhs);
0778 
0779                     if (shift_by > 64)
0780                         shift_by = 64;
0781                     value.ui >>= shift_by;
0782                 }
0783                 break;
0784             }
0785             break;
0786         }
0787         valid = (value_error)(valid | rhs.valid);
0788         return *this;
0789     }
0790 
0791     friend closure_value
0792     operator|| (closure_value const &lhs, closure_value const &rhs)
0793     {
0794         bool result = as_bool(lhs) || as_bool(rhs);
0795         return closure_value(result, (value_error)(lhs.valid | rhs.valid));
0796     }
0797 
0798     friend closure_value
0799     operator&& (closure_value const &lhs, closure_value const &rhs)
0800     {
0801         bool result = as_bool(lhs) && as_bool(rhs);
0802         return closure_value(result, (value_error)(lhs.valid | rhs.valid));
0803     }
0804 
0805     friend closure_value
0806     operator| (closure_value const &lhs, closure_value const &rhs)
0807     {
0808         uint_literal_type result = as_ulong(lhs) | as_ulong(rhs);
0809         return closure_value(result, (value_error)(lhs.valid | rhs.valid));
0810     }
0811 
0812     friend closure_value
0813     operator& (closure_value const &lhs, closure_value const &rhs)
0814     {
0815         uint_literal_type result = as_ulong(lhs) & as_ulong(rhs);
0816         return closure_value(result, (value_error)(lhs.valid | rhs.valid));
0817     }
0818 
0819     friend closure_value
0820     operator^ (closure_value const &lhs, closure_value const &rhs)
0821     {
0822         uint_literal_type result = as_ulong(lhs) ^ as_ulong(rhs);
0823         return closure_value(result, (value_error)(lhs.valid | rhs.valid));
0824     }
0825 
0826     // handle the ?: operator
0827     closure_value &
0828     handle_questionmark(closure_value const &cond, closure_value const &val2)
0829     {
0830         switch (type) {
0831         case is_int:
0832             switch (val2.type) {
0833             case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break;
0834             case is_int:  value.i = as_bool(cond) ? value.i : as_long(val2); break;
0835             case is_uint:
0836                 value.ui = as_bool(cond) ? value.ui : as_ulong(val2);
0837                 type = is_uint;   // changing type!
0838                 break;
0839             }
0840             break;
0841 
0842         case is_uint:   value.ui = as_bool(cond) ? value.ui : as_ulong(val2); break;
0843         case is_bool:   value.b = as_bool(cond) ? value.b : as_bool(val2); break;
0844         }
0845         valid = as_bool(cond) ? valid : val2.valid;
0846         return *this;
0847     }
0848 
0849 #if defined (BOOST_SPIRIT_DEBUG)
0850     friend std::ostream&
0851     operator<< (std::ostream &o, closure_value const &val)
0852     {
0853         switch (val.type) {
0854         case is_int:    o << "int(" << as_long(val) << ")"; break;
0855         case is_uint:   o << "unsigned int(" << as_ulong(val) << ")"; break;
0856         case is_bool:   o << "bool(" << as_bool(val) << ")"; break;
0857         }
0858         return o;
0859     }
0860 #endif // defined(BOOST_SPIRIT_DEBUG)
0861 
0862 private:
0863     value_type type;
0864     union {
0865         int_literal_type i;
0866         uint_literal_type ui;
0867         bool b;
0868     } value;
0869     value_error valid;
0870 };
0871 
0872 ///////////////////////////////////////////////////////////////////////////////
0873 }   // namespace closures
0874 }   // namespace grammars
0875 }   // namespace wave
0876 }   // namespace boost
0877 
0878 // the suffix header occurs after all of the code
0879 #ifdef BOOST_HAS_ABI_HEADERS
0880 #include BOOST_ABI_SUFFIX
0881 #endif
0882 
0883 #endif // !defined(BOOST_CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED)