15
15
// / `response_or_errort` in the case where the parse tree is of that type or
16
16
// / an empty optional otherwise.
17
17
18
- #include < solvers/smt2_incremental/ smt_response_validation.h>
18
+ #include " smt_response_validation.h"
19
19
20
+ #include < util/arith_tools.h>
20
21
#include < util/mp_arith.h>
21
22
#include < util/range.h>
22
23
@@ -190,15 +191,33 @@ static bool all_subs_are_pairs(const irept &parse_tree)
190
191
[](const irept &sub) { return sub.get_sub ().size () == 2 ; });
191
192
}
192
193
193
- static response_or_errort<irep_idt>
194
- validate_smt_identifier (const irept &parse_tree)
194
+ // / Checks for valid bit vector constants of the form `(_ bv(value) (width))`
195
+ // / for example - `(_ bv4 64)`.
196
+ static optionalt<smt_termt>
197
+ valid_smt_indexed_bit_vector (const irept &parse_tree)
195
198
{
196
- if (!parse_tree.get_sub ().empty () || parse_tree.id ().empty ())
197
- {
198
- return response_or_errort<irep_idt>(
199
- " Expected identifier, found - \" " + print_parse_tree (parse_tree) + " \" ." );
200
- }
201
- return response_or_errort<irep_idt>(parse_tree.id ());
199
+ if (parse_tree.get_sub ().size () != 3 )
200
+ return {};
201
+ if (parse_tree.get_sub ().at (0 ).id () != " _" )
202
+ return {};
203
+ const auto value_string = id2string (parse_tree.get_sub ().at (1 ).id ());
204
+ std::smatch match_results;
205
+ static const std::regex bv_value_regex{R"( ^bv(\d+)$)" , std::regex::optimize};
206
+ if (!std::regex_search (value_string, match_results, bv_value_regex))
207
+ return {};
208
+ INVARIANT (
209
+ match_results.size () == 2 ,
210
+ " Match results should include digits sub-expression if regex is matched." );
211
+ const std::string value_digits = match_results[1 ];
212
+ const auto value = string2integer (value_digits);
213
+ const auto bit_width_string = id2string (parse_tree.get_sub ().at (2 ).id ());
214
+ const auto bit_width =
215
+ numeric_cast_v<std::size_t >(string2integer (bit_width_string));
216
+ if (bit_width == 0 )
217
+ return {};
218
+ if (value >= power (mp_integer{2 }, bit_width))
219
+ return {};
220
+ return smt_bit_vector_constant_termt{value, bit_width};
202
221
}
203
222
204
223
static optionalt<smt_termt> valid_smt_bool (const irept &parse_tree)
@@ -229,7 +248,7 @@ static optionalt<smt_termt> valid_smt_hex(const std::string &text)
229
248
if (!std::regex_match (text, hex_format))
230
249
return {};
231
250
const std::string hex{text.begin () + 2 , text.end ()};
232
- // SMT-LIB 2 allows hex characters to be upper of lower case, but they should
251
+ // SMT-LIB 2 allows hex characters to be upper or lower case, but they should
233
252
// be upper case for mp_integer.
234
253
const mp_integer value =
235
254
string2integer (make_range (hex).map <std::function<int (int )>>(toupper), 16 );
@@ -240,6 +259,8 @@ static optionalt<smt_termt> valid_smt_hex(const std::string &text)
240
259
static optionalt<smt_termt>
241
260
valid_smt_bit_vector_constant (const irept &parse_tree)
242
261
{
262
+ if (const auto indexed = valid_smt_indexed_bit_vector (parse_tree))
263
+ return *indexed;
243
264
if (!parse_tree.get_sub ().empty () || parse_tree.id ().empty ())
244
265
return {};
245
266
const auto value_string = id2string (parse_tree.id ());
@@ -250,24 +271,52 @@ valid_smt_bit_vector_constant(const irept &parse_tree)
250
271
return {};
251
272
}
252
273
253
- static response_or_errort <smt_termt> validate_term (const irept &parse_tree)
274
+ static optionalt <smt_termt> valid_term (const irept &parse_tree)
254
275
{
255
276
if (const auto smt_bool = valid_smt_bool (parse_tree))
256
- return response_or_errort<smt_termt> {*smt_bool};
277
+ return {*smt_bool};
257
278
if (const auto bit_vector_constant = valid_smt_bit_vector_constant (parse_tree))
258
- return response_or_errort<smt_termt>{*bit_vector_constant};
279
+ return {*bit_vector_constant};
280
+ return {};
281
+ }
282
+
283
+ static response_or_errort<smt_termt> validate_term (const irept &parse_tree)
284
+ {
285
+ if (const auto term = valid_term (parse_tree))
286
+ return response_or_errort<smt_termt>{*term};
259
287
return response_or_errort<smt_termt>{" Unrecognised SMT term - \" " +
260
288
print_parse_tree (parse_tree) + " \" ." };
261
289
}
262
290
291
+ static response_or_errort<smt_termt>
292
+ validate_smt_descriptor (const irept &parse_tree, const smt_sortt &sort)
293
+ {
294
+ if (const auto term = valid_term (parse_tree))
295
+ return response_or_errort<smt_termt>{*term};
296
+ const auto id = parse_tree.id ();
297
+ if (!id.empty ())
298
+ return response_or_errort<smt_termt>{smt_identifier_termt{id, sort}};
299
+ return response_or_errort<smt_termt>{
300
+ " Expected descriptor SMT term, found - \" " + print_parse_tree (parse_tree) +
301
+ " \" ." };
302
+ }
303
+
263
304
static response_or_errort<smt_get_value_responset::valuation_pairt>
264
305
validate_valuation_pair (const irept &pair_parse_tree)
265
306
{
266
307
PRECONDITION (pair_parse_tree.get_sub ().size () == 2 );
267
308
const auto &descriptor = pair_parse_tree.get_sub ()[0 ];
268
309
const auto &value = pair_parse_tree.get_sub ()[1 ];
310
+ const response_or_errort<smt_termt> value_validation = validate_term (value);
311
+ if (const auto value_errors = value_validation.get_if_error ())
312
+ {
313
+ return response_or_errort<smt_get_value_responset::valuation_pairt>{
314
+ *value_errors};
315
+ }
316
+ const smt_termt value_term = *value_validation.get_if_valid ();
269
317
return validation_propagating<smt_get_value_responset::valuation_pairt>(
270
- validate_smt_identifier (descriptor), validate_term (value));
318
+ validate_smt_descriptor (descriptor, value_term.get_sort ()),
319
+ validate_term (value));
271
320
}
272
321
273
322
// / \returns: A response or error in the case where the parse tree appears to be
0 commit comments