29 if(token == smt2_tokenizert::OPEN)
31 else if(token == smt2_tokenizert::CLOSE)
40 if(
next_token() == smt2_tokenizert::END_OF_FILE)
57 throw error(
"command must start with '('");
62 throw error(
"expected symbol as command");
69 case smt2_tokenizert::END_OF_FILE:
71 "expected closing parenthesis at end of command,"
74 case smt2_tokenizert::CLOSE:
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");
91 std::size_t parentheses=0;
96 case smt2_tokenizert::OPEN:
101 case smt2_tokenizert::CLOSE:
109 case smt2_tokenizert::END_OF_FILE:
110 throw error(
"unexpected EOF in command");
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:
138 std::piecewise_construct,
139 std::forward_as_tuple(
id),
140 std::forward_as_tuple(idt::VARIABLE, std::move(expr)))
144 throw error() <<
"identifier '" <<
id <<
"' defined twice";
151 throw error(
"expected bindings after let");
153 std::vector<std::pair<irep_idt, exprt>> bindings;
160 throw error(
"expected symbol in binding");
168 throw error(
"expected ')' after value in binding");
171 std::pair<irep_idt, exprt>(identifier, value));
175 throw error(
"expected ')' at end of bindings");
178 std::vector<std::pair<irep_idt, idt>> saved_ids;
181 for(
auto &b : bindings)
183 auto insert_result =
id_map.insert({b.first,
idt{idt::BINDING, b.second}});
184 if(!insert_result.second)
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};
196 throw error(
"expected ')' after let");
201 for(
const auto &b : bindings)
203 variables.push_back(
symbol_exprt(b.first, b.second.type()));
204 values.push_back(b.second);
208 for(
const auto &
binding : bindings)
212 for(
auto &saved_id : saved_ids)
213 id_map.insert(std::move(saved_id));
215 return let_exprt(variables, values, where);
221 throw error() <<
"expected bindings after " << id;
230 throw error(
"expected symbol in binding");
237 throw error(
"expected ')' after sort in binding");
243 throw error(
"expected ')' at end of bindings");
246 std::vector<std::pair<irep_idt, idt>> saved_ids;
249 for(
auto &b : bindings)
252 id_map.insert({b.get_identifier(),
idt{idt::BINDING, b.
type()}});
253 if(!insert_result.second)
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()};
265 throw error() <<
"expected ')' after " << id;
268 for(
const auto &b : bindings)
269 id_map.erase(b.get_identifier());
272 for(
auto &saved_id : saved_ids)
273 id_map.insert(std::move(saved_id));
275 return {std::move(bindings), std::move(expr)};
288 if(!
binding.second.is_boolean())
289 throw error() <<
id <<
" expects a boolean term";
301 if(op.size() != function_type.domain().size())
302 throw error(
"wrong number of arguments for function");
304 for(std::size_t i=0; i<op.size(); i++)
306 if(op[i].type() != function_type.domain()[i])
307 throw error(
"wrong type for arguments for function");
317 for(
auto &expr : result)
319 if(expr.type().id() == ID_signedbv)
322 else if(expr.type().id() != ID_unsignedbv)
324 throw error(
"expected unsigned bitvector");
338 if(expr.
type().
id()==ID_unsignedbv)
341 if(expr.
type().
id()!=ID_signedbv)
342 throw error(
"expected signed bitvector");
351 for(std::size_t i = 1; i < op.size(); i++)
353 if(op[i].type() != op[0].type())
355 throw error() <<
"expression must have operands with matching types,"
366 throw error(
"expression must have at least one operand");
370 exprt result(
id, op[0].type());
378 throw error(
"expression must have two operands");
388 throw error(
"expression must have one operand");
396 throw error(
"expression must have two operands");
407 throw error() <<
"FloatingPoint equality takes two operands";
409 if(op[0].type().
id() != ID_floatbv || op[1].type().
id() != ID_floatbv)
410 throw error() <<
"FloatingPoint equality takes FloatingPoint operands";
412 if(op[0].type() != op[1].type())
414 throw error() <<
"FloatingPoint equality takes FloatingPoint operands with "
415 <<
"matching sort, but got " <<
smt2_format(op[0].type())
427 throw error() <<
id <<
" takes three operands";
429 if(op[1].type().
id() != ID_floatbv || op[2].type().
id() != ID_floatbv)
430 throw error() <<
id <<
" takes FloatingPoint operands";
432 if(op[1].type() != op[2].type())
434 throw error() <<
id <<
" takes FloatingPoint operands with matching sort, "
435 <<
"but got " <<
smt2_format(op[1].type()) <<
" vs "
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");
455 throw error(
"fp takes three operands");
457 if(op[0].type().
id() != ID_unsignedbv)
458 throw error(
"fp takes BitVec as first operand");
460 if(op[1].type().
id() != ID_unsignedbv)
461 throw error(
"fp takes BitVec as second operand");
463 if(op[2].type().
id() != ID_unsignedbv)
464 throw error(
"fp takes BitVec as third operand");
467 throw error(
"fp takes BitVec of size 1 as first operand");
477 const auto bv_type =
bv_typet(concat_type.get_width());
492 case smt2_tokenizert::SYMBOL:
497 throw error(
"expected symbol after '_'");
508 throw error(
"expected numeral as bitvector literal width");
513 throw error(
"expected ')' after bitvector literal");
517 else if(
id ==
"+oo" ||
id ==
"-oo" ||
id ==
"NaN")
522 throw error() <<
"expected number after " << id;
527 throw error() <<
"expected second number after " << id;
532 throw error() <<
"expected ')' after " << id;
546 throw error() <<
"unknown indexed identifier " << id;
560 if(!term.is_boolean())
561 throw error(
"named terms must be Boolean");
571 throw error(
"invalid name attribute, expected symbol");
574 throw error(
"unknown term attribute");
578 throw error(
"expected ')' at end of term attribute");
588 return e_it->second();
594 auto id_it =
id_map.find(
id);
597 if(id_it->second.type.id() == ID_mathematical_function)
605 throw error() <<
"unknown function symbol '" <<
id <<
'\'';
609 case smt2_tokenizert::OPEN:
617 throw error(
"expected symbol after '_'");
624 throw error(
"expected numeral after extract");
629 throw error(
"expected two numerals after extract");
634 throw error(
"expected ')' after extract");
639 throw error(
"extract takes one operand");
642 throw error(
"extract got bad indices");
650 else if(
id==
"rotate_left" ||
651 id==
"rotate_right" ||
657 throw error() <<
"expected numeral after " << id;
662 throw error() <<
"expected ')' after " <<
id <<
" index";
667 throw error() <<
id <<
" takes one operand";
669 if(
id==
"rotate_left")
674 else if(
id==
"rotate_right")
679 else if(
id==
"sign_extend")
693 else if(
id==
"zero_extend")
700 else if(
id == ID_repeat)
709 else if(
id ==
"to_fp")
712 throw error(
"expected number after to_fp");
717 throw error(
"expected second number after to_fp");
722 throw error(
"expected ')' after to_fp");
732 throw error(
"expected ')' at the end of to_fp");
739 source_op.type().id() == ID_real ||
740 source_op.type().id() == ID_integer)
744 if(source_op.is_constant())
748 const auto &real_number =
750 auto dot_pos = real_number.find(
'.');
751 if(dot_pos == std::string::npos)
759 std::string significand_str;
760 significand_str.reserve(real_number.size());
761 for(
auto ch : real_number)
764 significand_str += ch;
781 <<
"to_fp for non-constant real expressions is not implemented";
783 else if(source_op.type().id() == ID_unsignedbv)
794 else if(source_op.type().id() == ID_floatbv)
797 source_op, rounding_mode, spec.
to_type());
800 throw error() <<
"unexpected sort given as operand to to_fp";
802 else if(
id ==
"to_fp_unsigned")
805 throw error(
"expected number after to_fp_unsigned");
810 throw error(
"expected second number after to_fp_unsigned");
815 throw error(
"expected ')' after to_fp_unsigned");
825 throw error(
"expected ')' at the end of to_fp_unsigned");
827 if(source_op.type().id() == ID_unsignedbv)
832 source_op, rounding_mode, spec.
to_type());
836 <<
"unexpected sort given as operand to to_fp_unsigned";
838 else if(
id ==
"fp.to_sbv" ||
id ==
"fp.to_ubv")
842 throw error() <<
"expected number after " << id;
847 throw error() <<
"expected ')' after " << id;
852 throw error() <<
id <<
" takes two operands";
854 if(op[1].type().
id() != ID_floatbv)
855 throw error() <<
id <<
" takes a FloatingPoint operand";
857 if(
id ==
"fp.to_sbv")
867 throw error() <<
"unknown indexed identifier '"
884 <<
"unexpected 'as const' expression expects array type";
890 throw error() <<
"expecting ')' after sort in 'as const'";
894 if(value.type() != array_sort.element_type())
895 throw error() <<
"unexpected 'as const' with wrong element type";
898 throw error() <<
"expecting ')' at the end of 'as const'";
903 throw error() <<
"unexpected 'as' expression";
914 throw error(
"mismatched parentheses in an expression");
929 throw error(
"mismatched parentheses in an expression");
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:
945 throw error(
"mismatched parentheses in an expression");
958 throw error() <<
"bitvector division expects two operands";
965 exprt division_result;
979 if_exprt(divisor_is_zero, all_ones, division_result));
985 throw error() <<
"bitvector modulo expects two operands";
1003 mod_result =
mod_exprt(dividend, divisor);
1006 {dividend, divisor},
1008 if_exprt(divisor_is_zero, dividend, mod_result));
1015 case smt2_tokenizert::SYMBOL:
1022 return e_it->second();
1025 auto id_it =
id_map.find(identifier);
1026 if(id_it !=
id_map.end())
1028 symbol_exprt symbol_expr(identifier, id_it->second.type);
1030 symbol_expr.
set(ID_C_quoted,
true);
1031 return std::move(symbol_expr);
1035 throw error() <<
"unknown expression '" << identifier <<
'\'';
1038 case smt2_tokenizert::NUMERAL:
1041 if(buffer.size() >= 2 && buffer[0] ==
'#' && buffer[1] ==
'x')
1045 const std::size_t width = 4 * (buffer.size() - 2);
1050 else if(buffer.size() >= 2 && buffer[0] ==
'#' && buffer[1] ==
'b')
1054 const std::size_t width = buffer.size() - 2;
1065 case smt2_tokenizert::OPEN:
1068 case smt2_tokenizert::END_OF_FILE:
1069 throw error(
"EOF in an expression");
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");
1092 throw error(
"unsupported rounding mode");
1180 return unary(ID_unary_minus, op);
1182 return binary(ID_minus, op);
1211 const std::size_t total_width =
1212 std::accumulate(op_width.begin(), op_width.end(), 0);
1224 std::vector<exprt> pairwise_constraints;
1225 for(std::size_t i = 0; i < op.size(); i++)
1227 for(std::size_t j = i; j < op.size(); j++)
1230 pairwise_constraints.push_back(
1234 return multi_ary(ID_and, pairwise_constraints);
1242 throw error(
"ite takes three operands");
1244 if(!op[0].is_boolean())
1245 throw error(
"ite takes a boolean as first operand");
1247 if(op[1].type() != op[2].type())
1248 throw error(
"ite needs matching types");
1250 return if_exprt(op[0], op[1], op[2]);
1262 throw error(
"select takes two operands");
1264 if(op[0].type().
id() != ID_array)
1265 throw error(
"select expects array operand");
1275 throw error(
"store takes three operands");
1277 if(op[0].type().
id() != ID_array)
1278 throw error(
"store expects array operand");
1280 if(
to_array_type(op[0].type()).element_type() != op[2].type())
1281 throw error(
"store expects value that matches array element type");
1290 throw error(
"fp.abs takes one operand");
1292 if(op[0].type().
id() != ID_floatbv)
1293 throw error(
"fp.abs takes FloatingPoint operand");
1302 throw error(
"fp.isNaN takes one operand");
1304 if(op[0].type().
id() != ID_floatbv)
1305 throw error(
"fp.isNaN takes FloatingPoint operand");
1314 throw error(
"fp.isInfinite takes one operand");
1316 if(op[0].type().
id() != ID_floatbv)
1317 throw error(
"fp.isInfinite takes FloatingPoint operand");
1326 throw error(
"fp.isNormal takes one operand");
1328 if(op[0].type().
id() != ID_floatbv)
1329 throw error(
"fp.isNormal takes FloatingPoint operand");
1338 throw error(
"fp.isZero takes one operand");
1340 if(op[0].type().
id() != ID_floatbv)
1341 throw error(
"fp.isZero takes FloatingPoint operand");
1369 throw error() <<
"fp.rem takes three operands";
1371 if(op[0].type().
id() != ID_floatbv || op[1].type().
id() != ID_floatbv)
1372 throw error() <<
"fp.rem takes FloatingPoint operands";
1374 if(op[0].type() != op[1].type())
1377 <<
"fp.rem takes FloatingPoint operands with matching sort, "
1378 <<
"but got " <<
smt2_format(op[0].type()) <<
" vs "
1406 std::vector<typet>
sorts;
1414 throw error() <<
"unexpected end-of-file in a function sort";
1421 if(
sorts.size() < 2)
1422 throw error() <<
"expected function sort to have at least 2 type arguments";
1424 auto codomain = std::move(
sorts.back());
1438 case smt2_tokenizert::SYMBOL:
1441 case smt2_tokenizert::OPEN:
1443 throw error(
"expected symbol after '(' in a sort ");
1448 throw error(
"expected symbol after '_' in a sort");
1452 case smt2_tokenizert::CLOSE:
1453 case smt2_tokenizert::NUMERAL:
1454 case smt2_tokenizert::STRING_LITERAL:
1455 case smt2_tokenizert::NONE:
1456 case smt2_tokenizert::KEYWORD:
1457 throw error() <<
"unexpected token in a sort: '"
1460 case smt2_tokenizert::END_OF_FILE:
1461 throw error() <<
"unexpected end-of-file in a sort";
1467 const auto s_it =
sorts.find(token);
1469 if(s_it ==
sorts.end())
1470 throw error() <<
"unexpected sort: '" << token <<
'\'';
1472 return s_it->second();
1481 sorts[
"Float16"] = [] {
1484 sorts[
"Float32"] = [] {
1487 sorts[
"Float64"] = [] {
1490 sorts[
"Float128"] = [] {
1494 sorts[
"BitVec"] = [
this] {
1496 throw error(
"expected numeral as bit-width");
1502 throw error(
"expected ')' at end of sort");
1507 sorts[
"FloatingPoint"] = [
this] {
1509 throw error(
"expected numeral as bit-width");
1514 throw error(
"expected numeral as bit-width");
1520 throw error(
"expected ')' at end of sort");
1525 sorts[
"Array"] = [
this] {
1527 auto domain =
sort();
1528 auto range =
sort();
1532 throw error(
"expected ')' at end of Array sort");
1536 if(domain.id() == ID_unsignedbv)
1539 throw error(
"unsupported array sort");
1549 throw error(
"expected '(' at beginning of signature");
1559 std::vector<irep_idt> parameters;
1564 throw error(
"expected '(' at beginning of parameter");
1567 throw error(
"expected symbol in parameter");
1570 domain.push_back(
sort());
1571 parameters.push_back(
id);
1574 throw error(
"expected ')' at end of parameter");
1588 throw error(
"expected '(' at beginning of signature");
1599 domain.push_back(
sort());
1622 commands[
"declare-const"] = [
this]() {
1626 throw error() <<
"expected a symbol after " << s;
1638 commands[
"declare-fun"] = [
this]() {
1640 throw error(
"expected a symbol after declare-fun");
1648 commands[
"define-const"] = [
this]() {
1650 throw error(
"expected a symbol after define-const");
1654 const auto type =
sort();
1658 if(value.type() != type)
1660 throw error() <<
"type mismatch in constant definition: expected '"
1669 commands[
"define-fun"] = [
this]() {
1671 throw error(
"expected a symbol after define-fun");
1678 std::vector<std::pair<irep_idt, idt>> hidden_ids;
1680 for(
const auto &pair : signature.ids_and_types())
1682 auto insert_result =
1683 id_map.insert({pair.first,
idt{idt::PARAMETER, pair.second}});
1684 if(!insert_result.second)
1686 auto &id_entry = *insert_result.first;
1687 hidden_ids.emplace_back(id_entry.first, std::move(id_entry.second));
1688 id_entry.second =
idt{idt::PARAMETER, pair.second};
1696 for(
auto &
id : signature.parameters)
1700 for(
auto &hidden_id : hidden_ids)
1701 id_map.insert(std::move(hidden_id));
1704 if(signature.type.id() == ID_mathematical_function)
1707 if(body.type() != f_signature.codomain())
1709 throw error() <<
"type mismatch in function definition: expected '"
1710 <<
smt2_format(f_signature.codomain()) <<
"' but got '"
1714 else if(body.type() != signature.type)
1716 throw error() <<
"type mismatch in function definition: expected '"
1722 if(!signature.parameters.empty())
1723 body =
lambda_exprt(signature.binding_variables(), body);
API to expression classes for bitvectors.
Pre-defined bitvector types.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
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.
Array constructor from single element.
A base class for binary expressions.
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
std::vector< symbol_exprt > variablest
std::size_t get_width() const
Fixed-width bit-vector without numerical interpretation.
Concatenation of bit-vector operands.
A constant literal expression.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Base class for all expressions.
std::vector< exprt > operandst
typet & type()
Return the type of the expression.
The Boolean constant false.
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()
static ieee_float_spect single_precision()
static ieee_float_spect quadruple_precision()
class floatbv_typet to_type() const
static ieee_float_spect double_precision()
constant_exprt to_expr() const
static ieee_floatt plus_infinity(const ieee_float_spect &_spec)
static ieee_floatt NaN(const ieee_float_spect &_spec)
static ieee_floatt minus_infinity(const ieee_float_spect &_spec)
void from_base10(const mp_integer &exp, const mp_integer &frac)
compute f * (10^e)
The trinary if-then-else operator.
An expression denoting infinity.
constant_exprt largest_expr() const
Return an expression representing the largest value of this type.
Unbounded, signed integers (mathematical integers, not bitvectors)
void set(const irep_idt &name, const irep_idt &value)
const irep_idt & id() const
Evaluates to true if the operand is a normal number.
A (mathematical) lambda expression.
A type for mathematical functions (do not confuse with functions/methods in code)
std::vector< typet > domaint
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
A base class for quantifier expressions.
Unbounded, signed real numbers.
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
void command(const std::string &)
exprt::operandst operands()
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()
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 &)
exprt quantifier_expression(irep_idt)
std::pair< binding_exprt::variablest, exprt > binding(irep_idt)
exprt function_application_ieee_float_eq(const exprt::operandst &)
void check_matching_operand_types(const exprt::operandst &) const
signature_with_parameter_idst function_signature_definition()
exprt function_application_fp(const exprt::operandst &)
smt2_tokenizert::smt2_errort error() const
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
exprt unary(irep_idt, const exprt::operandst &)
enum { NONE, END_OF_FILE, STRING_LITERAL, NUMERAL, SYMBOL, KEYWORD, OPEN, CLOSE } tokent
const std::string & get_buffer() const
bool token_is_quoted_symbol() const
Expression to hold a symbol (variable)
const irep_idt & get_identifier() const
The Boolean constant true.
Semantic type conversion.
The type of an expression, extends irept.
Generic base class for unary expressions.
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly one argu...
Fixed-width bit-vector with unsigned binary interpretation.
Operator to update elements in structs and arrays.
bool has_prefix(const std::string &s, const std::string &prefix)
API to expression classes for floating-point arithmetic.
const std::string & id2string(const irep_idt &d)
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)
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< iteratort > make_range(iteratort begin, iteratort end)
#define CHECK_RETURN(CONDITION)
#define UNREACHABLE
This should be used to mark dead code.
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
bool is_signed(const typet &t)
Convenience function – is the type signed?