From 2f4bae4b4ffe6e913925f3d8f2c857a01aeea3bd Mon Sep 17 00:00:00 2001 From: mudathirmahgoub Date: Thu, 28 Jan 2021 14:51:28 -0600 Subject: [PATCH] Remove regex header from cvc4cpp.cpp (#5826) This PR replaces the heavy hammer std::regex_match for checking numbers with string operations --- src/api/cvc4cpp.cpp | 42 ++++++++++++++++++++++++++++++--- src/api/cvc4cpp.h | 3 +++ test/unit/api/term_black.cpp | 11 +++++++++ test/unit/parser/parser_black.h | 2 +- 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/api/cvc4cpp.cpp b/src/api/cvc4cpp.cpp index abec4d8dd..541c5f5a5 100644 --- a/src/api/cvc4cpp.cpp +++ b/src/api/cvc4cpp.cpp @@ -34,7 +34,6 @@ #include "api/cvc4cpp.h" #include -#include #include #include "base/check.h" @@ -3924,11 +3923,48 @@ Term Solver::mkPi() const CVC4_API_SOLVER_TRY_CATCH_END; } +bool Solver::isValidInteger(const std::string& s) const +{ + if (s.length() == 0) + { + // string should not be empty + return false; + } + + size_t index = 0; + if (s[index] == '-') + { + if (s.length() == 1) + { + // negative integers should contain at least one digit + return false; + } + index = 1; + } + + if (s[index] == '0' && s.length() > (index + 1)) + { + // From SMT-Lib 2.6: A〈numeral〉is the digit 0 or a non-empty sequence of + // digits not starting with 0. So integers like 001, 000 are not allowed + return false; + } + + // all remaining characters should be decimal digits + for (; index < s.length(); ++index) + { + if (!std::isdigit(s[index])) + { + return false; + } + } + + return true; +} + Term Solver::mkInteger(const std::string& s) const { CVC4_API_SOLVER_TRY_CATCH_BEGIN; - CVC4_API_ARG_CHECK_EXPECTED(std::regex_match(s, std::regex("-?\\d+")), s) - << " an integer "; + CVC4_API_ARG_CHECK_EXPECTED(isValidInteger(s), s) << " an integer "; Term integer = mkRealFromStrHelper(s); CVC4_API_ARG_CHECK_EXPECTED(integer.getSort() == getIntegerSort(), s) << " an integer"; diff --git a/src/api/cvc4cpp.h b/src/api/cvc4cpp.h index 66ba4f23b..60127d18b 100644 --- a/src/api/cvc4cpp.h +++ b/src/api/cvc4cpp.h @@ -3595,6 +3595,9 @@ class CVC4_PUBLIC Solver bool isInv = false, Grammar* g = nullptr) const; + /** check whether string s is a valid decimal integer */ + bool isValidInteger(const std::string& s) const; + /* The expression manager of this solver. */ std::unique_ptr d_exprMgr; /* The SMT engine of this solver. */ diff --git a/test/unit/api/term_black.cpp b/test/unit/api/term_black.cpp index 50d67688d..b6f8fc4ed 100644 --- a/test/unit/api/term_black.cpp +++ b/test/unit/api/term_black.cpp @@ -684,6 +684,17 @@ TEST_F(TestApiTermBlack, getInteger) Term int9 = d_solver.mkInteger("4294967296"); Term int10 = d_solver.mkInteger("18446744073709551615"); Term int11 = d_solver.mkInteger("18446744073709551616"); + Term int12 = d_solver.mkInteger("-0"); + + ASSERT_THROW(d_solver.mkInteger(""), CVC4ApiException); + ASSERT_THROW(d_solver.mkInteger("-"), CVC4ApiException); + ASSERT_THROW(d_solver.mkInteger("-1-"), CVC4ApiException); + ASSERT_THROW(d_solver.mkInteger("0.0"), CVC4ApiException); + ASSERT_THROW(d_solver.mkInteger("-0.1"), CVC4ApiException); + ASSERT_THROW(d_solver.mkInteger("012"), CVC4ApiException); + ASSERT_THROW(d_solver.mkInteger("0000"), CVC4ApiException); + ASSERT_THROW(d_solver.mkInteger("-01"), CVC4ApiException); + ASSERT_THROW(d_solver.mkInteger("-00"), CVC4ApiException); ASSERT_TRUE(!int1.isInt32() && !int1.isUInt32() && !int1.isInt64() && !int1.isUInt64() && int1.isInteger()); diff --git a/test/unit/parser/parser_black.h b/test/unit/parser/parser_black.h index d63f6b029..507ccb791 100644 --- a/test/unit/parser/parser_black.h +++ b/test/unit/parser/parser_black.h @@ -379,7 +379,7 @@ public: tryGoodExpr("1.5"); tryGoodExpr("#xfab09c7"); tryGoodExpr("#b0001011"); - tryGoodExpr("(* 5 01)"); // '01' is OK in non-strict mode + tryGoodExpr("(* 5 1)"); } void testBadSmt2Exprs() { -- 2.30.2