Implement MathLib::isFloatHex to detect C99 hexadecimal floating pointer literals. Rename MathLib::isHex to MathLib::isIntHex

This commit is contained in:
Alexander Mai 2015-07-26 08:06:56 +02:00
parent 12eb3ae716
commit bbec54db8e
4 changed files with 183 additions and 92 deletions

View File

@ -262,7 +262,7 @@ MathLib::value MathLib::value::add(int v) const
MathLib::biguint MathLib::toULongNumber(const std::string & str)
{
// hexadecimal numbers:
if (isHex(str)) {
if (isIntHex(str)) {
if (str[0] == '-') {
biguint ret = 0;
std::istringstream istr(str);
@ -316,7 +316,7 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str)
MathLib::bigint MathLib::toLongNumber(const std::string & str)
{
// hexadecimal numbers:
if (isHex(str)) {
if (isIntHex(str)) {
if (str[0] == '-') {
bigint ret = 0;
std::istringstream istr(str);
@ -372,7 +372,7 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str)
double MathLib::toDoubleNumber(const std::string &str)
{
if (isHex(str))
if (isIntHex(str))
return static_cast<double>(toLongNumber(str));
// nullcheck
else if (isNullValue(str))
@ -555,14 +555,14 @@ bool MathLib::isOct(const std::string& s)
if (isOctalDigit(*it))
state = DIGITS;
else
return isValidSuffix(it,s.end());
return isValidIntegerSuffix(it,s.end());
break;
}
}
return state == DIGITS;
}
bool MathLib::isHex(const std::string& s)
bool MathLib::isIntHex(const std::string& s)
{
enum Status {
START, PLUSMINUS, HEX_PREFIX, DIGIT, DIGITS
@ -599,14 +599,82 @@ bool MathLib::isHex(const std::string& s)
if (isxdigit(*it))
state = DIGITS;
else
return isValidSuffix(it,s.end());
return isValidIntegerSuffix(it,s.end());
break;
}
}
return state == DIGITS;
}
bool MathLib::isValidSuffix(std::string::const_iterator it, std::string::const_iterator end)
bool MathLib::isFloatHex(const std::string& s)
{
enum Status {
START, PLUSMINUS, HEX_PREFIX, WHOLE_NUMBER_DIGIT, WHOLE_NUMBER_DIGITS, FRACTION, EXPONENT_DIGIT, EXPONENT_DIGITS
} state = START;
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
switch (state) {
case START:
if (*it == '+' || *it == '-')
state = PLUSMINUS;
else if (*it == '0')
state = HEX_PREFIX;
else
return false;
break;
case PLUSMINUS:
if (*it == '0')
state = HEX_PREFIX;
else
return false;
break;
case HEX_PREFIX:
if (*it == 'x' || *it == 'X')
state = WHOLE_NUMBER_DIGIT;
else
return false;
break;
case WHOLE_NUMBER_DIGIT:
if (isxdigit(*it))
state = WHOLE_NUMBER_DIGITS;
else
return false;
break;
case WHOLE_NUMBER_DIGITS:
if (isxdigit(*it))
state = WHOLE_NUMBER_DIGITS;
else if (*it=='.')
state = FRACTION;
else if (*it=='p' || *it=='P')
state = EXPONENT_DIGIT;
else
return false;
break;
case FRACTION:
if (isxdigit(*it))
state = FRACTION;
else if (*it=='p' || *it=='P')
state = EXPONENT_DIGIT;
break;
case EXPONENT_DIGIT:
if (isxdigit(*it))
state = EXPONENT_DIGITS;
else if (*it=='+' || *it=='-')
state = EXPONENT_DIGITS;
else
return false;
break;
case EXPONENT_DIGITS:
if (isxdigit(*it))
state = EXPONENT_DIGITS;
else
return *it=='f'||*it=='F'||*it=='l'||*it=='L';
break;
}
}
return state==EXPONENT_DIGITS;
}
bool MathLib::isValidIntegerSuffix(std::string::const_iterator it, std::string::const_iterator end)
{
enum {START, SUFFIX_U, SUFFIX_UL, SUFFIX_ULL, SUFFIX_L, SUFFIX_LU, SUFFIX_LL, SUFFIX_LLU, SUFFIX_I, SUFFIX_I6, SUFFIX_I64} state = START;
for (; it != end; ++it) {
@ -721,7 +789,7 @@ bool MathLib::isBin(const std::string& s)
if (*it == '0' || *it == '1')
state = DIGITS;
else
return isValidSuffix(it,s.end());
return isValidIntegerSuffix(it,s.end());
break;
}
}
@ -753,7 +821,7 @@ bool MathLib::isDec(const std::string & s)
if (isdigit(*it))
state = DIGIT;
else
return isValidSuffix(it,s.end());
return isValidIntegerSuffix(it,s.end());
break;
}
}
@ -762,7 +830,7 @@ bool MathLib::isDec(const std::string & s)
bool MathLib::isInt(const std::string & s)
{
return isDec(s) || isHex(s) || isOct(s) || isBin(s);
return isDec(s) || isIntHex(s) || isOct(s) || isBin(s);
}
static std::string intsuffix(const std::string & first, const std::string & second)

View File

@ -80,11 +80,12 @@ public:
static bool isNegative(const std::string &str);
static bool isPositive(const std::string &str);
static bool isDec(const std::string & str);
static bool isHex(const std::string& str);
static bool isFloatHex(const std::string& str);
static bool isIntHex(const std::string& str);
static bool isOct(const std::string& str);
static bool isBin(const std::string& str);
static bool isValidSuffix(std::string::const_iterator it, std::string::const_iterator end);
static bool isValidIntegerSuffix(std::string::const_iterator it, std::string::const_iterator end);
static std::string add(const std::string & first, const std::string & second);
static std::string subtract(const std::string & first, const std::string & second);

View File

@ -130,7 +130,7 @@ void TokenList::addtoken(const std::string & str, const unsigned int lineno, con
// Replace hexadecimal value with decimal
std::string str2;
if (MathLib::isHex(str) || MathLib::isOct(str) || MathLib::isBin(str)) {
if (MathLib::isIntHex(str) || MathLib::isOct(str) || MathLib::isBin(str)) {
std::ostringstream str2stream;
str2stream << MathLib::toULongNumber(str);
str2 = str2stream.str();
@ -305,7 +305,7 @@ bool TokenList::createTokens(std::istream &code, const std::string& file0)
std::isdigit((unsigned char)CurrentToken[0]) &&
(CurrentToken.back() == 'e' ||
CurrentToken.back() == 'E') &&
!MathLib::isHex(CurrentToken)) {
!MathLib::isIntHex(CurrentToken)) {
// Don't separate doubles "4.2e+10"
} else if (CurrentToken.empty() && ch == '.' && std::isdigit((unsigned char)code.peek())) {
// tokenize .125 into 0.125

View File

@ -32,8 +32,9 @@ private:
TEST_CASE(isbin);
TEST_CASE(isdec);
TEST_CASE(isoct);
TEST_CASE(ishex);
TEST_CASE(isValidSuffix);
TEST_CASE(isfloathex);
TEST_CASE(isinthex);
TEST_CASE(isValidIntegerSuffix);
TEST_CASE(isnegative);
TEST_CASE(ispositive);
TEST_CASE(isfloat);
@ -552,136 +553,157 @@ private:
ASSERT_EQUALS(false, MathLib::isOct("+042LUL+0"));
}
void ishex() const {
void isfloathex() const {
// hex number syntax: [sign]0x[hexnumbers][suffix]
ASSERT_EQUALS(false, MathLib::isFloatHex(""));
ASSERT_EQUALS(true, MathLib::isFloatHex("0x1.999999999999ap-4"));
ASSERT_EQUALS(true, MathLib::isFloatHex("0x0.3p10"));
ASSERT_EQUALS(true, MathLib::isFloatHex("0x1.fp3"));
ASSERT_EQUALS(true, MathLib::isFloatHex("0x1P-1"));
ASSERT_EQUALS(true, MathLib::isFloatHex("0xcc.ccccccccccdp-11"));
ASSERT_EQUALS(true, MathLib::isFloatHex("0x3.243F6A88p+03"));
ASSERT_EQUALS(false, MathLib::isFloatHex("0"));
ASSERT_EQUALS(false, MathLib::isFloatHex("0x"));
ASSERT_EQUALS(false, MathLib::isFloatHex("0xa"));
ASSERT_EQUALS(false, MathLib::isFloatHex("+0x"));
ASSERT_EQUALS(false, MathLib::isFloatHex("-0x"));
ASSERT_EQUALS(false, MathLib::isFloatHex("0x"));
ASSERT_EQUALS(false, MathLib::isFloatHex("0x."));
ASSERT_EQUALS(false, MathLib::isFloatHex("0XP"));
ASSERT_EQUALS(false, MathLib::isFloatHex("0xx"));
}
void isinthex() const {
// hex number syntax: [sign]0x[hexnumbers][suffix]
// positive testing
ASSERT_EQUALS(true, MathLib::isHex("0xa"));
ASSERT_EQUALS(true, MathLib::isHex("0x2AF3"));
ASSERT_EQUALS(true, MathLib::isHex("-0xa"));
ASSERT_EQUALS(true, MathLib::isHex("-0x2AF3"));
ASSERT_EQUALS(true, MathLib::isHex("+0xa"));
ASSERT_EQUALS(true, MathLib::isHex("+0x2AF3"));
ASSERT_EQUALS(true, MathLib::isHex("0x0"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0U"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0U"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0L"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0L"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0LU"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0LU"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0UL"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0UL"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0LL"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0LL"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0ULL"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0ULL"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0LLU"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0LLU"));
ASSERT_EQUALS(true, MathLib::isIntHex("0xa"));
ASSERT_EQUALS(true, MathLib::isIntHex("0x2AF3"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0xa"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x2AF3"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0xa"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x2AF3"));
ASSERT_EQUALS(true, MathLib::isIntHex("0x0"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0U"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0U"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0L"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0L"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0LU"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0LU"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0UL"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0UL"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0LL"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0LL"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0ULL"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0ULL"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0LLU"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0LLU"));
// negative testing
ASSERT_EQUALS(false, MathLib::isHex("+0x"));
ASSERT_EQUALS(false, MathLib::isHex("-0x"));
ASSERT_EQUALS(false, MathLib::isHex("0x"));
ASSERT_EQUALS(false, MathLib::isHex("0xx"));
ASSERT_EQUALS(false, MathLib::isHex("-0175"));
ASSERT_EQUALS(false, MathLib::isHex("-0_garbage_"));
ASSERT_EQUALS(false, MathLib::isHex(" "));
ASSERT_EQUALS(false, MathLib::isHex(" "));
ASSERT_EQUALS(false, MathLib::isHex("0"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0Z"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0Z"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0Uz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0Uz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0Lz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0Lz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0LUz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0LUz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0ULz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0ULz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0LLz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0LLz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0ULLz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0ULLz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0LLUz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0LLUz"));
ASSERT_EQUALS(false, MathLib::isHex("0x0+0"));
ASSERT_EQUALS(false, MathLib::isHex("e2"));
ASSERT_EQUALS(false, MathLib::isHex("+E2"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x"));
ASSERT_EQUALS(false, MathLib::isIntHex("0x"));
ASSERT_EQUALS(false, MathLib::isIntHex("0xx"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0175"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0_garbage_"));
ASSERT_EQUALS(false, MathLib::isIntHex(" "));
ASSERT_EQUALS(false, MathLib::isIntHex(" "));
ASSERT_EQUALS(false, MathLib::isIntHex("0"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0Z"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x0Z"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0Uz"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x0Uz"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0Lz"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x0Lz"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0LUz"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x0LUz"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0ULz"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x0ULz"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0LLz"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x0LLz"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0ULLz"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x0ULLz"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0LLUz"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x0LLUz"));
ASSERT_EQUALS(false, MathLib::isIntHex("0x0+0"));
ASSERT_EQUALS(false, MathLib::isIntHex("e2"));
ASSERT_EQUALS(false, MathLib::isIntHex("+E2"));
// test empty string
ASSERT_EQUALS(false, MathLib::isHex(""));
ASSERT_EQUALS(false, MathLib::isIntHex(""));
}
void isValidSuffix(void) const {
void isValidIntegerSuffix(void) const {
// negative testing
std::string value = "ux";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "ulx";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "lx";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "lux";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "lll";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "garbage";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "llu ";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "i";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "iX";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "i6X";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "i64X";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "i64 ";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "i66";
ASSERT_EQUALS(false, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
// positive testing
value = "u";
ASSERT_EQUALS(true, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "ul";
ASSERT_EQUALS(true, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "ull";
ASSERT_EQUALS(true, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "l";
ASSERT_EQUALS(true, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "lu";
ASSERT_EQUALS(true, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "ll";
ASSERT_EQUALS(true, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "llu";
ASSERT_EQUALS(true, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
value = "i64";
ASSERT_EQUALS(true, MathLib::isValidSuffix(value.begin(), value.end()));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix(value.begin(), value.end()));
}
void ispositive() const {