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:
parent
a095b26d17
commit
a6969c4359
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue