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