diff --git a/scripts/mk_util.py b/scripts/mk_util.py
index 6d3ad3d4b..12ccc538c 100644
--- a/scripts/mk_util.py
+++ b/scripts/mk_util.py
@@ -2393,7 +2393,50 @@ class DotNetExampleComponent(ExampleComponent):
out.write('\n')
out.write('_ex_%s: %s\n\n' % (self.name, exefile))
if is_dotnet_core_enabled():
- print("TBD: build script for dotnet_example on core")
+ proj_name = 'dotnet_example.csproj'
+ out.write('_ex_%s:' % self.name)
+ for csfile in get_cs_files(self.ex_dir):
+ out.write(' ')
+ out.write(os.path.join(self.to_ex_dir, csfile))
+
+ def mk_echo(msg, first = False):
+ echo_ex_qu = '' if IS_WINDOWS else '"'
+ echo_in_qu = '"' if IS_WINDOWS else '\\"'
+ echo_esc = '^' if IS_WINDOWS else ''
+ echo_dir = '>' if first else '>>'
+
+ msg = msg.replace('"', echo_in_qu).replace('<', echo_esc + '<').replace('>', echo_esc + '>')
+ out.write('\t@echo %s%s%s %s %s\n' % (echo_ex_qu, msg, echo_ex_qu, echo_dir, proj_name))
+
+ out.write('\n')
+ mk_echo('', True)
+ mk_echo(' ')
+ mk_echo(' Exe')
+ mk_echo(' netcoreapp2.0')
+ if VS_X64:
+ platform = 'x64'
+ elif VS_ARM:
+ platform = 'ARM'
+ else:
+ platform = 'x86'
+ mk_echo(' %s' % platform)
+ mk_echo(' ')
+ mk_echo(' ')
+ mk_echo(' ' % self.to_ex_dir)
+ mk_echo(' ')
+ mk_echo(' Microsoft.Z3.dll')
+ mk_echo(' ')
+ mk_echo(' ')
+ mk_echo('')
+
+ dotnetCmdLine = [DOTNET, "build", proj_name]
+ dotnetCmdLine.extend(['-c'])
+ if DEBUG_MODE:
+ dotnetCmdLine.extend(['Debug'])
+ else:
+ dotnetCmdLine.extend(['Release'])
+ MakeRuleCmd.write_cmd(out, ' '.join(dotnetCmdLine))
+ out.write('\n')
class JavaExampleComponent(ExampleComponent):
def __init__(self, name, path):
diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp
index cb4ae19db..a5ad7b525 100644
--- a/src/api/api_solver.cpp
+++ b/src/api/api_solver.cpp
@@ -183,8 +183,12 @@ extern "C" {
}
else if (ext && std::string("dimacs") == ext) {
ast_manager& m = to_solver_ref(s)->get_manager();
+ std::stringstream err;
sat::solver solver(to_solver_ref(s)->get_params(), m.limit());
- parse_dimacs(is, solver);
+ if (!parse_dimacs(is, err, solver)) {
+ SET_ERROR_CODE(Z3_PARSER_ERROR, err.str().c_str());
+ return;
+ }
sat2goal s2g;
ref mc;
atom2bool_var a2b(m);
diff --git a/src/ast/rewriter/seq_rewriter.cpp b/src/ast/rewriter/seq_rewriter.cpp
index dad485d94..82607452f 100644
--- a/src/ast/rewriter/seq_rewriter.cpp
+++ b/src/ast/rewriter/seq_rewriter.cpp
@@ -561,6 +561,7 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu
zstring s;
rational pos, len;
+ TRACE("seq", tout << mk_pp(a, m()) << " " << mk_pp(b, m()) << " " << mk_pp(c, m()) << "\n";);
bool constantBase = m_util.str.is_string(a, s);
bool constantPos = m_autil.is_numeral(b, pos);
bool constantLen = m_autil.is_numeral(c, len);
@@ -599,6 +600,10 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu
SASSERT(_len > 0);
expr_ref_vector as(m()), bs(m());
m_util.str.get_concat(a, as);
+ if (as.empty()) {
+ result = a;
+ return BR_DONE;
+ }
for (unsigned i = 0; i < as.size() && _len > 0; ++i) {
if (m_util.str.is_unit(as[i].get())) {
if (_pos == 0) {
@@ -613,7 +618,12 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu
return BR_FAILED;
}
}
- result = m_util.str.mk_concat(bs);
+ if (bs.empty()) {
+ result = m_util.str.mk_empty(m().get_sort(a));
+ }
+ else {
+ result = m_util.str.mk_concat(bs);
+ }
return BR_DONE;
}
diff --git a/src/parsers/smt2/smt2parser.cpp b/src/parsers/smt2/smt2parser.cpp
index 106a77c0e..64f9c36fd 100644
--- a/src/parsers/smt2/smt2parser.cpp
+++ b/src/parsers/smt2/smt2parser.cpp
@@ -346,7 +346,8 @@ namespace smt2 {
// consume garbage
// return true if managed to recover from the error...
bool sync_after_error() {
- while (true) {
+ unsigned num_errors = 0;
+ while (num_errors < 100) {
try {
while (curr_is_rparen())
next();
@@ -374,8 +375,10 @@ namespace smt2 {
catch (scanner_exception & ex) {
SASSERT(ex.has_pos());
error(ex.line(), ex.pos(), ex.msg());
+ ++num_errors;
}
}
+ return false;
}
void check_next(scanner::token t, char const * msg) {
@@ -3117,7 +3120,7 @@ namespace smt2 {
bool operator()() {
m_num_bindings = 0;
- bool found_errors = false;
+ unsigned found_errors = 0;
try {
scan_core();
@@ -3126,7 +3129,7 @@ namespace smt2 {
error(ex.msg());
if (!sync_after_error())
return false;
- found_errors = true;
+ found_errors++;
}
while (true) {
@@ -3138,7 +3141,7 @@ namespace smt2 {
parse_cmd();
break;
case scanner::EOF_TOKEN:
- return !found_errors;
+ return found_errors == 0;
default:
throw parser_exception("invalid command, '(' expected");
break;
diff --git a/src/sat/dimacs.cpp b/src/sat/dimacs.cpp
index 463418b23..970e682b3 100644
--- a/src/sat/dimacs.cpp
+++ b/src/sat/dimacs.cpp
@@ -21,6 +21,8 @@ Revision History:
#undef min
#include "sat/sat_solver.h"
+struct lex_error {};
+
class stream_buffer {
std::istream & m_stream;
int m_val;
@@ -67,7 +69,7 @@ void skip_line(Buffer & in) {
}
template
-int parse_int(Buffer & in) {
+int parse_int(Buffer & in, std::ostream& err) {
int val = 0;
bool neg = false;
skip_whitespace(in);
@@ -81,9 +83,8 @@ int parse_int(Buffer & in) {
}
if (*in < '0' || *in > '9') {
- std::cerr << "(error, \"unexpected char: " << *in << " line: " << in.line() << "\")\n";
- exit(3);
- exit(ERR_PARSER);
+ err << "(error, \"unexpected char: " << *in << " line: " << in.line() << "\")\n";
+ throw lex_error();
}
while (*in >= '0' && *in <= '9') {
@@ -95,14 +96,14 @@ int parse_int(Buffer & in) {
}
template
-void read_clause(Buffer & in, sat::solver & solver, sat::literal_vector & lits) {
+void read_clause(Buffer & in, std::ostream& err, sat::solver & solver, sat::literal_vector & lits) {
int parsed_lit;
int var;
lits.reset();
while (true) {
- parsed_lit = parse_int(in);
+ parsed_lit = parse_int(in, err);
if (parsed_lit == 0)
break;
var = abs(parsed_lit);
@@ -114,24 +115,30 @@ void read_clause(Buffer & in, sat::solver & solver, sat::literal_vector & lits)
}
template
-void parse_dimacs_core(Buffer & in, sat::solver & solver) {
+bool parse_dimacs_core(Buffer & in, std::ostream& err, sat::solver & solver) {
sat::literal_vector lits;
- while (true) {
- skip_whitespace(in);
- if (*in == EOF) {
- break;
- }
- else if (*in == 'c' || *in == 'p') {
- skip_line(in);
- }
- else {
- read_clause(in, solver, lits);
- solver.mk_clause(lits.size(), lits.c_ptr());
+ try {
+ while (true) {
+ skip_whitespace(in);
+ if (*in == EOF) {
+ break;
+ }
+ else if (*in == 'c' || *in == 'p') {
+ skip_line(in);
+ }
+ else {
+ read_clause(in, err, solver, lits);
+ solver.mk_clause(lits.size(), lits.c_ptr());
+ }
}
}
+ catch (lex_error) {
+ return false;
+ }
+ return true;
}
-void parse_dimacs(std::istream & in, sat::solver & solver) {
+bool parse_dimacs(std::istream & in, std::ostream& err, sat::solver & solver) {
stream_buffer _in(in);
- parse_dimacs_core(_in, solver);
+ return parse_dimacs_core(_in, err, solver);
}
diff --git a/src/sat/dimacs.h b/src/sat/dimacs.h
index 50ebec0c8..4c5d51502 100644
--- a/src/sat/dimacs.h
+++ b/src/sat/dimacs.h
@@ -21,7 +21,7 @@ Revision History:
#include "sat/sat_types.h"
-void parse_dimacs(std::istream & s, sat::solver & solver);
+bool parse_dimacs(std::istream & s, std::ostream& err, sat::solver & solver);
#endif /* DIMACS_PARSER_H_ */
diff --git a/src/shell/dimacs_frontend.cpp b/src/shell/dimacs_frontend.cpp
index 3a2af72cf..738566ce2 100644
--- a/src/shell/dimacs_frontend.cpp
+++ b/src/shell/dimacs_frontend.cpp
@@ -136,7 +136,7 @@ void verify_solution(char const * file_name) {
std::cerr << "(error \"failed to open file '" << file_name << "'\")" << std::endl;
exit(ERR_OPEN_FILE);
}
- parse_dimacs(in, solver);
+ parse_dimacs(in, std::cerr, solver);
sat::model const & m = g_solver->get_model();
for (unsigned i = 1; i < m.size(); i++) {
@@ -178,10 +178,10 @@ unsigned read_dimacs(char const * file_name) {
std::cerr << "(error \"failed to open file '" << file_name << "'\")" << std::endl;
exit(ERR_OPEN_FILE);
}
- parse_dimacs(in, solver);
+ parse_dimacs(in, std::cerr, solver);
}
else {
- parse_dimacs(std::cin, solver);
+ parse_dimacs(std::cin, std::cerr, solver);
}
IF_VERBOSE(20, solver.display_status(verbose_stream()););