Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/wave/grammars/cpp_expression_value.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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(CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED) | |
12 #define 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 | |
53 closure_value(value_error valid_ = error_noerror) | |
54 : type(is_int), valid(valid_) | |
55 { value.i = 0; } | |
56 explicit closure_value(int i, value_error valid_ = error_noerror) | |
57 : type(is_int), valid(valid_) | |
58 { value.i = i; } | |
59 explicit closure_value(unsigned int ui, value_error valid_ = error_noerror) | |
60 : type(is_uint), valid(valid_) | |
61 { value.ui = ui; } | |
62 explicit closure_value(int_literal_type i, value_error valid_ = error_noerror) | |
63 : type(is_int), valid(valid_) | |
64 { value.i = i; } | |
65 explicit closure_value(uint_literal_type ui, value_error valid_ = error_noerror) | |
66 : type(is_uint), valid(valid_) | |
67 { value.ui = ui; } | |
68 explicit closure_value(bool b, value_error valid_ = error_noerror) | |
69 : type(is_bool), valid(valid_) | |
70 { value.b = b; } | |
71 | |
72 value_type get_type() const { return type; } | |
73 value_error is_valid() const { return valid; } | |
74 | |
75 // explicit conversion | |
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 } | |
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 } | |
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 } | |
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 } | |
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 | |
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 } | |
144 closure_value &operator= (int rhs) | |
145 { | |
146 type = is_int; | |
147 value.i = rhs; | |
148 valid = error_noerror; | |
149 return *this; | |
150 } | |
151 closure_value &operator= (unsigned int rhs) | |
152 { | |
153 type = is_uint; | |
154 value.ui = rhs; | |
155 valid = error_noerror; | |
156 return *this; | |
157 } | |
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 } | |
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 } | |
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 | |
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 } | |
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 } | |
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 } | |
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 } | |
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 | |
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 | |
574 operator~ (closure_value const &rhs) | |
575 { | |
576 return closure_value(~as_ulong(rhs), rhs.valid); | |
577 } | |
578 friend closure_value | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 & | |
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 & | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 & | |
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& | |
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(CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED) |