CBMC
Loading...
Searching...
No Matches
smt2_parser.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
9#include "smt2_parser.h"
10
11#include "smt2_format.h"
12
13#include <util/arith_tools.h>
14#include <util/bitvector_expr.h>
16#include <util/floatbv_expr.h>
17#include <util/ieee_float.h>
18#include <util/invariant.h>
20#include <util/prefix.h>
21#include <util/range.h>
22
23#include <numeric>
24
26{
27 const auto token = smt2_tokenizer.next_token();
28
29 if(token == smt2_tokenizert::OPEN)
31 else if(token == smt2_tokenizert::CLOSE)
33
34 return token;
35}
36
38{
39 while(parenthesis_level > 0)
40 if(next_token() == smt2_tokenizert::END_OF_FILE)
41 return;
42}
43
45{
46 exit=false;
47
48 while(!exit)
49 {
50 if(smt2_tokenizer.peek() == smt2_tokenizert::END_OF_FILE)
51 {
52 exit = true;
53 return;
54 }
55
56 if(next_token() != smt2_tokenizert::OPEN)
57 throw error("command must start with '('");
58
59 if(next_token() != smt2_tokenizert::SYMBOL)
60 {
62 throw error("expected symbol as command");
63 }
64
66
67 switch(next_token())
68 {
69 case smt2_tokenizert::END_OF_FILE:
70 throw error(
71 "expected closing parenthesis at end of command,"
72 " but got EOF");
73
74 case smt2_tokenizert::CLOSE:
75 // what we expect
76 break;
77
78 case smt2_tokenizert::OPEN:
79 case smt2_tokenizert::SYMBOL:
80 case smt2_tokenizert::NUMERAL:
81 case smt2_tokenizert::STRING_LITERAL:
82 case smt2_tokenizert::NONE:
83 case smt2_tokenizert::KEYWORD:
84 throw error("expected ')' at end of command");
85 }
86 }
87}
88
90{
91 std::size_t parentheses=0;
92 while(true)
93 {
94 switch(smt2_tokenizer.peek())
95 {
96 case smt2_tokenizert::OPEN:
97 next_token();
99 break;
100
101 case smt2_tokenizert::CLOSE:
102 if(parentheses==0)
103 return; // done
104
105 next_token();
106 parentheses--;
107 break;
108
109 case smt2_tokenizert::END_OF_FILE:
110 throw error("unexpected EOF in command");
111
112 case smt2_tokenizert::SYMBOL:
113 case smt2_tokenizert::NUMERAL:
114 case smt2_tokenizert::STRING_LITERAL:
115 case smt2_tokenizert::NONE:
116 case smt2_tokenizert::KEYWORD:
117 next_token();
118 }
119 }
120}
121
123{
124 exprt::operandst result;
125
126 while(smt2_tokenizer.peek() != smt2_tokenizert::CLOSE)
127 result.push_back(expression());
128
129 next_token(); // eat the ')'
130
131 return result;
132}
133
135{
136 if(!id_map
137 .emplace(
138 std::piecewise_construct,
139 std::forward_as_tuple(id),
140 std::forward_as_tuple(idt::VARIABLE, std::move(expr)))
141 .second)
142 {
143 // id already used
144 throw error() << "identifier '" << id << "' defined twice";
145 }
146}
147
149{
150 if(next_token() != smt2_tokenizert::OPEN)
151 throw error("expected bindings after let");
152
153 std::vector<std::pair<irep_idt, exprt>> bindings;
154
155 while(smt2_tokenizer.peek() == smt2_tokenizert::OPEN)
156 {
157 next_token();
158
159 if(next_token() != smt2_tokenizert::SYMBOL)
160 throw error("expected symbol in binding");
161
162 irep_idt identifier = smt2_tokenizer.get_buffer();
163
164 // note that the previous bindings are _not_ visible yet
165 exprt value=expression();
166
167 if(next_token() != smt2_tokenizert::CLOSE)
168 throw error("expected ')' after value in binding");
169
170 bindings.push_back(
171 std::pair<irep_idt, exprt>(identifier, value));
172 }
173
174 if(next_token() != smt2_tokenizert::CLOSE)
175 throw error("expected ')' at end of bindings");
176
177 // we may hide identifiers in outer scopes
178 std::vector<std::pair<irep_idt, idt>> saved_ids;
179
180 // add the bindings to the id_map
181 for(auto &b : bindings)
182 {
183 auto insert_result = id_map.insert({b.first, idt{idt::BINDING, b.second}});
184 if(!insert_result.second) // already there
185 {
186 auto &id_entry = *insert_result.first;
187 saved_ids.emplace_back(id_entry.first, std::move(id_entry.second));
188 id_entry.second = idt{idt::BINDING, b.second};
189 }
190 }
191
192 // now parse, with bindings in place
193 exprt where = expression();
194
195 if(next_token() != smt2_tokenizert::CLOSE)
196 throw error("expected ')' after let");
197
199 exprt::operandst values;
200
201 for(const auto &b : bindings)
202 {
203 variables.push_back(symbol_exprt(b.first, b.second.type()));
204 values.push_back(b.second);
205 }
206
207 // delete the bindings from the id_map
208 for(const auto &binding : bindings)
209 id_map.erase(binding.first);
210
211 // restore any previous ids
212 for(auto &saved_id : saved_ids)
213 id_map.insert(std::move(saved_id));
214
215 return let_exprt(variables, values, where);
216}
217
218std::pair<binding_exprt::variablest, exprt> smt2_parsert::binding(irep_idt id)
219{
220 if(next_token() != smt2_tokenizert::OPEN)
221 throw error() << "expected bindings after " << id;
222
224
225 while(smt2_tokenizer.peek() == smt2_tokenizert::OPEN)
226 {
227 next_token();
228
229 if(next_token() != smt2_tokenizert::SYMBOL)
230 throw error("expected symbol in binding");
231
232 irep_idt identifier = smt2_tokenizer.get_buffer();
233
234 typet type=sort();
235
236 if(next_token() != smt2_tokenizert::CLOSE)
237 throw error("expected ')' after sort in binding");
238
239 bindings.push_back(symbol_exprt(identifier, type));
240 }
241
242 if(next_token() != smt2_tokenizert::CLOSE)
243 throw error("expected ')' at end of bindings");
244
245 // we may hide identifiers in outer scopes
246 std::vector<std::pair<irep_idt, idt>> saved_ids;
247
248 // add the bindings to the id_map
249 for(auto &b : bindings)
250 {
251 auto insert_result =
252 id_map.insert({b.get_identifier(), idt{idt::BINDING, b.type()}});
253 if(!insert_result.second) // already there
254 {
255 auto &id_entry = *insert_result.first;
256 saved_ids.emplace_back(id_entry.first, std::move(id_entry.second));
257 id_entry.second = idt{idt::BINDING, b.type()};
258 }
259 }
260
261 // now parse, with bindings in place
262 exprt expr=expression();
263
264 if(next_token() != smt2_tokenizert::CLOSE)
265 throw error() << "expected ')' after " << id;
266
267 // remove bindings from id_map
268 for(const auto &b : bindings)
269 id_map.erase(b.get_identifier());
270
271 // restore any previous ids
272 for(auto &saved_id : saved_ids)
273 id_map.insert(std::move(saved_id));
274
275 return {std::move(bindings), std::move(expr)};
276}
277
279{
280 auto binding = this->binding(ID_lambda);
281 return lambda_exprt(binding.first, binding.second);
282}
283
285{
286 auto binding = this->binding(id);
287
288 if(!binding.second.is_boolean())
289 throw error() << id << " expects a boolean term";
290
291 return quantifier_exprt(id, binding.first, binding.second);
292}
293
295 const symbol_exprt &function,
296 const exprt::operandst &op)
297{
298 const auto &function_type = to_mathematical_function_type(function.type());
299
300 // check the arguments
301 if(op.size() != function_type.domain().size())
302 throw error("wrong number of arguments for function");
303
304 for(std::size_t i=0; i<op.size(); i++)
305 {
306 if(op[i].type() != function_type.domain()[i])
307 throw error("wrong type for arguments for function");
308 }
309
310 return function_application_exprt(function, op);
311}
312
314{
315 exprt::operandst result = op;
316
317 for(auto &expr : result)
318 {
319 if(expr.type().id() == ID_signedbv) // no need to cast
320 {
321 }
322 else if(expr.type().id() != ID_unsignedbv)
323 {
324 throw error("expected unsigned bitvector");
325 }
326 else
327 {
328 const auto width = to_unsignedbv_type(expr.type()).get_width();
329 expr = typecast_exprt(expr, signedbv_typet(width));
330 }
331 }
332
333 return result;
334}
335
337{
338 if(expr.type().id()==ID_unsignedbv) // no need to cast
339 return expr;
340
341 if(expr.type().id()!=ID_signedbv)
342 throw error("expected signed bitvector");
343
344 const auto width=to_signedbv_type(expr.type()).get_width();
345 return typecast_exprt(expr, unsignedbv_typet(width));
346}
347
349 const exprt::operandst &op) const
350{
351 for(std::size_t i = 1; i < op.size(); i++)
352 {
353 if(op[i].type() != op[0].type())
354 {
355 throw error() << "expression must have operands with matching types,"
356 " but got '"
357 << smt2_format(op[0].type()) << "' and '"
358 << smt2_format(op[i].type()) << '\'';
359 }
360 }
361}
362
364{
365 if(op.empty())
366 throw error("expression must have at least one operand");
367
369
370 exprt result(id, op[0].type());
371 result.operands() = op;
372 return result;
373}
374
376{
377 if(op.size()!=2)
378 throw error("expression must have two operands");
379
381
382 return binary_predicate_exprt(op[0], id, op[1]);
383}
384
386{
387 if(op.size()!=1)
388 throw error("expression must have one operand");
389
390 return unary_exprt(id, op[0], op[0].type());
391}
392
394{
395 if(op.size()!=2)
396 throw error("expression must have two operands");
397
399
400 return binary_exprt(op[0], id, op[1], op[0].type());
401}
402
404 const exprt::operandst &op)
405{
406 if(op.size() != 2)
407 throw error() << "FloatingPoint equality takes two operands";
408
409 if(op[0].type().id() != ID_floatbv || op[1].type().id() != ID_floatbv)
410 throw error() << "FloatingPoint equality takes FloatingPoint operands";
411
412 if(op[0].type() != op[1].type())
413 {
414 throw error() << "FloatingPoint equality takes FloatingPoint operands with "
415 << "matching sort, but got " << smt2_format(op[0].type())
416 << " vs " << smt2_format(op[1].type());
417 }
418
419 return ieee_float_equal_exprt(op[0], op[1]);
420}
421
423 const irep_idt &id,
424 const exprt::operandst &op)
425{
426 if(op.size() != 3)
427 throw error() << id << " takes three operands";
428
429 if(op[1].type().id() != ID_floatbv || op[2].type().id() != ID_floatbv)
430 throw error() << id << " takes FloatingPoint operands";
431
432 if(op[1].type() != op[2].type())
433 {
434 throw error() << id << " takes FloatingPoint operands with matching sort, "
435 << "but got " << smt2_format(op[1].type()) << " vs "
436 << smt2_format(op[2].type());
437 }
438
439 // clang-format off
440 const irep_idt expr_id =
441 id == "fp.add" ? ID_floatbv_plus :
442 id == "fp.sub" ? ID_floatbv_minus :
443 id == "fp.mul" ? ID_floatbv_mult :
444 id == "fp.div" ? ID_floatbv_div :
445 throw error("unsupported floating-point operation");
446 // clang-format on
447
448 return ieee_float_op_exprt(op[1], expr_id, op[2], op[0]);
449}
450
452{
453 // floating-point from bit-vectors
454 if(op.size() != 3)
455 throw error("fp takes three operands");
456
457 if(op[0].type().id() != ID_unsignedbv)
458 throw error("fp takes BitVec as first operand");
459
460 if(op[1].type().id() != ID_unsignedbv)
461 throw error("fp takes BitVec as second operand");
462
463 if(op[2].type().id() != ID_unsignedbv)
464 throw error("fp takes BitVec as third operand");
465
466 if(to_unsignedbv_type(op[0].type()).get_width() != 1)
467 throw error("fp takes BitVec of size 1 as first operand");
468
469 const auto width_e = to_unsignedbv_type(op[1].type()).get_width();
470 const auto width_f = to_unsignedbv_type(op[2].type()).get_width();
471
472 // stitch the bits together
473 const auto concat_type = unsignedbv_typet(width_f + width_e + 1);
474
475 // We need a bitvector type without numerical interpretation
476 // to do this conversion.
477 const auto bv_type = bv_typet(concat_type.get_width());
478
479 // The target type
481
482 return typecast_exprt(
485 fp_type);
486}
487
489{
490 switch(next_token())
491 {
492 case smt2_tokenizert::SYMBOL:
493 if(smt2_tokenizer.get_buffer() == "_") // indexed identifier
494 {
495 // indexed identifier
496 if(next_token() != smt2_tokenizert::SYMBOL)
497 throw error("expected symbol after '_'");
498
499 // copy, the reference won't be stable
500 const auto id = smt2_tokenizer.get_buffer();
501
502 if(has_prefix(id, "bv"))
503 {
505 std::string(smt2_tokenizer.get_buffer(), 2, std::string::npos));
506
507 if(next_token() != smt2_tokenizert::NUMERAL)
508 throw error("expected numeral as bitvector literal width");
509
510 auto width = std::stoll(smt2_tokenizer.get_buffer());
511
512 if(next_token() != smt2_tokenizert::CLOSE)
513 throw error("expected ')' after bitvector literal");
514
515 return from_integer(i, unsignedbv_typet(width));
516 }
517 else if(id == "+oo" || id == "-oo" || id == "NaN")
518 {
519 // These are the "plus infinity", "minus infinity" and NaN
520 // floating-point literals.
521 if(next_token() != smt2_tokenizert::NUMERAL)
522 throw error() << "expected number after " << id;
523
524 auto width_e = std::stoll(smt2_tokenizer.get_buffer());
525
526 if(next_token() != smt2_tokenizert::NUMERAL)
527 throw error() << "expected second number after " << id;
528
529 auto width_f = std::stoll(smt2_tokenizer.get_buffer());
530
531 if(next_token() != smt2_tokenizert::CLOSE)
532 throw error() << "expected ')' after " << id;
533
534 // width_f *includes* the hidden bit
535 const ieee_float_spect spec(width_f - 1, width_e);
536
537 if(id == "+oo")
538 return ieee_floatt::plus_infinity(spec).to_expr();
539 else if(id == "-oo")
540 return ieee_floatt::minus_infinity(spec).to_expr();
541 else // NaN
542 return ieee_floatt::NaN(spec).to_expr();
543 }
544 else
545 {
546 throw error() << "unknown indexed identifier " << id;
547 }
548 }
549 else if(smt2_tokenizer.get_buffer() == "!")
550 {
551 // these are "term attributes"
552 const auto term = expression();
553
554 while(smt2_tokenizer.peek() == smt2_tokenizert::KEYWORD)
555 {
556 next_token(); // eat the keyword
557 if(smt2_tokenizer.get_buffer() == "named")
558 {
559 // 'named terms' must be Boolean
560 if(!term.is_boolean())
561 throw error("named terms must be Boolean");
562
563 if(next_token() == smt2_tokenizert::SYMBOL)
564 {
565 const symbol_exprt symbol_expr(
567 named_terms.emplace(
568 symbol_expr.get_identifier(), named_termt(term, symbol_expr));
569 }
570 else
571 throw error("invalid name attribute, expected symbol");
572 }
573 else
574 throw error("unknown term attribute");
575 }
576
577 if(next_token() != smt2_tokenizert::CLOSE)
578 throw error("expected ')' at end of term attribute");
579 else
580 return term;
581 }
582 else
583 {
584 // non-indexed symbol, look up in expression table
585 const auto id = smt2_tokenizer.get_buffer();
586 const auto e_it = expressions.find(id);
587 if(e_it != expressions.end())
588 return e_it->second();
589
590 // get the operands
591 auto op = operands();
592
593 // rummage through id_map
594 auto id_it = id_map.find(id);
595 if(id_it != id_map.end())
596 {
597 if(id_it->second.type.id() == ID_mathematical_function)
598 {
599 return function_application(symbol_exprt(id, id_it->second.type), op);
600 }
601 else
602 return symbol_exprt(id, id_it->second.type);
603 }
604 else
605 throw error() << "unknown function symbol '" << id << '\'';
606 }
607 break;
608
609 case smt2_tokenizert::OPEN: // likely indexed identifier
610 if(smt2_tokenizer.peek() == smt2_tokenizert::SYMBOL)
611 {
612 next_token(); // eat symbol
613 if(smt2_tokenizer.get_buffer() == "_")
614 {
615 // indexed identifier
616 if(next_token() != smt2_tokenizert::SYMBOL)
617 throw error("expected symbol after '_'");
618
619 irep_idt id = smt2_tokenizer.get_buffer(); // hash it
620
621 if(id=="extract")
622 {
623 if(next_token() != smt2_tokenizert::NUMERAL)
624 throw error("expected numeral after extract");
625
626 auto upper = std::stoll(smt2_tokenizer.get_buffer());
627
628 if(next_token() != smt2_tokenizert::NUMERAL)
629 throw error("expected two numerals after extract");
630
631 auto lower = std::stoll(smt2_tokenizer.get_buffer());
632
633 if(next_token() != smt2_tokenizert::CLOSE)
634 throw error("expected ')' after extract");
635
636 auto op=operands();
637
638 if(op.size()!=1)
639 throw error("extract takes one operand");
640
641 if(upper<lower)
642 throw error("extract got bad indices");
643
644 auto lower_e = from_integer(lower, integer_typet());
645
646 unsignedbv_typet t(upper-lower+1);
647
648 return extractbits_exprt(op[0], lower_e, t);
649 }
650 else if(id=="rotate_left" ||
651 id=="rotate_right" ||
652 id == ID_repeat ||
653 id=="sign_extend" ||
654 id=="zero_extend")
655 {
656 if(next_token() != smt2_tokenizert::NUMERAL)
657 throw error() << "expected numeral after " << id;
658
660
661 if(next_token() != smt2_tokenizert::CLOSE)
662 throw error() << "expected ')' after " << id << " index";
663
664 auto op=operands();
665
666 if(op.size()!=1)
667 throw error() << id << " takes one operand";
668
669 if(id=="rotate_left")
670 {
671 auto dist=from_integer(index, integer_typet());
672 return binary_exprt(op[0], ID_rol, dist, op[0].type());
673 }
674 else if(id=="rotate_right")
675 {
676 auto dist=from_integer(index, integer_typet());
677 return binary_exprt(op[0], ID_ror, dist, op[0].type());
678 }
679 else if(id=="sign_extend")
680 {
681 // we first convert to a signed type of the original width,
682 // then extend to the new width, and then go to unsigned
683 const auto width = to_unsignedbv_type(op[0].type()).get_width();
685 const signedbv_typet large_signed_type{width + index};
686 const unsignedbv_typet unsigned_type{width + index};
687
688 return typecast_exprt(
692 }
693 else if(id == ID_zero_extend)
694 {
695 auto width=to_unsignedbv_type(op[0].type()).get_width();
696 unsignedbv_typet unsigned_type{width + index};
697
698 return zero_extend_exprt{op[0], unsigned_type};
699 }
700 else if(id == ID_repeat)
701 {
702 auto i = from_integer(index, integer_typet());
703 auto width = to_unsignedbv_type(op[0].type()).get_width() * index;
704 return replication_exprt(i, op[0], unsignedbv_typet(width));
705 }
706 else
707 return nil_exprt();
708 }
709 else if(id == "to_fp")
710 {
711 if(next_token() != smt2_tokenizert::NUMERAL)
712 throw error("expected number after to_fp");
713
714 auto width_e = std::stoll(smt2_tokenizer.get_buffer());
715
716 if(next_token() != smt2_tokenizert::NUMERAL)
717 throw error("expected second number after to_fp");
718
719 auto width_f = std::stoll(smt2_tokenizer.get_buffer());
720
721 if(next_token() != smt2_tokenizert::CLOSE)
722 throw error("expected ')' after to_fp");
723
724 // width_f *includes* the hidden bit
725 const ieee_float_spect spec(width_f - 1, width_e);
726
727 auto rounding_mode = expression();
728
729 auto source_op = expression();
730
731 if(next_token() != smt2_tokenizert::CLOSE)
732 throw error("expected ')' at the end of to_fp");
733
734 // There are several options for the source operand:
735 // 1) real or integer
736 // 2) bit-vector, which is interpreted as signed 2's complement
737 // 3) another floating-point format
738 if(
739 source_op.type().id() == ID_real ||
740 source_op.type().id() == ID_integer)
741 {
742 // For now, we can only do this when
743 // the source operand is a constant.
744 if(source_op.is_constant())
745 {
746 mp_integer significand, exponent;
747
748 const auto &real_number =
750 auto dot_pos = real_number.find('.');
751 if(dot_pos == std::string::npos)
752 {
753 exponent = 0;
754 significand = string2integer(real_number);
755 }
756 else
757 {
758 // remove the '.'
759 std::string significand_str;
760 significand_str.reserve(real_number.size());
761 for(auto ch : real_number)
762 {
763 if(ch != '.')
765 }
766
767 exponent =
769 significand = string2integer(significand_str);
770 }
771
773 spec,
774 static_cast<ieee_floatt::rounding_modet>(
775 numeric_cast_v<int>(to_constant_expr(rounding_mode))));
776 a.from_base10(significand, exponent);
777 return a.to_expr();
778 }
779 else
780 throw error()
781 << "to_fp for non-constant real expressions is not implemented";
782 }
783 else if(source_op.type().id() == ID_unsignedbv)
784 {
785 // The operand is hard-wired to be interpreted as a signed number.
788 source_op,
790 to_unsignedbv_type(source_op.type()).get_width())),
791 rounding_mode,
792 spec.to_type());
793 }
794 else if(source_op.type().id() == ID_floatbv)
795 {
797 source_op, rounding_mode, spec.to_type());
798 }
799 else
800 throw error() << "unexpected sort given as operand to to_fp";
801 }
802 else if(id == "to_fp_unsigned")
803 {
804 if(next_token() != smt2_tokenizert::NUMERAL)
805 throw error("expected number after to_fp_unsigned");
806
807 auto width_e = std::stoll(smt2_tokenizer.get_buffer());
808
809 if(next_token() != smt2_tokenizert::NUMERAL)
810 throw error("expected second number after to_fp_unsigned");
811
812 auto width_f = std::stoll(smt2_tokenizer.get_buffer());
813
814 if(next_token() != smt2_tokenizert::CLOSE)
815 throw error("expected ')' after to_fp_unsigned");
816
817 // width_f *includes* the hidden bit
818 const ieee_float_spect spec(width_f - 1, width_e);
819
820 auto rounding_mode = expression();
821
822 auto source_op = expression();
823
824 if(next_token() != smt2_tokenizert::CLOSE)
825 throw error("expected ')' at the end of to_fp_unsigned");
826
827 if(source_op.type().id() == ID_unsignedbv)
828 {
829 // The operand is hard-wired to be interpreted
830 // as an unsigned number.
832 source_op, rounding_mode, spec.to_type());
833 }
834 else
835 throw error()
836 << "unexpected sort given as operand to to_fp_unsigned";
837 }
838 else if(id == "fp.to_sbv" || id == "fp.to_ubv")
839 {
840 // These are indexed by the number of bits of the result.
841 if(next_token() != smt2_tokenizert::NUMERAL)
842 throw error() << "expected number after " << id;
843
844 auto width = std::stoll(smt2_tokenizer.get_buffer());
845
846 if(next_token() != smt2_tokenizert::CLOSE)
847 throw error() << "expected ')' after " << id;
848
849 auto op = operands();
850
851 if(op.size() != 2)
852 throw error() << id << " takes two operands";
853
854 if(op[1].type().id() != ID_floatbv)
855 throw error() << id << " takes a FloatingPoint operand";
856
857 if(id == "fp.to_sbv")
858 return typecast_exprt(
859 floatbv_typecast_exprt(op[1], op[0], signedbv_typet(width)),
860 unsignedbv_typet(width));
861 else
863 op[1], op[0], unsignedbv_typet(width));
864 }
865 else
866 {
867 throw error() << "unknown indexed identifier '"
868 << smt2_tokenizer.get_buffer() << '\'';
869 }
870 }
871 else if(smt2_tokenizer.get_buffer() == "as")
872 {
873 // This is an extension understood by Z3 and CVC4.
874 if(
875 smt2_tokenizer.peek() == smt2_tokenizert::SYMBOL &&
876 smt2_tokenizer.get_buffer() == "const")
877 {
878 next_token(); // eat the "const"
879 auto sort = this->sort();
880
881 if(sort.id() != ID_array)
882 {
883 throw error()
884 << "unexpected 'as const' expression expects array type";
885 }
886
887 const auto &array_sort = to_array_type(sort);
888
889 if(smt2_tokenizer.next_token() != smt2_tokenizert::CLOSE)
890 throw error() << "expecting ')' after sort in 'as const'";
891
892 auto value = expression();
893
894 if(value.type() != array_sort.element_type())
895 throw error() << "unexpected 'as const' with wrong element type";
896
897 if(smt2_tokenizer.next_token() != smt2_tokenizert::CLOSE)
898 throw error() << "expecting ')' at the end of 'as const'";
899
900 return array_of_exprt(value, array_sort);
901 }
902 else
903 throw error() << "unexpected 'as' expression";
904 }
905 else
906 {
907 // just double parentheses
909
910 if(
911 next_token() != smt2_tokenizert::CLOSE &&
912 next_token() != smt2_tokenizert::CLOSE)
913 {
914 throw error("mismatched parentheses in an expression");
915 }
916
917 return tmp;
918 }
919 }
920 else
921 {
922 // just double parentheses
924
925 if(
926 next_token() != smt2_tokenizert::CLOSE &&
927 next_token() != smt2_tokenizert::CLOSE)
928 {
929 throw error("mismatched parentheses in an expression");
930 }
931
932 return tmp;
933 }
934 break;
935
936 case smt2_tokenizert::CLOSE:
937 case smt2_tokenizert::NUMERAL:
938 case smt2_tokenizert::STRING_LITERAL:
939 case smt2_tokenizert::END_OF_FILE:
940 case smt2_tokenizert::NONE:
941 case smt2_tokenizert::KEYWORD:
942 // just parentheses
944 if(next_token() != smt2_tokenizert::CLOSE)
945 throw error("mismatched parentheses in an expression");
946
947 return tmp;
948 }
949
951}
952
954 const exprt::operandst &operands,
955 bool is_signed)
956{
957 if(operands.size() != 2)
958 throw error() << "bitvector division expects two operands";
959
960 // SMT-LIB2 defines the result of division by 0 to be 1....1
961 auto divisor = symbol_exprt("divisor", operands[1].type());
962 auto divisor_is_zero = equal_exprt(divisor, from_integer(0, divisor.type()));
963 auto all_ones = to_unsignedbv_type(operands[0].type()).largest_expr();
964
966
967 if(is_signed)
968 {
969 auto signed_operands = cast_bv_to_signed({operands[0], divisor});
972 }
973 else
974 division_result = div_exprt(operands[0], divisor);
975
976 return let_exprt(
977 {divisor},
978 operands[1],
980}
981
983{
984 if(operands.size() != 2)
985 throw error() << "bitvector modulo expects two operands";
986
987 // SMT-LIB2 defines the result of "lhs modulo 0" to be "lhs"
988 auto dividend = symbol_exprt("dividend", operands[0].type());
989 auto divisor = symbol_exprt("divisor", operands[1].type());
990 auto divisor_is_zero = equal_exprt(divisor, from_integer(0, divisor.type()));
991
993
994 // bvurem and bvsrem match our mod_exprt.
995 // bvsmod doesn't.
996 if(is_signed)
997 {
998 auto signed_operands = cast_bv_to_signed({dividend, divisor});
999 mod_result =
1001 }
1002 else
1003 mod_result = mod_exprt(dividend, divisor);
1004
1005 return let_exprt(
1006 {dividend, divisor},
1007 {operands[0], operands[1]},
1008 if_exprt(divisor_is_zero, dividend, mod_result));
1009}
1010
1012{
1013 switch(next_token())
1014 {
1015 case smt2_tokenizert::SYMBOL:
1016 {
1017 const auto &identifier = smt2_tokenizer.get_buffer();
1018
1019 // in the expression table?
1020 const auto e_it = expressions.find(identifier);
1021 if(e_it != expressions.end())
1022 return e_it->second();
1023
1024 // rummage through id_map
1025 auto id_it = id_map.find(identifier);
1026 if(id_it != id_map.end())
1027 {
1028 symbol_exprt symbol_expr(identifier, id_it->second.type);
1030 symbol_expr.set(ID_C_quoted, true);
1031 return std::move(symbol_expr);
1032 }
1033
1034 // don't know, give up
1035 throw error() << "unknown expression '" << identifier << '\'';
1036 }
1037
1038 case smt2_tokenizert::NUMERAL:
1039 {
1040 const std::string &buffer = smt2_tokenizer.get_buffer();
1041 if(buffer.size() >= 2 && buffer[0] == '#' && buffer[1] == 'x')
1042 {
1043 mp_integer value =
1044 string2integer(std::string(buffer, 2, std::string::npos), 16);
1045 const std::size_t width = 4 * (buffer.size() - 2);
1046 CHECK_RETURN(width != 0 && width % 4 == 0);
1047 unsignedbv_typet type(width);
1048 return from_integer(value, type);
1049 }
1050 else if(buffer.size() >= 2 && buffer[0] == '#' && buffer[1] == 'b')
1051 {
1052 mp_integer value =
1053 string2integer(std::string(buffer, 2, std::string::npos), 2);
1054 const std::size_t width = buffer.size() - 2;
1055 CHECK_RETURN(width != 0);
1056 unsignedbv_typet type(width);
1057 return from_integer(value, type);
1058 }
1059 else
1060 {
1061 return constant_exprt(buffer, integer_typet());
1062 }
1063 }
1064
1065 case smt2_tokenizert::OPEN: // function application
1066 return function_application();
1067
1068 case smt2_tokenizert::END_OF_FILE:
1069 throw error("EOF in an expression");
1070
1071 case smt2_tokenizert::CLOSE:
1072 case smt2_tokenizert::STRING_LITERAL:
1073 case smt2_tokenizert::NONE:
1074 case smt2_tokenizert::KEYWORD:
1075 throw error("unexpected token in an expression");
1076 }
1077
1079}
1080
1082{
1083 expressions["true"] = [] { return true_exprt(); };
1084 expressions["false"] = [] { return false_exprt(); };
1085
1086 expressions["roundNearestTiesToEven"] = [] {
1087 // we encode as 32-bit unsignedbv
1089 };
1090
1091 expressions["RNE"] = [] {
1092 // we encode as 32-bit unsignedbv
1094 };
1095
1096 expressions["roundNearestTiesToAway"] = [] {
1097 // we encode as 32-bit unsignedbv
1099 };
1100
1101 expressions["RNA"] = [] {
1102 // we encode as 32-bit unsignedbv
1104 };
1105
1106 expressions["roundTowardPositive"] = [] {
1107 // we encode as 32-bit unsignedbv
1109 };
1110
1111 expressions["RTP"] = [] {
1112 // we encode as 32-bit unsignedbv
1114 };
1115
1116 expressions["roundTowardNegative"] = [] {
1117 // we encode as 32-bit unsignedbv
1119 };
1120
1121 expressions["RTN"] = [] {
1122 // we encode as 32-bit unsignedbv
1124 };
1125
1126 expressions["roundTowardZero"] = [] {
1127 // we encode as 32-bit unsignedbv
1129 };
1130
1131 expressions["RTZ"] = [] {
1132 // we encode as 32-bit unsignedbv
1134 };
1135
1136 expressions["lambda"] = [this] { return lambda_expression(); };
1137 expressions["let"] = [this] { return let_expression(); };
1138 expressions["exists"] = [this] { return quantifier_expression(ID_exists); };
1139 expressions["forall"] = [this] { return quantifier_expression(ID_forall); };
1140 expressions["and"] = [this] { return multi_ary(ID_and, operands()); };
1141 expressions["or"] = [this] { return multi_ary(ID_or, operands()); };
1142 expressions["xor"] = [this] { return multi_ary(ID_xor, operands()); };
1143 expressions["not"] = [this] { return unary(ID_not, operands()); };
1144 expressions["="] = [this] { return binary_predicate(ID_equal, operands()); };
1145 expressions["<="] = [this] { return binary_predicate(ID_le, operands()); };
1146 expressions[">="] = [this] { return binary_predicate(ID_ge, operands()); };
1147 expressions["<"] = [this] { return binary_predicate(ID_lt, operands()); };
1148 expressions[">"] = [this] { return binary_predicate(ID_gt, operands()); };
1149
1150 expressions["bvule"] = [this] { return binary_predicate(ID_le, operands()); };
1151
1152 expressions["bvsle"] = [this] {
1154 };
1155
1156 expressions["bvuge"] = [this] { return binary_predicate(ID_ge, operands()); };
1157
1158 expressions["bvsge"] = [this] {
1160 };
1161
1162 expressions["bvult"] = [this] { return binary_predicate(ID_lt, operands()); };
1163
1164 expressions["bvslt"] = [this] {
1166 };
1167
1168 expressions["bvugt"] = [this] { return binary_predicate(ID_gt, operands()); };
1169
1170 expressions["bvsgt"] = [this] {
1172 };
1173
1174 expressions["bvcomp"] = [this] {
1175 auto b0 = from_integer(0, unsignedbv_typet(1));
1176 auto b1 = from_integer(1, unsignedbv_typet(1));
1178 };
1179
1180 expressions["bvashr"] = [this] {
1182 };
1183
1184 expressions["bvlshr"] = [this] { return binary(ID_lshr, operands()); };
1185 expressions["bvshr"] = [this] { return binary(ID_lshr, operands()); };
1186 expressions["bvlshl"] = [this] { return binary(ID_shl, operands()); };
1187 expressions["bvashl"] = [this] { return binary(ID_shl, operands()); };
1188 expressions["bvshl"] = [this] { return binary(ID_shl, operands()); };
1189 expressions["bvand"] = [this] { return multi_ary(ID_bitand, operands()); };
1190 expressions["bvnand"] = [this] { return multi_ary(ID_bitnand, operands()); };
1191 expressions["bvor"] = [this] { return multi_ary(ID_bitor, operands()); };
1192 expressions["bvnor"] = [this] { return multi_ary(ID_bitnor, operands()); };
1193 expressions["bvxor"] = [this] { return multi_ary(ID_bitxor, operands()); };
1194 expressions["bvxnor"] = [this] { return multi_ary(ID_bitxnor, operands()); };
1195 expressions["bvnot"] = [this] { return unary(ID_bitnot, operands()); };
1196 expressions["bvneg"] = [this] { return unary(ID_unary_minus, operands()); };
1197 expressions["bvadd"] = [this] { return multi_ary(ID_plus, operands()); };
1198 expressions["+"] = [this] { return multi_ary(ID_plus, operands()); };
1199 expressions["bvsub"] = [this] { return binary(ID_minus, operands()); };
1200 expressions["bvmul"] = [this] { return multi_ary(ID_mult, operands()); };
1201 expressions["*"] = [this] { return multi_ary(ID_mult, operands()); };
1202
1203 expressions["-"] = [this] {
1204 auto op = operands();
1205 if(op.size() == 1)
1206 return unary(ID_unary_minus, op);
1207 else
1208 return binary(ID_minus, op);
1209 };
1210
1211 expressions["bvsdiv"] = [this] { return bv_division(operands(), true); };
1212 expressions["bvudiv"] = [this] { return bv_division(operands(), false); };
1213 expressions["/"] = [this] { return binary(ID_div, operands()); };
1214 expressions["div"] = [this] { return binary(ID_div, operands()); };
1215
1216 expressions["bvsrem"] = [this] { return bv_mod(operands(), true); };
1217 expressions["bvurem"] = [this] { return bv_mod(operands(), false); };
1218
1219 // 2's complement signed remainder (sign follows divisor)
1220 // We don't have that.
1221 expressions["bvsmod"] = [this] { return bv_mod(operands(), true); };
1222
1223 expressions["mod"] = [this] {
1224 // SMT-LIB2 uses Boute's Euclidean definition for mod,
1225 // which is never negative and undefined when the second
1226 // argument is zero.
1227 return binary(ID_euclidean_mod, operands());
1228 };
1229
1230 expressions["concat"] = [this] {
1231 auto op = operands();
1232
1233 // add the widths
1234 auto op_width = make_range(op).map(
1235 [](const exprt &o) { return to_bitvector_type(o.type()).get_width(); });
1236
1237 const std::size_t total_width =
1238 std::accumulate(op_width.begin(), op_width.end(), 0);
1239
1240 return concatenation_exprt(std::move(op), unsignedbv_typet(total_width));
1241 };
1242
1243 expressions["distinct"] = [this] {
1244 // pair-wise different constraint, multi-ary
1245 auto op = operands();
1246 if(op.size() == 2)
1247 return binary_predicate(ID_notequal, op);
1248 else
1249 {
1250 std::vector<exprt> pairwise_constraints;
1251 for(std::size_t i = 0; i < op.size(); i++)
1252 {
1253 for(std::size_t j = i; j < op.size(); j++)
1254 {
1255 if(i != j)
1256 pairwise_constraints.push_back(
1257 binary_exprt(op[i], ID_notequal, op[j], bool_typet()));
1258 }
1259 }
1261 }
1262 };
1263
1264 expressions["ite"] = [this] {
1265 auto op = operands();
1266
1267 if(op.size() != 3)
1268 throw error("ite takes three operands");
1269
1270 if(!op[0].is_boolean())
1271 throw error("ite takes a boolean as first operand");
1272
1273 if(op[1].type() != op[2].type())
1274 throw error("ite needs matching types");
1275
1276 return if_exprt(op[0], op[1], op[2]);
1277 };
1278
1279 expressions["implies"] = [this] { return binary(ID_implies, operands()); };
1280
1281 expressions["=>"] = [this] { return binary(ID_implies, operands()); };
1282
1283 expressions["select"] = [this] {
1284 auto op = operands();
1285
1286 // array index
1287 if(op.size() != 2)
1288 throw error("select takes two operands");
1289
1290 if(op[0].type().id() != ID_array)
1291 throw error("select expects array operand");
1292
1293 return index_exprt(op[0], op[1]);
1294 };
1295
1296 expressions["store"] = [this] {
1297 auto op = operands();
1298
1299 // array update
1300 if(op.size() != 3)
1301 throw error("store takes three operands");
1302
1303 if(op[0].type().id() != ID_array)
1304 throw error("store expects array operand");
1305
1306 if(to_array_type(op[0].type()).element_type() != op[2].type())
1307 throw error("store expects value that matches array element type");
1308
1309 return with_exprt(op[0], op[1], op[2]);
1310 };
1311
1312 expressions["fp.abs"] = [this] {
1313 auto op = operands();
1314
1315 if(op.size() != 1)
1316 throw error("fp.abs takes one operand");
1317
1318 if(op[0].type().id() != ID_floatbv)
1319 throw error("fp.abs takes FloatingPoint operand");
1320
1321 return abs_exprt(op[0]);
1322 };
1323
1324 expressions["fp.isNaN"] = [this] {
1325 auto op = operands();
1326
1327 if(op.size() != 1)
1328 throw error("fp.isNaN takes one operand");
1329
1330 if(op[0].type().id() != ID_floatbv)
1331 throw error("fp.isNaN takes FloatingPoint operand");
1332
1333 return unary_predicate_exprt(ID_isnan, op[0]);
1334 };
1335
1336 expressions["fp.isInfinite"] = [this] {
1337 auto op = operands();
1338
1339 if(op.size() != 1)
1340 throw error("fp.isInfinite takes one operand");
1341
1342 if(op[0].type().id() != ID_floatbv)
1343 throw error("fp.isInfinite takes FloatingPoint operand");
1344
1345 return unary_predicate_exprt(ID_isinf, op[0]);
1346 };
1347
1348 expressions["fp.isNormal"] = [this] {
1349 auto op = operands();
1350
1351 if(op.size() != 1)
1352 throw error("fp.isNormal takes one operand");
1353
1354 if(op[0].type().id() != ID_floatbv)
1355 throw error("fp.isNormal takes FloatingPoint operand");
1356
1357 return isnormal_exprt(op[0]);
1358 };
1359
1360 expressions["fp.isZero"] = [this] {
1361 auto op = operands();
1362
1363 if(op.size() != 1)
1364 throw error("fp.isZero takes one operand");
1365
1366 if(op[0].type().id() != ID_floatbv)
1367 throw error("fp.isZero takes FloatingPoint operand");
1368
1369 return not_exprt(typecast_exprt(op[0], bool_typet()));
1370 };
1371
1372 expressions["fp"] = [this] { return function_application_fp(operands()); };
1373
1374 expressions["fp.add"] = [this] {
1375 return function_application_ieee_float_op("fp.add", operands());
1376 };
1377
1378 expressions["fp.mul"] = [this] {
1379 return function_application_ieee_float_op("fp.mul", operands());
1380 };
1381
1382 expressions["fp.sub"] = [this] {
1383 return function_application_ieee_float_op("fp.sub", operands());
1384 };
1385
1386 expressions["fp.div"] = [this] {
1387 return function_application_ieee_float_op("fp.div", operands());
1388 };
1389
1390 expressions["fp.rem"] = [this] {
1391 auto op = operands();
1392
1393 // Note that these do not have a rounding mode.
1394 if(op.size() != 2)
1395 throw error() << "fp.rem takes three operands";
1396
1397 if(op[0].type().id() != ID_floatbv || op[1].type().id() != ID_floatbv)
1398 throw error() << "fp.rem takes FloatingPoint operands";
1399
1400 if(op[0].type() != op[1].type())
1401 {
1402 throw error()
1403 << "fp.rem takes FloatingPoint operands with matching sort, "
1404 << "but got " << smt2_format(op[0].type()) << " vs "
1405 << smt2_format(op[1].type());
1406 }
1407
1408 return binary_exprt(op[0], ID_floatbv_rem, op[1]);
1409 };
1410
1411 expressions["fp.roundToIntegral"] = [this]
1412 {
1413 auto op = operands();
1414
1415 if(op.size() != 2)
1416 throw error() << "fp.roundToIntegral takes two operands";
1417
1418 if(op[1].type().id() != ID_floatbv)
1419 throw error() << "fp.roundToIntegral takes a FloatingPoint operand";
1420
1421 // Note swapped order.
1422 return floatbv_round_to_integral_exprt(op[1], op[0]);
1423 };
1424
1425 expressions["fp.eq"] = [this] {
1427 };
1428
1429 expressions["fp.leq"] = [this] {
1430 return binary_predicate(ID_le, operands());
1431 };
1432
1433 expressions["fp.lt"] = [this] { return binary_predicate(ID_lt, operands()); };
1434
1435 expressions["fp.geq"] = [this] {
1436 return binary_predicate(ID_ge, operands());
1437 };
1438
1439 expressions["fp.gt"] = [this] { return binary_predicate(ID_gt, operands()); };
1440
1441 expressions["fp.neg"] = [this] { return unary(ID_unary_minus, operands()); };
1442}
1443
1445{
1446 std::vector<typet> sorts;
1447
1448 // (-> sort+ sort)
1449 // The last sort is the co-domain.
1450
1451 while(smt2_tokenizer.peek() != smt2_tokenizert::CLOSE)
1452 {
1453 if(smt2_tokenizer.peek() == smt2_tokenizert::END_OF_FILE)
1454 throw error() << "unexpected end-of-file in a function sort";
1455
1456 sorts.push_back(sort()); // recursive call
1457 }
1458
1459 next_token(); // eat the ')'
1460
1461 if(sorts.size() < 2)
1462 throw error() << "expected function sort to have at least 2 type arguments";
1463
1464 auto codomain = std::move(sorts.back());
1465 sorts.pop_back();
1466
1467 return mathematical_function_typet(std::move(sorts), std::move(codomain));
1468}
1469
1471{
1472 // a sort is one of the following three cases:
1473 // SYMBOL
1474 // ( _ SYMBOL ...
1475 // ( SYMBOL ...
1476 switch(next_token())
1477 {
1478 case smt2_tokenizert::SYMBOL:
1479 break;
1480
1481 case smt2_tokenizert::OPEN:
1482 if(smt2_tokenizer.next_token() != smt2_tokenizert::SYMBOL)
1483 throw error("expected symbol after '(' in a sort ");
1484
1485 if(smt2_tokenizer.get_buffer() == "_")
1486 {
1487 if(next_token() != smt2_tokenizert::SYMBOL)
1488 throw error("expected symbol after '_' in a sort");
1489 }
1490 break;
1491
1492 case smt2_tokenizert::CLOSE:
1493 case smt2_tokenizert::NUMERAL:
1494 case smt2_tokenizert::STRING_LITERAL:
1495 case smt2_tokenizert::NONE:
1496 case smt2_tokenizert::KEYWORD:
1497 throw error() << "unexpected token in a sort: '"
1498 << smt2_tokenizer.get_buffer() << '\'';
1499
1500 case smt2_tokenizert::END_OF_FILE:
1501 throw error() << "unexpected end-of-file in a sort";
1502 }
1503
1504 // now we have a SYMBOL
1505 const auto &token = smt2_tokenizer.get_buffer();
1506
1507 const auto s_it = sorts.find(token);
1508
1509 if(s_it == sorts.end())
1510 throw error() << "unexpected sort: '" << token << '\'';
1511
1512 return s_it->second();
1513}
1514
1516{
1517 sorts["Bool"] = [] { return bool_typet(); };
1518 sorts["Int"] = [] { return integer_typet(); };
1519 sorts["Real"] = [] { return real_typet(); };
1520
1521 sorts["Float16"] = [] {
1522 return ieee_float_spect::half_precision().to_type();
1523 };
1524 sorts["Float32"] = [] {
1525 return ieee_float_spect::single_precision().to_type();
1526 };
1527 sorts["Float64"] = [] {
1528 return ieee_float_spect::double_precision().to_type();
1529 };
1530 sorts["Float128"] = [] {
1531 return ieee_float_spect::quadruple_precision().to_type();
1532 };
1533
1534 sorts["BitVec"] = [this] {
1535 if(next_token() != smt2_tokenizert::NUMERAL)
1536 throw error("expected numeral as bit-width");
1537
1538 auto width = std::stoll(smt2_tokenizer.get_buffer());
1539
1540 // eat the ')'
1541 if(next_token() != smt2_tokenizert::CLOSE)
1542 throw error("expected ')' at end of sort");
1543
1544 return unsignedbv_typet(width);
1545 };
1546
1547 sorts["FloatingPoint"] = [this] {
1548 if(next_token() != smt2_tokenizert::NUMERAL)
1549 throw error("expected numeral as bit-width");
1550
1551 const auto width_e = std::stoll(smt2_tokenizer.get_buffer());
1552
1553 if(next_token() != smt2_tokenizert::NUMERAL)
1554 throw error("expected numeral as bit-width");
1555
1556 const auto width_f = std::stoll(smt2_tokenizer.get_buffer());
1557
1558 // consume the ')'
1559 if(next_token() != smt2_tokenizert::CLOSE)
1560 throw error("expected ')' at end of sort");
1561
1562 return ieee_float_spect(width_f - 1, width_e).to_type();
1563 };
1564
1565 sorts["Array"] = [this] {
1566 // this gets two sorts as arguments, domain and range
1567 auto domain = sort();
1568 auto range = sort();
1569
1570 // eat the ')'
1571 if(next_token() != smt2_tokenizert::CLOSE)
1572 throw error("expected ')' at end of Array sort");
1573
1574 // we can turn arrays that map an unsigned bitvector type
1575 // to something else into our 'array_typet'
1576 if(domain.id() == ID_unsignedbv)
1577 return array_typet(range, infinity_exprt(domain));
1578 else
1579 throw error("unsupported array sort");
1580 };
1581
1582 sorts["->"] = [this] { return function_sort(); };
1583}
1584
1587{
1588 if(next_token() != smt2_tokenizert::OPEN)
1589 throw error("expected '(' at beginning of signature");
1590
1591 if(smt2_tokenizer.peek() == smt2_tokenizert::CLOSE)
1592 {
1593 // no parameters
1594 next_token(); // eat the ')'
1596 }
1597
1599 std::vector<irep_idt> parameters;
1600
1601 while(smt2_tokenizer.peek() != smt2_tokenizert::CLOSE)
1602 {
1603 if(next_token() != smt2_tokenizert::OPEN)
1604 throw error("expected '(' at beginning of parameter");
1605
1606 if(next_token() != smt2_tokenizert::SYMBOL)
1607 throw error("expected symbol in parameter");
1608
1610 domain.push_back(sort());
1611 parameters.push_back(id);
1612
1613 if(next_token() != smt2_tokenizert::CLOSE)
1614 throw error("expected ')' at end of parameter");
1615 }
1616
1617 next_token(); // eat the ')'
1618
1619 typet codomain = sort();
1620
1622 mathematical_function_typet(domain, codomain), parameters);
1623}
1624
1626{
1627 if(next_token() != smt2_tokenizert::OPEN)
1628 throw error("expected '(' at beginning of signature");
1629
1630 if(smt2_tokenizer.peek() == smt2_tokenizert::CLOSE)
1631 {
1632 next_token(); // eat the ')'
1633 return sort();
1634 }
1635
1637
1638 while(smt2_tokenizer.peek() != smt2_tokenizert::CLOSE)
1639 domain.push_back(sort());
1640
1641 next_token(); // eat the ')'
1642
1643 typet codomain = sort();
1644
1645 return mathematical_function_typet(domain, codomain);
1646}
1647
1648void smt2_parsert::command(const std::string &c)
1649{
1650 auto c_it = commands.find(c);
1651 if(c_it == commands.end())
1652 {
1653 // silently ignore
1655 }
1656 else
1657 c_it->second();
1658}
1659
1661{
1662 commands["declare-const"] = [this]() {
1663 const auto s = smt2_tokenizer.get_buffer();
1664
1665 if(next_token() != smt2_tokenizert::SYMBOL)
1666 throw error() << "expected a symbol after " << s;
1667
1669 auto type = sort();
1670
1671 add_unique_id(id, exprt(ID_nil, type));
1672 };
1673
1674 // declare-var appears to be a synonym for declare-const that is
1675 // accepted by Z3 and CVC4
1676 commands["declare-var"] = commands["declare-const"];
1677
1678 commands["declare-fun"] = [this]() {
1679 if(next_token() != smt2_tokenizert::SYMBOL)
1680 throw error("expected a symbol after declare-fun");
1681
1683 auto type = function_signature_declaration();
1684
1685 add_unique_id(id, exprt(ID_nil, type));
1686 };
1687
1688 commands["define-const"] = [this]() {
1689 if(next_token() != smt2_tokenizert::SYMBOL)
1690 throw error("expected a symbol after define-const");
1691
1692 const irep_idt id = smt2_tokenizer.get_buffer();
1693
1694 const auto type = sort();
1695 const auto value = expression();
1696
1697 // check type of value
1698 if(value.type() != type)
1699 {
1700 throw error() << "type mismatch in constant definition: expected '"
1701 << smt2_format(type) << "' but got '"
1702 << smt2_format(value.type()) << '\'';
1703 }
1704
1705 // create the entry
1706 add_unique_id(id, value);
1707 };
1708
1709 commands["define-fun"] = [this]() {
1710 if(next_token() != smt2_tokenizert::SYMBOL)
1711 throw error("expected a symbol after define-fun");
1712
1713 const irep_idt id = smt2_tokenizer.get_buffer();
1714
1715 const auto signature = function_signature_definition();
1716
1717 // put the parameters into the scope and take care of hiding
1718 std::vector<std::pair<irep_idt, idt>> hidden_ids;
1719
1720 for(const auto &pair : signature.ids_and_types())
1721 {
1722 auto insert_result =
1723 id_map.insert({pair.first, idt{idt::PARAMETER, pair.second}});
1724 if(!insert_result.second) // already there
1725 {
1726 auto &id_entry = *insert_result.first;
1727 hidden_ids.emplace_back(id_entry.first, std::move(id_entry.second));
1728 id_entry.second = idt{idt::PARAMETER, pair.second};
1729 }
1730 }
1731
1732 // now parse body with parameter ids in place
1733 auto body = expression();
1734
1735 // remove the parameter ids
1736 for(auto &id : signature.parameters)
1737 id_map.erase(id);
1738
1739 // restore the hidden ids, if any
1740 for(auto &hidden_id : hidden_ids)
1741 id_map.insert(std::move(hidden_id));
1742
1743 // check type of body
1744 if(signature.type.id() == ID_mathematical_function)
1745 {
1746 const auto &f_signature = to_mathematical_function_type(signature.type);
1747 if(body.type() != f_signature.codomain())
1748 {
1749 throw error() << "type mismatch in function definition: expected '"
1750 << smt2_format(f_signature.codomain()) << "' but got '"
1751 << smt2_format(body.type()) << '\'';
1752 }
1753 }
1754 else if(body.type() != signature.type)
1755 {
1756 throw error() << "type mismatch in function definition: expected '"
1757 << smt2_format(signature.type) << "' but got '"
1758 << smt2_format(body.type()) << '\'';
1759 }
1760
1761 // if there are parameters, this is a lambda
1762 if(!signature.parameters.empty())
1763 body = lambda_exprt(signature.binding_variables(), body);
1764
1765 // create the entry
1766 add_unique_id(id, std::move(body));
1767 };
1768
1769 commands["exit"] = [this]() { exit = true; };
1770}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
API to expression classes for bitvectors.
Pre-defined bitvector types.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
Absolute value.
Definition std_expr.h:442
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Array constructor from single element.
Definition std_expr.h:1558
Arrays with given size.
Definition std_types.h:807
A base class for binary expressions.
Definition std_expr.h:638
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
Definition std_expr.h:731
std::vector< symbol_exprt > variablest
Definition std_expr.h:3236
The Boolean type.
Definition std_types.h:36
Fixed-width bit-vector without numerical interpretation.
Concatenation of bit-vector operands.
A constant literal expression.
Definition std_expr.h:3117
Division.
Definition std_expr.h:1157
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Equality.
Definition std_expr.h:1366
Base class for all expressions.
Definition expr.h:56
std::vector< exprt > operandst
Definition expr.h:58
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
Extracts a sub-range of a bit-vector operand.
The Boolean constant false.
Definition std_expr.h:3199
Round a floating-point number to an integral value considering the given rounding mode.
Semantic type conversion from/to floating-point formats.
Application of (mathematical) function.
IEEE-floating-point equality.
IEEE floating-point operations These have two data operands (op0 and op1) and one rounding mode (op2)...
static ieee_float_spect half_precision()
Definition ieee_float.h:63
static ieee_float_spect single_precision()
Definition ieee_float.h:70
static ieee_float_spect quadruple_precision()
Definition ieee_float.h:82
class floatbv_typet to_type() const
static ieee_float_spect double_precision()
Definition ieee_float.h:76
static ieee_float_valuet minus_infinity(const ieee_float_spect &_spec)
Definition ieee_float.h:209
static ieee_float_valuet NaN(const ieee_float_spect &_spec)
Definition ieee_float.h:195
static ieee_float_valuet plus_infinity(const ieee_float_spect &_spec)
Definition ieee_float.h:202
An IEEE 754 value plus a rounding mode, enabling operations with rounding on values.
Definition ieee_float.h:338
The trinary if-then-else operator.
Definition std_expr.h:2497
Array index operator.
Definition std_expr.h:1470
An expression denoting infinity.
Definition std_expr.h:3224
Unbounded, signed integers (mathematical integers, not bitvectors)
void set(const irep_idt &name, const irep_idt &value)
Definition irep.h:412
const irep_idt & id() const
Definition irep.h:388
Evaluates to true if the operand is a normal number.
A (mathematical) lambda expression.
A let expression.
Definition std_expr.h:3331
A type for mathematical functions (do not confuse with functions/methods in code)
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Definition std_expr.h:1228
The NIL expression.
Definition std_expr.h:3208
Boolean negation.
Definition std_expr.h:2454
A base class for quantifier expressions.
Unbounded, signed real numbers.
Bit-vector replication.
Fixed-width bit-vector with two's complement interpretation.
exprt function_application_ieee_float_op(const irep_idt &, const exprt::operandst &)
std::size_t parenthesis_level
Definition smt2_parser.h:94
void command(const std::string &)
exprt::operandst operands()
void command_sequence()
exprt bv_mod(const exprt::operandst &, bool is_signed)
exprt binary(irep_idt, const exprt::operandst &)
exprt bv_division(const exprt::operandst &, bool is_signed)
void skip_to_end_of_list()
This skips tokens until all bracketed expressions are closed.
std::unordered_map< std::string, std::function< exprt()> > expressions
exprt lambda_expression()
typet function_signature_declaration()
named_termst named_terms
Definition smt2_parser.h:74
id_mapt id_map
Definition smt2_parser.h:58
std::unordered_map< std::string, std::function< void()> > commands
exprt function_application()
void add_unique_id(irep_idt, exprt)
exprt cast_bv_to_unsigned(const exprt &)
Apply typecast to unsignedbv to given expression.
exprt::operandst cast_bv_to_signed(const exprt::operandst &)
Apply typecast to signedbv to expressions in vector.
exprt multi_ary(irep_idt, const exprt::operandst &)
void ignore_command()
exprt quantifier_expression(irep_idt)
std::pair< binding_exprt::variablest, exprt > binding(irep_idt)
exprt function_application_ieee_float_eq(const exprt::operandst &)
exprt let_expression()
void check_matching_operand_types(const exprt::operandst &) const
signature_with_parameter_idst function_signature_definition()
exprt function_application_fp(const exprt::operandst &)
typet function_sort()
smt2_tokenizert::smt2_errort error() const
Definition smt2_parser.h:83
void setup_expressions()
exprt binary_predicate(irep_idt, const exprt::operandst &)
smt2_tokenizert::tokent next_token()
std::unordered_map< std::string, std::function< typet()> > sorts
smt2_tokenizert smt2_tokenizer
Definition smt2_parser.h:92
exprt unary(irep_idt, const exprt::operandst &)
void setup_commands()
const std::string & get_buffer() const
bool token_is_quoted_symbol() const
Expression to hold a symbol (variable)
Definition std_expr.h:131
const irep_idt & get_identifier() const
Definition std_expr.h:160
The Boolean constant true.
Definition std_expr.h:3190
Semantic type conversion.
Definition std_expr.h:2073
The type of an expression, extends irept.
Definition type.h:29
Generic base class for unary expressions.
Definition std_expr.h:361
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly one argu...
Definition std_expr.h:585
Fixed-width bit-vector with unsigned binary interpretation.
Operator to update elements in structs and arrays.
Definition std_expr.h:2598
zero extension The operand is converted to the given type by either a) truncating if the new type is ...
bool has_prefix(const std::string &s, const std::string &prefix)
Definition converter.cpp:13
API to expression classes for floating-point arithmetic.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
API to expression classes for 'mathematical' expressions.
const mathematical_function_typet & to_mathematical_function_type(const typet &type)
Cast a typet to a mathematical_function_typet.
const mp_integer string2integer(const std::string &n, unsigned base)
Definition mp_arith.cpp:54
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition range.h:522
static smt2_format_containert< T > smt2_format(const T &_o)
Definition smt2_format.h:28
BigInt mp_integer
Definition smt_terms.h:17
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3172
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888
bool is_signed(const typet &t)
Convenience function – is the type signed?
Definition util.cpp:45