wgsl-reader: Hex float exponents are optional

Fixed: tint:1210
Change-Id: I4256494e3ca3f98082f360e0447d0392964073bd
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/66040
Auto-Submit: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
David Neto 2021-10-14 21:38:01 +00:00 committed by Tint LUCI CQ
parent a095b26d17
commit a6969c4359
2 changed files with 63 additions and 34 deletions

View File

@ -343,7 +343,9 @@ Token Lexer::try_hex_float() {
} }
// .? // .?
bool hex_point = false;
if (matches(end, ".")) { if (matches(end, ".")) {
hex_point = true;
end++; end++;
} }
@ -359,14 +361,18 @@ Token Lexer::try_hex_float() {
return {}; return {};
} }
// (p|P) // Is the binary exponent present? It's optional.
if (matches(end, "p") || matches(end, "P")) { const bool has_exponent = (matches(end, "p") || matches(end, "P"));
if (has_exponent) {
end++; end++;
} else { }
if (!has_exponent && !hex_point) {
// It's not a hex float. At best it's a hex integer.
return {}; return {};
} }
// At this point, we know for sure our token is a hex float value. // At this point, we know for sure our token is a hex float value,
// or an invalid token.
// Parse integer part // Parse integer part
// [0-9a-fA-F]* // [0-9a-fA-F]*
@ -423,42 +429,48 @@ Token Lexer::try_hex_float() {
} }
} }
// (+|-)? // Determine if the value of the mantissa is zero.
int32_t exponent_sign = 1;
if (matches(end, "+")) {
end++;
} else if (matches(end, "-")) {
exponent_sign = -1;
end++;
}
// Determine if the value is zero.
// Note: it's not enough to check mantissa == 0 as we drop the initial bit, // Note: it's not enough to check mantissa == 0 as we drop the initial bit,
// whether it's in the integer part or the fractional part. // whether it's in the integer part or the fractional part.
const bool is_zero = !seen_prior_one_bits; const bool is_zero = !seen_prior_one_bits;
TINT_ASSERT(Reader, !is_zero || mantissa == 0); TINT_ASSERT(Reader, !is_zero || mantissa == 0);
// Parse exponent from input // Parse the optional exponent.
// [0-9]+ // ((p|P)(\+|-)?[0-9]+)?
// Allow overflow (in uint32_t) when the floating point value magnitude is uint32_t input_exponent = 0; // Defaults to 0 if not present
// zero. int32_t exponent_sign = 1;
bool has_exponent = false; // If the 'p' part is present, the rest of the exponent must exist.
uint32_t input_exponent = 0; if (has_exponent) {
while (end < len_ && isdigit(content_->data[end])) { // Parse the rest of the exponent.
has_exponent = true; // (+|-)?
auto prev_exponent = input_exponent; if (matches(end, "+")) {
input_exponent = (input_exponent * 10) + dec_value(content_->data[end]); end++;
// Check if we've overflowed input_exponent. This only matters when } else if (matches(end, "-")) {
// the mantissa is non-zero. exponent_sign = -1;
if (!is_zero && (prev_exponent > input_exponent)) { end++;
return {Token::Type::kError, source, }
"exponent is too large for hex float"};
// Parse exponent from input
// [0-9]+
// Allow overflow (in uint32_t) when the floating point value magnitude is
// zero.
bool has_exponent_digits = false;
while (end < len_ && isdigit(content_->data[end])) {
has_exponent_digits = true;
auto prev_exponent = input_exponent;
input_exponent = (input_exponent * 10) + dec_value(content_->data[end]);
// Check if we've overflowed input_exponent. This only matters when
// the mantissa is non-zero.
if (!is_zero && (prev_exponent > input_exponent)) {
return {Token::Type::kError, source,
"exponent is too large for hex float"};
}
end++;
}
if (!has_exponent_digits) {
return {Token::Type::kError, source,
"expected an exponent value for hex float"};
} }
end++;
}
if (!has_exponent) {
return {Token::Type::kError, source,
"expected an exponent value for hex float"};
} }
pos_ = end; pos_ = end;

View File

@ -275,6 +275,14 @@ FloatLiteralTestCase hexfloat_literal_test_cases[] = {
{"-0x123Ep+1", -9340.f}, {"-0x123Ep+1", -9340.f},
{"0x1a2b3cP12", 7.024656e+09f}, {"0x1a2b3cP12", 7.024656e+09f},
{"-0x1a2b3cP12", -7.024656e+09f}, {"-0x1a2b3cP12", -7.024656e+09f},
// Examples without a binary exponent part.
{"0x1.", 1.0f},
{"0x.8", 0.5f},
{"0x1.8", 1.5f},
{"-0x1.", -1.0f},
{"-0x.8", -0.5f},
{"-0x1.8", -1.5f},
}; };
INSTANTIATE_TEST_SUITE_P(ParserImplFloatLiteralTest_HexFloat, INSTANTIATE_TEST_SUITE_P(ParserImplFloatLiteralTest_HexFloat,
ParserImplFloatLiteralTest, ParserImplFloatLiteralTest,
@ -326,9 +334,18 @@ INSTANTIATE_TEST_SUITE_P(
testing::ValuesIn(invalid_hexfloat_exponent_too_large_cases)); testing::ValuesIn(invalid_hexfloat_exponent_too_large_cases));
InvalidLiteralTestCase invalid_hexfloat_exponent_missing_cases[] = { InvalidLiteralTestCase invalid_hexfloat_exponent_missing_cases[] = {
// Lower case p
{"0x0p", "1:1: expected an exponent value for hex float"}, {"0x0p", "1:1: expected an exponent value for hex float"},
{"0x0p+", "1:1: expected an exponent value for hex float"},
{"0x0p-", "1:1: expected an exponent value for hex float"},
{"0x1.0p", "1:1: expected an exponent value for hex float"}, {"0x1.0p", "1:1: expected an exponent value for hex float"},
{"0x0.1p", "1:1: expected an exponent value for hex float"}, {"0x0.1p", "1:1: expected an exponent value for hex float"},
// Upper case p
{"0x0P", "1:1: expected an exponent value for hex float"},
{"0x0P+", "1:1: expected an exponent value for hex float"},
{"0x0P-", "1:1: expected an exponent value for hex float"},
{"0x1.0P", "1:1: expected an exponent value for hex float"},
{"0x0.1P", "1:1: expected an exponent value for hex float"},
}; };
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
ParserImplInvalidLiteralTest_HexFloatExponentMissing, ParserImplInvalidLiteralTest_HexFloatExponentMissing,