Factor out common error-handling functions for lexing numbers of different bases (#1888)

This commit is contained in:
Rangi
2026-03-19 15:32:25 -04:00
committed by GitHub
parent b8e425b41d
commit 66e521e9e5

View File

@@ -935,6 +935,21 @@ static std::string readAnonLabelRef(char c) {
return sym_MakeAnonLabelName(n, c == '-'); return sym_MakeAnonLabelName(n, c == '-');
} }
static void checkDigitSeparator(bool nonDigit) {
if (nonDigit) {
error("Invalid integer constant, '_' after another '_'");
}
}
static void checkIntegerConstantSuffix(bool empty, bool nonDigit, char const *prefix) {
if (empty) {
error("Invalid integer constant, no digits after %s", prefix);
}
if (nonDigit) {
error("Invalid integer constant, trailing '_'");
}
}
static uint32_t readFractionalPart(uint32_t integer) { static uint32_t readFractionalPart(uint32_t integer) {
uint32_t value = 0, divisor = 1; uint32_t value = 0, divisor = 1;
uint8_t precision = 0; uint8_t precision = 0;
@@ -948,9 +963,7 @@ static uint32_t readFractionalPart(uint32_t integer) {
for (int c = peek();; c = nextChar()) { for (int c = peek();; c = nextChar()) {
if (state == READFRACTIONALPART_DIGITS) { if (state == READFRACTIONALPART_DIGITS) {
if (c == '_') { if (c == '_') {
if (nonDigit) { checkDigitSeparator(nonDigit);
error("Invalid integer constant, '_' after another '_'");
}
nonDigit = true; nonDigit = true;
continue; continue;
} }
@@ -962,15 +975,16 @@ static uint32_t readFractionalPart(uint32_t integer) {
} else if (!isDigit(c)) { } else if (!isDigit(c)) {
break; break;
} }
c -= '0';
nonDigit = false; nonDigit = false;
if (divisor > (UINT32_MAX - (c - '0')) / 10) { if (divisor > (UINT32_MAX - c) / 10) {
warning(WARNING_LARGE_CONSTANT, "Precision of fixed-point constant is too large"); warning(WARNING_LARGE_CONSTANT, "Precision of fixed-point constant is too large");
// Discard any additional digits // Discard any additional digits
skipChars([](int d) { return isDigit(d) || d == '_'; }); skipChars([](int d) { return isDigit(d) || d == '_'; });
break; break;
} }
value = value * 10 + (c - '0'); value = value * 10 + c;
divisor *= 10; divisor *= 10;
} else { } else {
if (c == '.' && state == READFRACTIONALPART_PRECISION) { if (c == '.' && state == READFRACTIONALPART_PRECISION) {
@@ -1061,9 +1075,7 @@ static uint32_t readBinaryNumber(char const *prefix) {
for (int c = peek();; c = nextChar()) { for (int c = peek();; c = nextChar()) {
if (c == '_') { if (c == '_') {
if (nonDigit) { checkDigitSeparator(nonDigit);
error("Invalid integer constant, '_' after another '_'");
}
nonDigit = true; nonDigit = true;
continue; continue;
} }
@@ -1088,13 +1100,7 @@ static uint32_t readBinaryNumber(char const *prefix) {
value = value * 2 + bit; value = value * 2 + bit;
} }
if (empty) { checkIntegerConstantSuffix(empty, nonDigit, prefix);
error("Invalid integer constant, no digits after %s", prefix);
}
if (nonDigit) {
error("Invalid integer constant, trailing '_'");
}
return value; return value;
} }
@@ -1105,9 +1111,7 @@ static uint32_t readOctalNumber(char const *prefix) {
for (int c = peek();; c = nextChar()) { for (int c = peek();; c = nextChar()) {
if (c == '_') { if (c == '_') {
if (nonDigit) { checkDigitSeparator(nonDigit);
error("Invalid integer constant, '_' after another '_'");
}
nonDigit = true; nonDigit = true;
continue; continue;
} }
@@ -1115,7 +1119,7 @@ static uint32_t readOctalNumber(char const *prefix) {
if (!isOctDigit(c)) { if (!isOctDigit(c)) {
break; break;
} }
c = c - '0'; c -= '0';
empty = false; empty = false;
nonDigit = false; nonDigit = false;
@@ -1128,13 +1132,7 @@ static uint32_t readOctalNumber(char const *prefix) {
value = value * 8 + c; value = value * 8 + c;
} }
if (empty) { checkIntegerConstantSuffix(empty, nonDigit, prefix);
error("Invalid integer constant, no digits after %s", prefix);
}
if (nonDigit) {
error("Invalid integer constant, trailing '_'");
}
return value; return value;
} }
@@ -1145,9 +1143,7 @@ static uint32_t readDecimalNumber(int initial) {
for (int c = peek();; c = nextChar()) { for (int c = peek();; c = nextChar()) {
if (c == '_') { if (c == '_') {
if (nonDigit) { checkDigitSeparator(nonDigit);
error("Invalid integer constant, '_' after another '_'");
}
nonDigit = true; nonDigit = true;
continue; continue;
} }
@@ -1155,7 +1151,7 @@ static uint32_t readDecimalNumber(int initial) {
if (!isDigit(c)) { if (!isDigit(c)) {
break; break;
} }
c = c - '0'; c -= '0';
nonDigit = false; nonDigit = false;
if (value > (UINT32_MAX - c) / 10) { if (value > (UINT32_MAX - c) / 10) {
@@ -1167,10 +1163,7 @@ static uint32_t readDecimalNumber(int initial) {
value = value * 10 + c; value = value * 10 + c;
} }
if (nonDigit) { checkIntegerConstantSuffix(false, nonDigit, nullptr);
error("Invalid integer constant, trailing '_'");
}
return value; return value;
} }
@@ -1181,9 +1174,7 @@ static uint32_t readHexNumber(char const *prefix) {
for (int c = peek();; c = nextChar()) { for (int c = peek();; c = nextChar()) {
if (c == '_') { if (c == '_') {
if (nonDigit) { checkDigitSeparator(nonDigit);
error("Invalid integer constant, '_' after another '_'");
}
nonDigit = true; nonDigit = true;
continue; continue;
} }
@@ -1204,13 +1195,7 @@ static uint32_t readHexNumber(char const *prefix) {
value = value * 16 + c; value = value * 16 + c;
} }
if (empty) { checkIntegerConstantSuffix(empty, nonDigit, prefix);
error("Invalid integer constant, no digits after %s", prefix);
}
if (nonDigit) {
error("Invalid integer constant, trailing '_'");
}
return value; return value;
} }
@@ -1221,9 +1206,7 @@ static uint32_t readGfxConstant() {
for (int c = peek();; c = nextChar()) { for (int c = peek();; c = nextChar()) {
if (c == '_') { if (c == '_') {
if (nonDigit) { checkDigitSeparator(nonDigit);
error("Invalid integer constant, '_' after another '_'");
}
nonDigit = true; nonDigit = true;
continue; continue;
} }