3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-25 10:05:32 +00:00

fixes to #1155 and partial introduction of SMTLIB 2.6 datatype format

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-07-24 09:12:43 -07:00
parent 2b0106c199
commit a0a8bc2a62
13 changed files with 452 additions and 156 deletions

View file

@ -53,6 +53,8 @@ namespace smt2 {
dictionary<int> m_sort_id2param_idx;
dictionary<int> m_dt_name2idx;
dictionary<unsigned> m_dt_name2arity;
svector<symbol> m_dt_names;
scoped_ptr<psort_ref_vector> m_psort_stack;
scoped_ptr<sort_ref_vector> m_sort_stack;
@ -97,6 +99,8 @@ namespace smt2 {
symbol m_define_sort;
symbol m_declare_sort;
symbol m_declare_datatypes;
symbol m_declare_datatype;
symbol m_par;
symbol m_push;
symbol m_pop;
symbol m_get_value;
@ -367,6 +371,13 @@ namespace smt2 {
symbol const & curr_id() const { return m_scanner.get_id(); }
rational curr_numeral() const { return m_scanner.get_number(); }
unsigned curr_unsigned() {
rational n = curr_numeral();
if (!n.is_unsigned())
throw parser_exception("invalid indexed identifier, index is too big to fit in an unsigned machine integer");
return n.get_unsigned();
}
bool curr_is_identifier() const { return curr() == scanner::SYMBOL_TOKEN; }
bool curr_is_keyword() const { return curr() == scanner::KEYWORD_TOKEN; }
@ -400,6 +411,8 @@ namespace smt2 {
void check_int(char const * msg) { if (!curr_is_int()) throw parser_exception(msg); }
void check_int_or_float(char const * msg) { if (!curr_is_int() && !curr_is_float()) throw parser_exception(msg); }
void check_float(char const * msg) { if (!curr_is_float()) throw parser_exception(msg); }
symbol check_identifier_next(char const * msg) { check_identifier(msg); symbol s = curr_id(); next(); return s; }
char const * m_current_file;
void set_current_file(char const * s) { m_current_file = s; }
@ -550,7 +563,7 @@ namespace smt2 {
return r;
}
psort * parse_psort_name(bool ignore_unknow_sort = false) {
psort * parse_psort_name(bool ignore_unknown_sort = false) {
SASSERT(curr_is_identifier());
symbol id = curr_id();
psort_decl * d = m_ctx.find_psort_decl(id);
@ -567,10 +580,10 @@ namespace smt2 {
return pm().mk_psort_var(m_sort_id2param_idx.size(), idx);
}
else {
if (ignore_unknow_sort)
return 0;
unknown_sort(id);
UNREACHABLE();
if (!ignore_unknown_sort) {
unknown_sort(id);
UNREACHABLE();
}
return 0;
}
}
@ -580,19 +593,15 @@ namespace smt2 {
SASSERT(curr_is_identifier());
SASSERT(curr_id_is_underscore());
next();
check_identifier("invalid indexed sort, symbol expected");
symbol id = curr_id();
symbol id = check_identifier_next("invalid indexed sort, symbol expected");
psort_decl * d = m_ctx.find_psort_decl(id);
if (d == 0)
unknown_sort(id);
next();
sbuffer<unsigned> args;
while (!curr_is_rparen()) {
check_int("invalid indexed sort, integer or ')' expected");
rational n = curr_numeral();
if (!n.is_unsigned())
throw parser_exception("invalid indexed sort, index is too big to fit in an unsigned machine integer");
args.push_back(n.get_unsigned());
unsigned u = curr_unsigned();
args.push_back(u);
next();
}
if (args.empty())
@ -608,8 +617,17 @@ namespace smt2 {
SASSERT(curr_is_identifier());
symbol id = curr_id();
psort_decl * d = m_ctx.find_psort_decl(id);
if (d == 0)
unknown_sort(id);
int idx = 0;
if (d == 0) {
if (m_dt_name2idx.find(id, idx)) {
unsigned num_params = m_dt_name2arity.find(id);
throw parser_exception("smtlib 2.6 parametric datatype sorts are not supported");
// d = pm().mk_psort_dt_decl(num_params, id);
}
else {
unknown_sort(id);
}
}
next();
void * mem = m_stack.allocate(sizeof(psort_frame));
new (mem) psort_frame(*this, d, psort_stack().size());
@ -627,6 +645,7 @@ namespace smt2 {
TRACE("smt2parser", tout << "num: " << num << ", d->get_num_params(): " << d->get_num_params() << "\n";);
throw parser_exception("invalid number of parameters to sort constructor");
}
psort * r = pm().mk_psort_app(m_sort_id2param_idx.size(), d, num, psort_stack().c_ptr() + spos);
psort_stack().shrink(spos);
psort_stack().push_back(r);
@ -634,13 +653,13 @@ namespace smt2 {
next();
}
void parse_psort() {
void parse_psort(bool ignore_unknown_sort = false) {
unsigned stack_pos = psort_stack().size();
(void)stack_pos;
unsigned num_frames = 0;
do {
if (curr_is_identifier()) {
psort_stack().push_back(parse_psort_name());
psort_stack().push_back(parse_psort_name(false));
}
else if (curr_is_rparen()) {
if (num_frames == 0)
@ -743,43 +762,46 @@ namespace smt2 {
unsigned parse_symbols() {
unsigned sz = 0;
check_lparen_next("invalid list of symbols, '(' expected");
while (!curr_is_rparen()) {
check_identifier("invalid list of symbols, symbol or ')' expected");
m_symbol_stack.push_back(curr_id());
next();
while (!curr_is_rparen()) {
m_symbol_stack.push_back(check_identifier_next("invalid list of symbols, symbol or ')' expected"));
sz++;
}
next();
return sz;
}
ptype parse_ptype() {
SASSERT(curr_is_identifier());
psort * p = parse_psort_name(true);
ptype result;
if (p != 0) {
result = ptype(p);
}
else {
// parse_psort_name failed, identifier was not consumed.
int idx;
if (m_dt_name2idx.find(curr_id(), idx)) {
result = ptype(idx);
}
else {
result = ptype(curr_id());
}
SASSERT(curr_is_identifier());
next();
}
return result;
}
// [ '(' identifier sort ')' ]+
void parse_accessor_decls(paccessor_decl_ref_buffer & a_decls) {
while (!curr_is_rparen()) {
check_lparen_next("invalid datatype declaration, '(' or ')' expected");
check_identifier("invalid accessor declaration, symbol (accessor name) expected");
symbol a_name = curr_id();
next();
if (curr_is_identifier()) {
psort * p = parse_psort_name(true);
if (p != 0) {
a_decls.push_back(pm().mk_paccessor_decl(m_sort_id2param_idx.size(), a_name, ptype(p)));
}
else {
// parse_psort_name failed, identifier was not consumed.
int idx;
if (m_dt_name2idx.find(curr_id(), idx)) {
a_decls.push_back(pm().mk_paccessor_decl(m_sort_id2param_idx.size(), a_name, ptype(idx)));
}
else {
a_decls.push_back(pm().mk_paccessor_decl(m_sort_id2param_idx.size(), a_name, ptype(curr_id())));
}
SASSERT(curr_is_identifier());
next();
}
symbol a_name = check_identifier_next("invalid accessor declaration, symbol (accessor name) expected");
if (curr_is_identifier()) {
a_decls.push_back(pm().mk_paccessor_decl(m_sort_id2param_idx.size(), a_name, parse_ptype()));
}
else {
parse_psort();
parse_psort(true);
a_decls.push_back(pm().mk_paccessor_decl(m_sort_id2param_idx.size(), a_name, ptype(psort_stack().back())));
psort_stack().pop_back();
}
@ -816,46 +838,53 @@ namespace smt2 {
if (ct_decls.empty())
throw parser_exception("invalid datatype declaration, datatype does not have any constructors");
}
void parse_declare_datatypes() {
SASSERT(curr_is_identifier());
SASSERT(curr_id() == m_declare_datatypes);
next();
unsigned line = m_scanner.get_line();
unsigned pos = m_scanner.get_pos();
parse_sort_decl_params();
m_dt_name2idx.reset();
bool is_smt2_6 = parse_sort_decl_or_params();
unsigned i = 0;
pdatatype_decl_ref_buffer new_dt_decls(pm());
check_lparen_next("invalid datatype declaration, '(' expected");
pdatatype_decl_ref d(pm());
while (!curr_is_rparen()) {
check_lparen_next("invalid datatype declaration, '(' or ')' expected");
check_identifier("invalid datatype declaration, symbol (datatype name) expected");
symbol dt_name = curr_id();
next();
m_dt_name2idx.insert(dt_name, i);
pconstructor_decl_ref_buffer new_ct_decls(pm());
parse_constructor_decls(new_ct_decls);
new_dt_decls.push_back(pm().mk_pdatatype_decl(m_sort_id2param_idx.size(), dt_name, new_ct_decls.size(), new_ct_decls.c_ptr()));
check_rparen_next("invalid datatype declaration, ')' expected");
if (is_smt2_6) {
if (i >= m_dt_names.size()) {
throw parser_exception("invalid datatype declaration, too many data-type bodies defined");
}
symbol dt_name = m_dt_names[i];
parse_datatype_dec(new_ct_decls);
d = pm().mk_pdatatype_decl(m_dt_name2arity.find(dt_name), dt_name, new_ct_decls.size(), new_ct_decls.c_ptr());
}
else {
check_lparen_next("invalid datatype declaration, '(' or ')' expected");
symbol dt_name = check_identifier_next("invalid datatype declaration, symbol (datatype name) expected");
m_dt_name2idx.insert(dt_name, i);
parse_constructor_decls(new_ct_decls);
d = pm().mk_pdatatype_decl(m_sort_id2param_idx.size(), dt_name, new_ct_decls.size(), new_ct_decls.c_ptr());
check_rparen_next("invalid datatype declaration, ')' expected");
}
new_dt_decls.push_back(d);
i++;
}
if (i < m_dt_names.size()) {
throw parser_exception("invalid datatype declaration, too few datatype definitions compared to declared sorts");
}
next();
check_rparen("invalid datatype declaration");
unsigned sz = new_dt_decls.size();
if (sz == 0) {
m_ctx.print_success();
next();
m_ctx.print_success();
next();
return;
}
}
else if (sz == 1) {
symbol missing;
if (new_dt_decls[0]->has_missing_refs(missing)) {
std::string err_msg = "invalid datatype declaration, unknown sort '";
err_msg += missing.str();
err_msg += "'";
throw parser_exception(err_msg, line, pos);
}
check_missing(new_dt_decls[0], line, pos);
}
else {
SASSERT(sz > 1);
@ -874,12 +903,7 @@ namespace smt2 {
pdatatype_decl * d = new_dt_decls[i];
SASSERT(d != 0);
symbol duplicated;
if (d->has_duplicate_accessors(duplicated)) {
std::string err_msg = "invalid datatype declaration, repeated accessor identifier '";
err_msg += duplicated.str();
err_msg += "'";
throw parser_exception(err_msg, line, pos);
}
check_duplicate(d, line, pos);
m_ctx.insert(d);
if (d->get_num_params() == 0) {
// if datatype is not parametric... then force instantiation to register accessor, recognizers and constructors...
@ -890,7 +914,85 @@ namespace smt2 {
TRACE("declare_datatypes", tout << "i: " << i << " new_dt_decls.size(): " << sz << "\n";
for (unsigned i = 0; i < sz; i++) tout << new_dt_decls[i]->get_name() << "\n";);
m_ctx.print_success();
next();
next();
}
// (declare-datatypes ( sort_dec n+1 ) ( datatype_dec n+1 ) )
void parse_declare_datatypes_smt2() {
}
// ( declare-datatype symbol datatype_dec)
void parse_declare_datatype() {
SASSERT(curr_is_identifier());
SASSERT(curr_id() == m_declare_datatype);
next();
unsigned line = m_scanner.get_line();
unsigned pos = m_scanner.get_pos();
symbol dt_name = curr_id();
next();
m_dt_name2idx.reset();
m_dt_name2idx.insert(dt_name, 0);
m_sort_id2param_idx.reset();
pdatatype_decl_ref d(pm());
pconstructor_decl_ref_buffer new_ct_decls(pm());
parse_datatype_dec(new_ct_decls);
d = pm().mk_pdatatype_decl(m_sort_id2param_idx.size(), dt_name, new_ct_decls.size(), new_ct_decls.c_ptr());
check_missing(d, line, pos);
check_duplicate(d, line, pos);
m_ctx.insert(d);
if (d->get_num_params() == 0) {
// if datatype is not parametric... then force instantiation to register accessor, recognizers and constructors...
sort_ref s(m());
s = d->instantiate(pm(), 0, 0);
}
check_rparen_next("invalid end of datatype declaration, ')' expected");
m_ctx.print_success();
}
// datatype_dec ::= ( constructor_dec+ ) | ( par ( symbol+ ) ( constructor_dec+ ) )
void parse_datatype_dec(pconstructor_decl_ref_buffer & ct_decls) {
check_lparen_next("invalid datatype declaration, '(' expected");
if (curr_id() == m_par) {
next();
parse_sort_decl_params();
check_lparen_next("invalid constructor declaration after par, '(' expected");
parse_constructor_decls(ct_decls);
check_rparen_next("invalid datatype declaration, ')' expected");
}
else {
parse_constructor_decls(ct_decls);
}
check_rparen_next("invalid datatype declaration, ')' expected");
}
void check_missing(pdatatype_decl* d, unsigned line, unsigned pos) {
symbol missing;
if (d->has_missing_refs(missing)) {
std::string err_msg = "invalid datatype declaration, unknown sort '";
err_msg += missing.str();
err_msg += "'";
throw parser_exception(err_msg, line, pos);
}
}
void check_duplicate(pdatatype_decl* d, unsigned line, unsigned pos) {
symbol duplicated;
if (d->has_duplicate_accessors(duplicated)) {
std::string err_msg = "invalid datatype declaration, repeated accessor identifier '";
err_msg += duplicated.str();
err_msg += "'";
throw parser_exception(err_msg, line, pos);
}
}
void name_expr(expr * n, symbol const & s) {
@ -970,10 +1072,8 @@ namespace smt2 {
fr->m_last_symbol = symbol::null;
TRACE("consume_attributes", tout << "id: " << id << ", expr_stack().size(): " << expr_stack().size() << "\n";);
if (id == m_named) {
next();
check_identifier("invalid attribute value, symbol expected");
name_expr(expr_stack().back(), curr_id());
next();
next();
name_expr(expr_stack().back(), check_identifier_next("invalid attribute value, symbol expected"));
}
else if (id == m_lblpos || id == m_lblneg) {
next();
@ -989,18 +1089,13 @@ namespace smt2 {
check_in_quant_ctx(fr);
next();
check_int("invalid weight attribute, integer expected");
rational n = curr_numeral();
if (!n.is_unsigned())
throw parser_exception("invalid weight attribute, value is too big to fit in an unsigned machine integer");
store_weight(fr, n.get_unsigned());
store_weight(fr, curr_unsigned());
next();
}
else if (id == m_skid) {
check_in_quant_ctx(fr);
next();
check_identifier("invalid attribute value, symbol expected");
store_skid(fr, curr_id());
next();
next();
store_skid(fr, check_identifier_next("invalid attribute value, symbol expected"));
}
else if (id == m_qid) {
check_in_quant_ctx(fr);
@ -1207,10 +1302,8 @@ namespace smt2 {
unsigned num_indices = 0;
while (!curr_is_rparen()) {
if (curr_is_int()) {
rational n = curr_numeral();
if (!n.is_unsigned())
throw parser_exception("invalid indexed identifier, index is too big to fit in an unsigned machine integer");
m_param_stack.push_back(parameter(n.get_unsigned()));
unsigned u = curr_unsigned();
m_param_stack.push_back(parameter(u));
next();
}
else if (curr_is_identifier() || curr_is_lparen()) {
@ -1786,8 +1879,8 @@ namespace smt2 {
}
void parse_sort_decl_params() {
check_lparen_next("invalid sort declaration, parameters missing");
m_sort_id2param_idx.reset();
check_lparen_next("invalid sort declaration, parameters missing");
unsigned i = 0;
while (!curr_is_rparen()) {
check_identifier("invalid sort parameter, symbol or ')' expected");
@ -1795,7 +1888,43 @@ namespace smt2 {
i++;
next();
}
next();
next();
}
bool parse_sort_decl_or_params() {
m_sort_id2param_idx.reset();
m_dt_name2arity.reset();
m_dt_name2idx.reset();
m_dt_names.reset();
check_lparen_next("invalid sort declaration, parameters missing");
unsigned i = 0;
bool first = true;
bool is_decl = false;
while (!curr_is_rparen()) {
if (first) {
is_decl = curr_is_lparen();
first = false;
}
if (is_decl) {
check_lparen_next("invalid sort declaration, '(' expected");
symbol dt_name = check_identifier_next("invalid sort name, identified expected");
check_int("invalid sort declaration, arity expected");
unsigned u = curr_unsigned();
next();
m_dt_name2idx.insert(dt_name, i);
m_dt_name2arity.insert(dt_name, u);
m_dt_names.push_back(dt_name);
check_rparen("invalid sort declaration, ')' expected");
}
else {
check_identifier("invalid sort parameter, symbol or ')' expected");
m_sort_id2param_idx.insert(curr_id(), i);
}
i++;
next();
}
next();
return is_decl;
}
void parse_declare_sort() {
@ -1814,10 +1943,8 @@ namespace smt2 {
}
else {
check_int("invalid sort declaration, arity (<numeral>) or ')' expected");
rational n = curr_numeral();
if (!n.is_unsigned())
throw parser_exception("invalid sort declaration, arity is too big to fit in an unsigned machine integer");
psort_decl * decl = pm().mk_psort_user_decl(n.get_unsigned(), id, 0);
unsigned u = curr_unsigned();
psort_decl * decl = pm().mk_psort_user_decl(u, id, 0);
m_ctx.insert(decl);
next();
check_rparen("invalid sort declaration, ')' expected");
@ -2222,9 +2349,7 @@ namespace smt2 {
if (curr_is_keyword() && (curr_id() == ":model-index" || curr_id() == ":model_index")) {
next();
check_int("integer index expected to indexed model evaluation");
if (!curr_numeral().is_unsigned())
throw parser_exception("expected unsigned integer index to model evaluation");
index = curr_numeral().get_unsigned();
index = curr_unsigned();
next();
}
@ -2315,10 +2440,8 @@ namespace smt2 {
next();
while (!curr_is_rparen()) {
check_int("invalid indexed function declaration reference, integer or ')' expected");
rational n = curr_numeral();
if (!n.is_unsigned())
throw parser_exception("invalid indexed function declaration reference, index is too big to fit in an unsigned machine integer");
indices.push_back(n.get_unsigned());
unsigned u = curr_unsigned();
indices.push_back(u);
next();
}
if (indices.empty())
@ -2350,10 +2473,8 @@ namespace smt2 {
switch (k) {
case CPK_UINT: {
check_int("invalid command argument, unsigned integer expected");
rational n = curr_numeral();
if (!n.is_unsigned())
throw parser_exception("invalid command argument, numeral is too big to fit in an unsigned machine integer");
m_curr_cmd->set_next_arg(m_ctx, n.get_unsigned());
unsigned u = curr_unsigned();
m_curr_cmd->set_next_arg(m_ctx, u);
next();
break;
}
@ -2554,6 +2675,10 @@ namespace smt2 {
parse_declare_datatypes();
return;
}
if (s == m_declare_datatype) {
parse_declare_datatype();
return;
}
if (s == m_get_value) {
parse_get_value();
return;
@ -2610,6 +2735,8 @@ namespace smt2 {
m_define_sort("define-sort"),
m_declare_sort("declare-sort"),
m_declare_datatypes("declare-datatypes"),
m_declare_datatype("declare-datatype"),
m_par("par"),
m_push("push"),
m_pop("pop"),
m_get_value("get-value"),