Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b97d3a1

Browse files
author
Daniel Kroening
committedNov 25, 2018
exception based error handling for SMT2 files
1 parent b0a6201 commit b97d3a1

File tree

7 files changed

+357
-465
lines changed

7 files changed

+357
-465
lines changed
 
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
function-application2.smt2
33

4-
^EXIT=134$
4+
^EXIT=20$
55
^SIGNAL=0$
66
^\(error "line 5: type mismatch in function definition: expected `\(_ BitVec 16\)' but got `\(_ BitVec 8\)'"\)$
77
--

‎src/solvers/smt2/smt2_parser.cpp

Lines changed: 167 additions & 305 deletions
Large diffs are not rendered by default.

‎src/solvers/smt2/smt2_parser.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class smt2_parsert:public smt2_tokenizert
2626
bool parse() override
2727
{
2828
command_sequence();
29-
return !ok;
29+
return false;
3030
}
3131

3232
struct idt
@@ -51,12 +51,12 @@ class smt2_parsert:public smt2_tokenizert
5151
const typet type;
5252
};
5353

54+
bool exit;
55+
5456
/// This skips tokens until all bracketed expressions are closed
5557
void skip_to_end_of_list();
5658

5759
protected:
58-
bool exit;
59-
6060
// we override next_token to track the parenthesis level
6161
std::size_t parenthesis_level;
6262
tokent next_token() override;

‎src/solvers/smt2/smt2_solver.cpp

Lines changed: 87 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -121,99 +121,88 @@ void smt2_solvert::expand_function_applications(exprt &expr)
121121

122122
void smt2_solvert::command(const std::string &c)
123123
{
124-
try
124+
if(c == "assert")
125125
{
126-
if(c=="assert")
126+
exprt e = expression();
127+
if(e.is_not_nil())
127128
{
128-
exprt e=expression();
129-
if(e.is_not_nil())
130-
{
131-
expand_function_applications(e);
132-
define_constants(e);
133-
solver.set_to_true(e);
134-
}
129+
expand_function_applications(e);
130+
define_constants(e);
131+
solver.set_to_true(e);
135132
}
136-
else if(c=="check-sat")
133+
}
134+
else if(c == "check-sat")
135+
{
136+
switch(solver())
137137
{
138-
switch(solver())
139-
{
140-
case decision_proceduret::resultt::D_SATISFIABLE:
141-
std::cout << "sat\n";
142-
break;
138+
case decision_proceduret::resultt::D_SATISFIABLE:
139+
std::cout << "sat\n";
140+
break;
143141

144-
case decision_proceduret::resultt::D_UNSATISFIABLE:
145-
std::cout << "unsat\n";
146-
break;
142+
case decision_proceduret::resultt::D_UNSATISFIABLE:
143+
std::cout << "unsat\n";
144+
break;
147145

148-
case decision_proceduret::resultt::D_ERROR:
149-
std::cout << "error\n";
150-
}
151-
}
152-
else if(c=="check-sat-assuming")
153-
{
154-
std::cout << "not yet implemented\n";
155-
}
156-
else if(c=="display")
157-
{
158-
// this is a command that Z3 appears to implement
159-
exprt e=expression();
160-
if(e.is_not_nil())
161-
{
162-
std::cout << e.pretty() << '\n'; // need to do an 'smt2_format'
163-
}
164-
}
165-
else if(c=="simplify")
166-
{
167-
// this is a command that Z3 appears to implement
168-
exprt e=expression();
169-
if(e.is_not_nil())
170-
{
171-
const symbol_tablet symbol_table;
172-
const namespacet ns(symbol_table);
173-
exprt e_simplified=simplify_expr(e, ns);
174-
std::cout << e.pretty() << '\n'; // need to do an 'smt2_format'
175-
}
146+
case decision_proceduret::resultt::D_ERROR:
147+
std::cout << "error\n";
176148
}
177-
#if 0
178-
// TODO:
179-
| ( declare-const hsymboli hsorti )
180-
| ( declare-datatype hsymboli hdatatype_deci)
181-
| ( declare-datatypes ( hsort_deci n+1 ) ( hdatatype_deci n+1 ) )
182-
| ( declare-fun hsymboli ( hsorti ??? ) hsorti )
183-
| ( declare-sort hsymboli hnumerali )
184-
| ( define-fun hfunction_def i )
185-
| ( define-fun-rec hfunction_def i )
186-
| ( define-funs-rec ( hfunction_deci n+1 ) ( htermi n+1 ) )
187-
| ( define-sort hsymboli ( hsymboli ??? ) hsorti )
188-
| ( echo hstringi )
189-
| ( exit )
190-
| ( get-assertions )
191-
| ( get-assignment )
192-
| ( get-info hinfo_flag i )
193-
| ( get-model )
194-
| ( get-option hkeywordi )
195-
| ( get-proof )
196-
| ( get-unsat-assumptions )
197-
| ( get-unsat-core )
198-
| ( get-value ( htermi + ) )
199-
| ( pop hnumerali )
200-
| ( push hnumerali )
201-
| ( reset )
202-
| ( reset-assertions )
203-
| ( set-info hattributei )
204-
| ( set-option hoptioni )
205-
#endif
206-
else
207-
smt2_parsert::command(c);
208149
}
209-
catch(const char *error)
150+
else if(c == "check-sat-assuming")
151+
{
152+
std::cout << "not yet implemented\n";
153+
}
154+
else if(c == "display")
210155
{
211-
std::cout << "error: " << error << '\n';
156+
// this is a command that Z3 appears to implement
157+
exprt e = expression();
158+
if(e.is_not_nil())
159+
{
160+
std::cout << e.pretty() << '\n'; // need to do an 'smt2_format'
161+
}
212162
}
213-
catch(const std::string &error)
163+
else if(c == "simplify")
214164
{
215-
std::cout << "error: " << error << '\n';
165+
// this is a command that Z3 appears to implement
166+
exprt e = expression();
167+
if(e.is_not_nil())
168+
{
169+
const symbol_tablet symbol_table;
170+
const namespacet ns(symbol_table);
171+
exprt e_simplified = simplify_expr(e, ns);
172+
std::cout << e.pretty() << '\n'; // need to do an 'smt2_format'
173+
}
216174
}
175+
#if 0
176+
// TODO:
177+
| ( declare-const hsymboli hsorti )
178+
| ( declare-datatype hsymboli hdatatype_deci)
179+
| ( declare-datatypes ( hsort_deci n+1 ) ( hdatatype_deci n+1 ) )
180+
| ( declare-fun hsymboli ( hsorti ??? ) hsorti )
181+
| ( declare-sort hsymboli hnumerali )
182+
| ( define-fun hfunction_def i )
183+
| ( define-fun-rec hfunction_def i )
184+
| ( define-funs-rec ( hfunction_deci n+1 ) ( htermi n+1 ) )
185+
| ( define-sort hsymboli ( hsymboli ??? ) hsorti )
186+
| ( echo hstringi )
187+
| ( exit )
188+
| ( get-assertions )
189+
| ( get-assignment )
190+
| ( get-info hinfo_flag i )
191+
| ( get-model )
192+
| ( get-option hkeywordi )
193+
| ( get-proof )
194+
| ( get-unsat-assumptions )
195+
| ( get-unsat-core )
196+
| ( get-value ( htermi + ) )
197+
| ( pop hnumerali )
198+
| ( push hnumerali )
199+
| ( reset )
200+
| ( reset-assertions )
201+
| ( set-info hattributei )
202+
| ( set-option hoptioni )
203+
#endif
204+
else
205+
smt2_parsert::command(c);
217206
}
218207

219208
class smt2_message_handlert : public message_handlert
@@ -261,10 +250,25 @@ int solver(std::istream &in)
261250

262251
smt2_solvert smt2_solver(in, boolbv);
263252
smt2_solver.set_message_handler(message_handler);
253+
bool error_found = false;
264254

265-
smt2_solver.parse();
255+
while(!smt2_solver.exit)
256+
{
257+
try
258+
{
259+
smt2_solver.parse();
260+
}
261+
catch(const smt2_solvert::smt2_errort &error)
262+
{
263+
smt2_solver.skip_to_end_of_list();
264+
error_found = true;
265+
messaget message(message_handler);
266+
message.error().source_location.set_line(error.get_line_no());
267+
message.error() << error.what() << messaget::eom;
268+
}
269+
}
266270

267-
if(!smt2_solver)
271+
if(error_found)
268272
return 20;
269273
else
270274
return 0;

‎src/solvers/smt2/smt2_tokenizer.cpp

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,7 @@ smt2_tokenizert::tokent smt2_tokenizert::get_quoted_symbol()
159159
}
160160

161161
// Hmpf. Eof before end of quoted symbol. This is an error.
162-
error() << "EOF within quoted symbol" << eom;
163-
return ERROR;
162+
throw error("EOF within quoted symbol");
164163
}
165164

166165
smt2_tokenizert::tokent smt2_tokenizert::get_string_literal()
@@ -191,8 +190,7 @@ smt2_tokenizert::tokent smt2_tokenizert::get_string_literal()
191190
}
192191

193192
// Hmpf. Eof before end of string literal. This is an error.
194-
error() << "EOF within string literal" << eom;
195-
return ERROR;
193+
throw error("EOF within string literal");
196194
}
197195

198196
smt2_tokenizert::tokent smt2_tokenizert::next_token()
@@ -272,18 +270,10 @@ void smt2_tokenizert::get_token_from_stream()
272270
return;
273271
}
274272
else
275-
{
276-
error() << "unknown numeral token" << eom;
277-
token=ERROR;
278-
return;
279-
}
273+
throw error("unknown numeral token");
280274
}
281275
else
282-
{
283-
error() << "unexpected EOF in numeral token" << eom;
284-
token=ERROR;
285-
return;
286-
}
276+
throw error("unexpected EOF in numeral token");
287277
break;
288278

289279
default: // likely a simple symbol or a numeral
@@ -302,9 +292,9 @@ void smt2_tokenizert::get_token_from_stream()
302292
else
303293
{
304294
// illegal character, error
305-
error() << "unexpected character `" << ch << '\'' << eom;
306-
token=ERROR;
307-
return;
295+
std::ostringstream msg;
296+
msg << "unexpected character `" << ch << '\'';
297+
throw error(msg.str());
308298
}
309299
}
310300
}

‎src/solvers/smt2/smt2_tokenizer.h

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,60 @@ Author: Daniel Kroening, kroening@kroening.com
99
#ifndef CPROVER_SOLVERS_SMT2_SMT2_TOKENIZER_H
1010
#define CPROVER_SOLVERS_SMT2_SMT2_TOKENIZER_H
1111

12+
#include <util/exception_utils.h>
1213
#include <util/parser.h>
1314

1415
#include <string>
1516

1617
class smt2_tokenizert:public parsert
1718
{
1819
public:
19-
explicit smt2_tokenizert(std::istream &_in)
20-
: ok(true), peeked(false), token(NONE)
20+
explicit smt2_tokenizert(std::istream &_in) : peeked(false), token(NONE)
2121
{
2222
in=&_in;
2323
line_no=1;
2424
}
2525

26-
operator bool()
26+
class smt2_errort : public cprover_exception_baset
2727
{
28-
return ok;
29-
}
28+
public:
29+
smt2_errort(const std::string &_message, unsigned _line_no)
30+
: message(_message), line_no(_line_no)
31+
{
32+
}
33+
34+
smt2_errort(std::string &&_message, unsigned _line_no)
35+
: message(std::move(_message)), line_no(_line_no)
36+
{
37+
}
38+
39+
std::string what() const override
40+
{
41+
return message;
42+
}
43+
44+
unsigned get_line_no() const
45+
{
46+
return line_no;
47+
}
48+
49+
protected:
50+
const std::string message;
51+
unsigned line_no;
52+
};
3053

3154
protected:
3255
std::string buffer;
33-
bool ok, peeked;
34-
using tokent=enum { NONE, END_OF_FILE, ERROR, STRING_LITERAL,
35-
NUMERAL, SYMBOL, OPEN, CLOSE };
56+
bool peeked;
57+
using tokent = enum {
58+
NONE,
59+
END_OF_FILE,
60+
STRING_LITERAL,
61+
NUMERAL,
62+
SYMBOL,
63+
OPEN,
64+
CLOSE
65+
};
3666
tokent token;
3767

3868
virtual tokent next_token();
@@ -49,17 +79,20 @@ class smt2_tokenizert:public parsert
4979
}
5080
}
5181

52-
mstreamt &error()
53-
{
54-
ok=false;
55-
messaget::error().source_location.set_line(line_no);
56-
return messaget::error();
57-
}
58-
5982
/// skip any tokens until all parentheses are closed
6083
/// or the end of file is reached
6184
void skip_to_end_of_list();
6285

86+
smt2_errort error(std::string &&message)
87+
{
88+
return smt2_errort(std::move(message), line_no);
89+
}
90+
91+
smt2_errort error(const std::ostringstream &message)
92+
{
93+
return smt2_errort(message.str(), line_no);
94+
}
95+
6396
private:
6497
tokent get_decimal_numeral();
6598
tokent get_hex_numeral();

‎src/solvers/smt2/smt2irep.cpp

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -33,60 +33,63 @@ class smt2irept:public smt2_tokenizert
3333

3434
bool smt2irept::parse()
3535
{
36-
std::stack<irept> stack;
37-
result.clear();
38-
39-
while(true)
36+
try
4037
{
41-
switch(next_token())
38+
std::stack<irept> stack;
39+
result.clear();
40+
41+
while(true)
4242
{
43-
case END_OF_FILE:
44-
error() << "unexpected end of file" << eom;
45-
return true;
46-
47-
case STRING_LITERAL:
48-
case NUMERAL:
49-
case SYMBOL:
50-
if(stack.empty())
43+
switch(next_token())
5144
{
52-
result=irept(buffer);
53-
return false; // all done!
54-
}
55-
else
56-
stack.top().get_sub().push_back(irept(buffer));
57-
break;
58-
59-
case OPEN: // '('
60-
// produce sub-irep
61-
stack.push(irept());
62-
break;
63-
64-
case CLOSE: // ')'
65-
// done with sub-irep
66-
if(stack.empty())
67-
{
68-
error() << "unexpected ')'" << eom;
69-
return true;
70-
}
71-
else
72-
{
73-
irept tmp=stack.top();
74-
stack.pop();
45+
case END_OF_FILE:
46+
throw error("unexpected end of file");
7547

48+
case STRING_LITERAL:
49+
case NUMERAL:
50+
case SYMBOL:
7651
if(stack.empty())
7752
{
78-
result=tmp;
53+
result = irept(buffer);
7954
return false; // all done!
8055
}
56+
else
57+
stack.top().get_sub().push_back(irept(buffer));
58+
break;
8159

82-
stack.top().get_sub().push_back(tmp);
60+
case OPEN: // '('
61+
// produce sub-irep
62+
stack.push(irept());
8363
break;
84-
}
8564

86-
default:
87-
return true;
65+
case CLOSE: // ')'
66+
// done with sub-irep
67+
if(stack.empty())
68+
throw error("unexpected ')'");
69+
else
70+
{
71+
irept tmp = stack.top();
72+
stack.pop();
73+
74+
if(stack.empty())
75+
{
76+
result = tmp;
77+
return false; // all done!
78+
}
79+
80+
stack.top().get_sub().push_back(tmp);
81+
break;
82+
}
83+
84+
default:
85+
throw error("unexpected token");
86+
}
8887
}
8988
}
89+
catch(smt2_errort)
90+
{
91+
return true;
92+
}
9093
}
9194

9295
irept smt2irep(std::istream &in)

0 commit comments

Comments
 (0)
Please sign in to comment.