1515// / `response_or_errort` in the case where the parse tree is of that type or
1616// / an empty optional otherwise.
1717
18- #include < solvers/smt2_incremental/ smt_response_validation.h>
18+ #include " smt_response_validation.h"
1919
20+ #include < util/arith_tools.h>
2021#include < util/mp_arith.h>
2122#include < util/range.h>
2223
@@ -190,15 +191,33 @@ static bool all_subs_are_pairs(const irept &parse_tree)
190191 [](const irept &sub) { return sub.get_sub ().size () == 2 ; });
191192}
192193
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)
195198{
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};
202221}
203222
204223static 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)
229248 if (!std::regex_match (text, hex_format))
230249 return {};
231250 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
233252 // be upper case for mp_integer.
234253 const mp_integer value =
235254 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)
240259static optionalt<smt_termt>
241260valid_smt_bit_vector_constant (const irept &parse_tree)
242261{
262+ if (const auto indexed = valid_smt_indexed_bit_vector (parse_tree))
263+ return *indexed;
243264 if (!parse_tree.get_sub ().empty () || parse_tree.id ().empty ())
244265 return {};
245266 const auto value_string = id2string (parse_tree.id ());
@@ -250,24 +271,52 @@ valid_smt_bit_vector_constant(const irept &parse_tree)
250271 return {};
251272}
252273
253- static response_or_errort <smt_termt> validate_term (const irept &parse_tree)
274+ static optionalt <smt_termt> valid_term (const irept &parse_tree)
254275{
255276 if (const auto smt_bool = valid_smt_bool (parse_tree))
256- return response_or_errort<smt_termt> {*smt_bool};
277+ return {*smt_bool};
257278 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};
259287 return response_or_errort<smt_termt>{" Unrecognised SMT term - \" " +
260288 print_parse_tree (parse_tree) + " \" ." };
261289}
262290
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+
263304static response_or_errort<smt_get_value_responset::valuation_pairt>
264305validate_valuation_pair (const irept &pair_parse_tree)
265306{
266307 PRECONDITION (pair_parse_tree.get_sub ().size () == 2 );
267308 const auto &descriptor = pair_parse_tree.get_sub ()[0 ];
268309 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 ();
269317 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));
271320}
272321
273322// / \returns: A response or error in the case where the parse tree appears to be
0 commit comments