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 '('");
63 throw error(
"expected symbol as command");
70 case smt2_tokenizert::END_OF_FILE:
72 "expected closing parenthesis at end of command,"
75 case smt2_tokenizert::CLOSE:
79 case smt2_tokenizert::OPEN:
80 case smt2_tokenizert::SYMBOL:
81 case smt2_tokenizert::NUMERAL:
82 case smt2_tokenizert::STRING_LITERAL:
83 case smt2_tokenizert::NONE:
84 case smt2_tokenizert::KEYWORD:
85 throw error(
"expected ')' at end of command");
97 case smt2_tokenizert::OPEN:
102 case smt2_tokenizert::CLOSE:
110 case smt2_tokenizert::END_OF_FILE:
111 throw error(
"unexpected EOF in command");
113 case smt2_tokenizert::SYMBOL:
114 case smt2_tokenizert::NUMERAL:
115 case smt2_tokenizert::STRING_LITERAL:
116 case smt2_tokenizert::NONE:
117 case smt2_tokenizert::KEYWORD:
139 std::piecewise_construct,
140 std::forward_as_tuple(
id),
141 std::forward_as_tuple(idt::VARIABLE, std::move(expr)))
145 throw error() <<
"identifier '" <<
id <<
"' defined twice";
152 throw error(
"expected bindings after let");
154 std::vector<std::pair<irep_idt, exprt>> bindings;
162 throw error(
"expected symbol in binding");
170 throw error(
"expected ')' after value in binding");
173 std::pair<irep_idt, exprt>(identifier, value));
177 throw error(
"expected ')' at end of bindings");
180 std::vector<std::pair<irep_idt, idt>>
saved_ids;
183 for(
auto &
b : bindings)
198 throw error(
"expected ')' after let");
203 for(
const auto &
b : bindings)
206 values.push_back(
b.second);
210 for(
const auto &
binding : bindings)
217 return let_exprt(variables, values, where);
223 throw error() <<
"expected bindings after " << id;
233 throw error(
"expected symbol in binding");
240 throw error(
"expected ')' after sort in binding");
246 throw error(
"expected ')' at end of bindings");
249 std::vector<std::pair<irep_idt, idt>>
saved_ids;
252 for(
auto &
b : bindings)
255 id_map.insert({
b.identifier(),
idt{idt::BINDING,
b.type()}});
268 throw error() <<
"expected ')' after " << id;
271 for(
const auto &
b : bindings)
278 return {std::move(bindings), std::move(expr)};
291 if(!
binding.second.is_boolean())
292 throw error() <<
id <<
" expects a boolean term";
304 if(op.size() != function_type.domain().size())
305 throw error(
"wrong number of arguments for function");
307 for(std::size_t i=0; i<op.size(); i++)
309 if(op[i].type() != function_type.domain()[i])
310 throw error(
"wrong type for arguments for function");
320 for(
auto &expr : result)
327 throw error(
"expected unsigned bitvector");
345 throw error(
"expected signed bitvector");
354 for(std::size_t i = 1; i < op.size(); i++)
356 if(op[i].type() != op[0].type())
358 throw error() <<
"expression must have operands with matching types,"
369 throw error(
"expression must have at least one operand");
373 exprt result(
id, op[0].type());
381 throw error(
"expression must have two operands");
391 throw error(
"expression must have one operand");
399 throw error(
"expression must have two operands");
410 throw error() <<
"FloatingPoint equality takes two operands";
413 throw error() <<
"FloatingPoint equality takes FloatingPoint operands";
415 if(op[0].type() != op[1].type())
417 throw error() <<
"FloatingPoint equality takes FloatingPoint operands with "
418 <<
"matching sort, but got " <<
smt2_format(op[0].type())
430 throw error() <<
id <<
" takes three operands";
433 throw error() <<
id <<
" takes FloatingPoint operands";
435 if(op[1].type() != op[2].type())
437 throw error() <<
id <<
" takes FloatingPoint operands with matching sort, "
438 <<
"but got " <<
smt2_format(op[1].type()) <<
" vs "
448 throw error(
"unsupported floating-point operation");
458 throw error(
"fp takes three operands");
461 throw error(
"fp takes BitVec as first operand");
464 throw error(
"fp takes BitVec as second operand");
467 throw error(
"fp takes BitVec as third operand");
470 throw error(
"fp takes BitVec of size 1 as first operand");
497 case smt2_tokenizert::SYMBOL:
498 if(token.text ==
"_")
502 if(
id_token != smt2_tokenizert::SYMBOL)
503 throw error(
"expected symbol after '_'");
513 throw error(
"expected numeral as bitvector literal width");
518 throw error(
"expected ')' after bitvector literal");
522 else if(
id ==
"+oo" ||
id ==
"-oo" ||
id ==
"NaN")
527 if(
e_token != smt2_tokenizert::NUMERAL)
528 throw error() <<
"expected number after " << id;
533 if(
f_token != smt2_tokenizert::NUMERAL)
534 throw error() <<
"expected second number after " << id;
539 throw error() <<
"expected ')' after " << id;
553 throw error() <<
"unknown indexed identifier " << id;
556 else if(token.text ==
"!")
567 if(!term.is_boolean())
568 throw error(
"named terms must be Boolean");
578 throw error(
"invalid name attribute, expected symbol");
581 throw error(
"unknown term attribute");
585 throw error(
"expected ')' at end of term attribute");
592 const auto &
id = token.text;
595 return e_it->second();
612 throw error() <<
"unknown function symbol '" <<
id <<
'\'';
616 case smt2_tokenizert::OPEN:
624 if(
id_token != smt2_tokenizert::SYMBOL)
625 throw error(
"expected symbol after '_'");
633 throw error(
"expected numeral after extract");
639 throw error(
"expected two numerals after extract");
644 throw error(
"expected ')' after extract");
649 throw error(
"extract takes one operand");
652 throw error(
"extract got bad indices");
660 else if(
id==
"rotate_left" ||
661 id==
"rotate_right" ||
668 throw error() <<
"expected numeral after " << id;
673 throw error() <<
"expected ')' after " <<
id <<
" index";
678 throw error() <<
id <<
" takes one operand";
680 if(
id==
"rotate_left")
685 else if(
id==
"rotate_right")
690 else if(
id==
"sign_extend")
720 else if(
id ==
"to_fp")
723 if(
e_token != smt2_tokenizert::NUMERAL)
724 throw error(
"expected number after to_fp");
729 if(
f_token != smt2_tokenizert::NUMERAL)
730 throw error(
"expected second number after to_fp");
735 throw error(
"expected ')' after to_fp");
761 throw error() <<
"to_fp bit-pattern reinterpretation expects a "
762 "bit-vector operand of width "
781 throw error(
"expected ')' at the end of to_fp");
800 if(
dot_pos == std::string::npos)
825 a.from_base10(significand, exponent);
830 <<
"to_fp for non-constant real expressions is not implemented";
849 throw error() <<
"unexpected sort given as operand to to_fp";
851 else if(
id ==
"to_fp_unsigned")
854 if(
e_token != smt2_tokenizert::NUMERAL)
855 throw error(
"expected number after to_fp_unsigned");
860 if(
f_token != smt2_tokenizert::NUMERAL)
861 throw error(
"expected second number after to_fp_unsigned");
866 throw error(
"expected ')' after to_fp_unsigned");
876 throw error(
"expected ')' at the end of to_fp_unsigned");
887 <<
"unexpected sort given as operand to to_fp_unsigned";
889 else if(
id ==
"fp.to_sbv" ||
id ==
"fp.to_ubv")
894 throw error() <<
"expected number after " << id;
899 throw error() <<
"expected ')' after " << id;
904 throw error() <<
id <<
" takes two operands";
907 throw error() <<
id <<
" takes a FloatingPoint operand";
909 if(
id ==
"fp.to_sbv")
919 throw error() <<
"unknown indexed identifier '" <<
id <<
'\'';
935 <<
"unexpected 'as const' expression expects array type";
941 throw error() <<
"expecting ')' after sort in 'as const'";
946 throw error() <<
"unexpected 'as const' with wrong element type";
949 throw error() <<
"expecting ')' at the end of 'as const'";
954 throw error() <<
"unexpected 'as' expression";
965 throw error(
"mismatched parentheses in an expression");
980 throw error(
"mismatched parentheses in an expression");
987 case smt2_tokenizert::CLOSE:
988 case smt2_tokenizert::NUMERAL:
989 case smt2_tokenizert::STRING_LITERAL:
990 case smt2_tokenizert::END_OF_FILE:
991 case smt2_tokenizert::NONE:
992 case smt2_tokenizert::KEYWORD:
996 throw error(
"mismatched parentheses in an expression");
1009 throw error() <<
"bitvector division expects two operands";
1036 throw error() <<
"bitvector modulo expects two operands";
1057 {dividend, divisor},
1068 case smt2_tokenizert::SYMBOL:
1070 const auto &identifier = token.text;
1075 return e_it->second();
1082 if(token.quoted_symbol)
1084 return std::move(symbol_expr);
1088 throw error() <<
"unknown expression '" << identifier <<
'\'';
1091 case smt2_tokenizert::NUMERAL:
1093 const std::string &
buffer = token.text;
1098 const std::size_t width = 4 * (
buffer.size() - 2);
1107 const std::size_t width =
buffer.size() - 2;
1118 case smt2_tokenizert::OPEN:
1121 case smt2_tokenizert::END_OF_FILE:
1122 throw error(
"EOF in an expression");
1124 case smt2_tokenizert::CLOSE:
1125 case smt2_tokenizert::STRING_LITERAL:
1126 case smt2_tokenizert::NONE:
1127 case smt2_tokenizert::KEYWORD:
1128 throw error(
"unexpected token in an expression");
1290 const std::size_t total_width =
1304 for(std::size_t i = 0; i < op.size(); i++)
1306 for(std::size_t j = i; j < op.size(); j++)
1321 throw error(
"ite takes three operands");
1323 if(!op[0].is_boolean())
1324 throw error(
"ite takes a boolean as first operand");
1326 if(op[1].type() != op[2].type())
1327 throw error(
"ite needs matching types");
1329 return if_exprt(op[0], op[1], op[2]);
1341 throw error(
"select takes two operands");
1344 throw error(
"select expects array operand");
1354 throw error(
"store takes three operands");
1357 throw error(
"store expects array operand");
1359 if(
to_array_type(op[0].type()).element_type() != op[2].type())
1360 throw error(
"store expects value that matches array element type");
1371 throw error(name +
" takes one operand");
1374 throw error(name +
" takes FloatingPoint operand");
1376 return std::move(op[0]);
1467 throw error() <<
"fp.rem takes three operands";
1470 throw error() <<
"fp.rem takes FloatingPoint operands";
1472 if(op[0].type() != op[1].type())
1475 <<
"fp.rem takes FloatingPoint operands with matching sort, "
1476 <<
"but got " <<
smt2_format(op[0].type()) <<
" vs "
1488 throw error() <<
"fp.fma takes four operands";
1494 throw error() <<
"fp.fma takes FloatingPoint operands";
1506 throw error() <<
"fp.roundToIntegral takes two operands";
1509 throw error() <<
"fp.roundToIntegral takes a FloatingPoint operand";
1536 std::vector<typet>
sorts;
1544 throw error() <<
"unexpected end-of-file in a function sort";
1551 if(
sorts.size() < 2)
1552 throw error() <<
"expected function sort to have at least 2 type arguments";
1554 auto codomain = std::move(
sorts.back());
1570 case smt2_tokenizert::SYMBOL:
1573 case smt2_tokenizert::OPEN:
1577 throw error(
"expected symbol after '(' in a sort ");
1583 throw error(
"expected symbol after '_' in a sort");
1592 case smt2_tokenizert::CLOSE:
1593 case smt2_tokenizert::NUMERAL:
1594 case smt2_tokenizert::STRING_LITERAL:
1595 case smt2_tokenizert::NONE:
1596 case smt2_tokenizert::KEYWORD:
1597 throw error() <<
"unexpected token in a sort: '" <<
sort_token.text <<
'\'';
1599 case smt2_tokenizert::END_OF_FILE:
1600 throw error() <<
"unexpected end-of-file in a sort";
1609 throw error() <<
"unexpected sort: '" << token <<
'\'';
1611 return s_it->second();
1620 sorts[
"Float16"] = [] {
1623 sorts[
"Float32"] = [] {
1626 sorts[
"Float64"] = [] {
1629 sorts[
"Float128"] = [] {
1633 sorts[
"BitVec"] = [
this]
1637 throw error(
"expected numeral as bit-width");
1643 throw error(
"expected ')' at end of sort");
1648 sorts[
"FloatingPoint"] = [
this]
1651 if(
e_token != smt2_tokenizert::NUMERAL)
1652 throw error(
"expected numeral as bit-width");
1657 if(
f_token != smt2_tokenizert::NUMERAL)
1658 throw error(
"expected numeral as bit-width");
1664 throw error(
"expected ')' at end of sort");
1669 sorts[
"Array"] = [
this] {
1671 auto domain =
sort();
1672 auto range =
sort();
1676 throw error(
"expected ')' at end of Array sort");
1683 throw error(
"unsupported array sort");
1693 throw error(
"expected '(' at beginning of signature");
1703 std::vector<irep_idt> parameters;
1708 throw error(
"expected '(' at beginning of parameter");
1712 throw error(
"expected symbol in parameter");
1715 domain.push_back(
sort());
1716 parameters.push_back(
id);
1719 throw error(
"expected ')' at end of parameter");
1733 throw error(
"expected '(' at beginning of signature");
1744 domain.push_back(
sort());
1767 commands[
"declare-const"] = [
this]()
1770 if(
id_token != smt2_tokenizert::SYMBOL)
1771 throw error(
"expected a symbol after declare-const");
1786 if(
id_token != smt2_tokenizert::SYMBOL)
1787 throw error(
"expected a symbol after declare-fun");
1795 commands[
"define-const"] = [
this]()
1798 if(
id_token != smt2_tokenizert::SYMBOL)
1799 throw error(
"expected a symbol after define-const");
1803 const auto type =
sort();
1807 if(value.type() != type)
1809 throw error() <<
"type mismatch in constant definition: expected '"
1821 if(
id_token != smt2_tokenizert::SYMBOL)
1822 throw error(
"expected a symbol after define-fun");
1829 std::vector<std::pair<irep_idt, idt>>
hidden_ids;
1831 for(
const auto &
pair : signature.ids_and_types())
1847 for(
auto &
id : signature.parameters)
1860 throw error() <<
"type mismatch in function definition: expected '"
1865 else if(body.type() != signature.type)
1867 throw error() <<
"type mismatch in function definition: expected '"
1873 if(!signature.parameters.empty())
1874 body =
lambda_exprt(signature.binding_variables(), body);
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.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Boolean AND All operands must be boolean, and the result is always boolean.
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
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.
Fused multiply-add expression: round(op0 * op1 + op2) with a single rounding.
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()
static ieee_float_spect single_precision()
static ieee_float_spect quadruple_precision()
class floatbv_typet to_type() const
static ieee_float_spect double_precision()
std::size_t width() const
static ieee_float_valuet minus_infinity(const ieee_float_spect &_spec)
static ieee_float_valuet NaN(const ieee_float_spect &_spec)
static ieee_float_valuet plus_infinity(const ieee_float_spect &_spec)
An IEEE 754 value plus a rounding mode, enabling operations with rounding on values.
The trinary if-then-else operator.
An expression denoting infinity.
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 finite.
Evaluates to true if the operand is infinite.
Evaluates to true if the operand is NaN.
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.
Sign of an expression Predicate is true if _op is negative, false otherwise.
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 &)
tokent next_token()
Consume and return the next token.
const tokent & peek()
Return the next token without consuming it.
Expression to hold a symbol (variable)
void identifier(const irep_idt &identifier)
The Boolean constant true.
Semantic type conversion.
The type of an expression, extends irept.
Generic base class for unary expressions.
Fixed-width bit-vector with unsigned binary interpretation.
Operator to update elements in structs and arrays.
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)
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?