@@ -9,19 +9,21 @@ Author: Daniel Kroening, kroening@kroening.com
9
9
// / \file
10
10
// / Expression Representation
11
11
12
+ #include " arith_tools.h"
12
13
#include " expr.h"
13
- #include < cassert>
14
- #include < stack>
15
- #include " string2int.h"
16
- #include " mp_arith.h"
14
+ #include " expr_iterator.h"
17
15
#include " fixedbv.h"
18
16
#include " ieee_float.h"
19
17
#include " invariant.h"
20
- #include " expr_iterator .h"
18
+ #include " mp_arith .h"
21
19
#include " rational.h"
22
20
#include " rational_tools.h"
23
- #include " arith_tools.h"
24
21
#include " std_expr.h"
22
+ #include " string2int.h"
23
+
24
+ #include < cassert>
25
+ #include < stack>
26
+ #include < ostream>
25
27
26
28
void exprt::move_to_operands (exprt &expr)
27
29
{
@@ -535,3 +537,182 @@ const_unique_depth_iteratort exprt::unique_depth_cbegin() const
535
537
{ return const_unique_depth_iteratort (*this ); }
536
538
const_unique_depth_iteratort exprt::unique_depth_cend () const
537
539
{ return const_unique_depth_iteratort (); }
540
+
541
+ // / We use the precendences that most readers expect
542
+ // / (i.e., the ones you learn in primary school),
543
+ // / and stay clear of the surprising ones that C has.
544
+ static bool bracket_subexpression (const exprt &sub_expr, const exprt &expr)
545
+ {
546
+ // no need for parentheses whenever the subexpression
547
+ // doesn't have operands
548
+ if (!sub_expr.has_operands ())
549
+ return false ;
550
+
551
+ // * and / bind stronger than + and -
552
+ if (
553
+ (sub_expr.id () == ID_mult || sub_expr.id () == ID_div) &&
554
+ (expr.id () == ID_plus || expr.id () == ID_minus))
555
+ return false ;
556
+
557
+ // ==, !=, <, <=, >, >= bind stronger than && and ||
558
+ if (
559
+ (sub_expr.id () == ID_equal || sub_expr.id () == ID_notequal ||
560
+ sub_expr.id () == ID_lt || sub_expr.id () == ID_gt ||
561
+ sub_expr.id () == ID_le || sub_expr.id () == ID_ge) &&
562
+ (expr.id () == ID_and || expr.id () == ID_or))
563
+ return false ;
564
+
565
+ return true ;
566
+ }
567
+
568
+ // / This formats turns a multi-ary expression,
569
+ // / adding parentheses where indicated by the precedence.
570
+ static std::ostream &format_rec (std::ostream &os, const multi_ary_exprt &src)
571
+ {
572
+ bool first = true ;
573
+
574
+ for (const auto &op : src.operands ())
575
+ {
576
+ if (first)
577
+ first = false ;
578
+ else
579
+ os << ' ' << src.id () << ' ' ;
580
+
581
+ const bool need_parentheses = bracket_subexpression (op, src);
582
+
583
+ if (need_parentheses)
584
+ os << ' (' ;
585
+
586
+ os << format (op);
587
+
588
+ if (need_parentheses)
589
+ os << ' )' ;
590
+ }
591
+
592
+ return os;
593
+ }
594
+
595
+ // / This formats a binary expression
596
+ static std::ostream &format_rec (std::ostream &os, const binary_exprt &src)
597
+ {
598
+ return format_rec (os, to_multi_ary_expr (src));
599
+ }
600
+
601
+ // / This formats a unary expression,
602
+ // / adding parentheses very aggressively.
603
+ static std::ostream &format_rec (std::ostream &os, const unary_exprt &src)
604
+ {
605
+ if (src.id () == ID_not)
606
+ os << ' !' ;
607
+ else if (src.id () == ID_unary_minus)
608
+ os << ' -' ;
609
+ else
610
+ return os << src.pretty ();
611
+
612
+ if (src.op0 ().has_operands ())
613
+ return os << ' (' << format (src.op0 ()) << ' )' ;
614
+ else
615
+ return os << format (src.op0 ());
616
+ }
617
+
618
+ static std::ostream &format_rec (std::ostream &os, const constant_exprt &src)
619
+ {
620
+ auto type = src.type ().id ();
621
+
622
+ if (type == ID_bool)
623
+ {
624
+ if (src.is_true ())
625
+ return os << " true" ;
626
+ else if (src.is_false ())
627
+ return os << " false" ;
628
+ else
629
+ return os << src.pretty ();
630
+ }
631
+ else if (type == ID_unsignedbv || type == ID_signedbv)
632
+ return os << *numeric_cast<mp_integer>(src);
633
+ else if (type == ID_integer)
634
+ return os << src.get_value ();
635
+ else if (type == ID_floatbv)
636
+ return os << ieee_floatt (src);
637
+ else
638
+ return os << src.pretty ();
639
+ }
640
+
641
+ // The below generates a string in a generic syntax
642
+ // that is inspired by C/C++/Java, and is meant for debugging
643
+ // purposes.
644
+ std::ostream &format_rec (std::ostream &os, const exprt &expr)
645
+ {
646
+ const auto &id = expr.id ();
647
+
648
+ if (id == ID_plus || id == ID_mult || id == ID_and || id == ID_or)
649
+ return format_rec (os, to_multi_ary_expr (expr));
650
+ else if (
651
+ id == ID_lt || id == ID_gt || id == ID_ge || id == ID_le ||
652
+ id == ID_minus || id == ID_implies || id == ID_equal || id == ID_notequal)
653
+ return format_rec (os, to_binary_expr (expr));
654
+ else if (id == ID_not || id == ID_unary_minus)
655
+ return format_rec (os, to_unary_expr (expr));
656
+ else if (id == ID_constant)
657
+ return format_rec (os, to_constant_expr (expr));
658
+ else if (id == ID_typecast)
659
+ return os << " cast(" << format (to_typecast_expr (expr).op ()) << " , "
660
+ << format (expr.type ()) << ' )' ;
661
+ else if (id == ID_member)
662
+ return os << format (to_member_expr (expr).op ()) << ' .'
663
+ << to_member_expr (expr).get_component_name ();
664
+ else if (id == ID_symbol)
665
+ return os << to_symbol_expr (expr).get_identifier ();
666
+ else if (id == ID_forall || id == ID_exists)
667
+ return os << id << ' ' << format (to_quantifier_expr (expr).symbol ()) << " : "
668
+ << format (to_quantifier_expr (expr).symbol ().type ()) << " . "
669
+ << format (to_quantifier_expr (expr).where ());
670
+ else if (id == ID_let)
671
+ return os << " LET " << format (to_let_expr (expr).symbol ()) << " = "
672
+ << format (to_let_expr (expr).value ()) << " IN "
673
+ << format (to_let_expr (expr).where ());
674
+ else if (id == ID_array || id == ID_struct)
675
+ {
676
+ os << " { " ;
677
+
678
+ bool first = true ;
679
+
680
+ for (const auto &op : expr.operands ())
681
+ {
682
+ if (first)
683
+ first = false ;
684
+ else
685
+ os << " , " ;
686
+
687
+ os << format (op);
688
+ }
689
+
690
+ return os << ' }' ;
691
+ }
692
+ else if (id == ID_if)
693
+ {
694
+ const auto &if_expr = to_if_expr (expr);
695
+ return os << format (if_expr.cond ()) << ' ?' << format (if_expr.true_case ())
696
+ << ' :' << format (if_expr.false_case ());
697
+ }
698
+ else
699
+ {
700
+ if (!expr.has_operands ())
701
+ return os << id;
702
+
703
+ os << id << ' (' ;
704
+ bool first = true ;
705
+
706
+ for (const auto &op : expr.operands ())
707
+ {
708
+ if (first)
709
+ first = false ;
710
+ else
711
+ os << " , " ;
712
+
713
+ os << format (op);
714
+ }
715
+
716
+ return os << ' )' ;
717
+ }
718
+ }
0 commit comments