wgsl: float literals can have 'f' suffix
Fixes: tint:1307
Change-Id: Ie21a2c24e5aedf0353f95e7a66c41e6177e8a168
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/69760
Auto-Submit: David Neto <dneto@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/reader/wgsl/lexer.cc b/src/reader/wgsl/lexer.cc
index 5c57c9c..f55e5b6 100644
--- a/src/reader/wgsl/lexer.cc
+++ b/src/reader/wgsl/lexer.cc
@@ -256,11 +256,18 @@
}
}
- if (!has_point && !has_exponent) {
+ bool has_f_suffix = false;
+ if (end < len_ && matches(end, "f")) {
+ end++;
+ has_f_suffix = true;
+ }
+
+ if (!has_point && !has_exponent && !has_f_suffix) {
// If it only has digits then it's an integer.
return {};
}
+ // Save the error string, for use by diagnostics.
const auto str = content_->data.substr(start, end - start);
pos_ = end;
@@ -488,6 +495,14 @@
}
end++;
}
+
+ // Parse optional 'f' suffix. For a hex float, it can only exist
+ // when the exponent is present. Otherwise it will look like
+ // one of the mantissa digits.
+ if (end < len_ && matches(end, "f")) {
+ end++;
+ }
+
if (!has_exponent_digits) {
return {Token::Type::kError, source,
"expected an exponent value for hex float"};
diff --git a/src/reader/wgsl/lexer_test.cc b/src/reader/wgsl/lexer_test.cc
index d5fad28..d476b53 100644
--- a/src/reader/wgsl/lexer_test.cc
+++ b/src/reader/wgsl/lexer_test.cc
@@ -137,29 +137,65 @@
}
INSTANTIATE_TEST_SUITE_P(LexerTest,
FloatTest,
- testing::Values(FloatData{"0.0", 0.0f},
- FloatData{"0.", 0.0f},
- FloatData{".0", 0.0f},
- FloatData{"5.7", 5.7f},
- FloatData{"5.", 5.f},
- FloatData{".7", .7f},
- FloatData{"-0.0", 0.0f},
- FloatData{"-.0", 0.0f},
- FloatData{"-0.", 0.0f},
- FloatData{"-5.7", -5.7f},
- FloatData{"-5.", -5.f},
- FloatData{"-.7", -.7f},
- // No decimal, with exponent
- FloatData{"1e5", 1e5f},
- FloatData{"1E5", 1e5f},
- FloatData{"1e-5", 1e-5f},
- FloatData{"1E-5", 1e-5f},
- // With decimal and exponents
- FloatData{"0.2e+12", 0.2e12f},
- FloatData{"1.2e-5", 1.2e-5f},
- FloatData{"2.57e23", 2.57e23f},
- FloatData{"2.5e+0", 2.5f},
- FloatData{"2.5e-0", 2.5f}));
+ testing::Values(
+ // No decimal, with 'f' suffix
+ FloatData{"0f", 0.0f},
+ FloatData{"1f", 1.0f},
+ FloatData{"-0f", 0.0f},
+ FloatData{"-1f", -1.0f},
+
+ // Zero, with decimal.
+ FloatData{"0.0", 0.0f},
+ FloatData{"0.", 0.0f},
+ FloatData{".0", 0.0f},
+ FloatData{"-0.0", 0.0f},
+ FloatData{"-0.", 0.0f},
+ FloatData{"-.0", 0.0f},
+ // Zero, with decimal and 'f' suffix
+ FloatData{"0.0f", 0.0f},
+ FloatData{"0.f", 0.0f},
+ FloatData{".0f", 0.0f},
+ FloatData{"-0.0f", 0.0f},
+ FloatData{"-0.f", 0.0f},
+ FloatData{"-.0", 0.0f},
+
+ // Non-zero with decimal
+ FloatData{"5.7", 5.7f},
+ FloatData{"5.", 5.f},
+ FloatData{".7", .7f},
+ FloatData{"-5.7", -5.7f},
+ FloatData{"-5.", -5.f},
+ FloatData{"-.7", -.7f},
+ // Non-zero with decimal and 'f' suffix
+ FloatData{"5.7f", 5.7f},
+ FloatData{"5.f", 5.f},
+ FloatData{".7f", .7f},
+ FloatData{"-5.7f", -5.7f},
+ FloatData{"-5.f", -5.f},
+ FloatData{"-.7f", -.7f},
+
+ // No decimal, with exponent
+ FloatData{"1e5", 1e5f},
+ FloatData{"1E5", 1e5f},
+ FloatData{"1e-5", 1e-5f},
+ FloatData{"1E-5", 1e-5f},
+ // No decimal, with exponent and 'f' suffix
+ FloatData{"1e5f", 1e5f},
+ FloatData{"1E5f", 1e5f},
+ FloatData{"1e-5f", 1e-5f},
+ FloatData{"1E-5f", 1e-5f},
+ // With decimal and exponents
+ FloatData{"0.2e+12", 0.2e12f},
+ FloatData{"1.2e-5", 1.2e-5f},
+ FloatData{"2.57e23", 2.57e23f},
+ FloatData{"2.5e+0", 2.5f},
+ FloatData{"2.5e-0", 2.5f},
+ // With decimal and exponents and 'f' suffix
+ FloatData{"0.2e+12f", 0.2e12f},
+ FloatData{"1.2e-5f", 1.2e-5f},
+ FloatData{"2.57e23f", 2.57e23f},
+ FloatData{"2.5e+0f", 2.5f},
+ FloatData{"2.5e-0f", 2.5f}));
using FloatTest_Invalid = testing::TestWithParam<const char*>;
TEST_P(FloatTest_Invalid, Handles) {
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index cac4b4e..f1fca91 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -2844,12 +2844,6 @@
return create<ast::UintLiteralExpression>(t.source(), t.to_u32());
}
if (match(Token::Type::kFloatLiteral)) {
- auto p = peek();
- if (p.IsIdentifier() && p.to_str() == "f") {
- next(); // Consume 'f'
- return add_error(p.source(),
- "float literals must not be suffixed with 'f'");
- }
return create<ast::FloatLiteralExpression>(t.source(), t.to_f32());
}
return Failure::kNoMatch;
diff --git a/src/reader/wgsl/parser_impl_const_literal_test.cc b/src/reader/wgsl/parser_impl_const_literal_test.cc
index 37350b9..9e6a88a 100644
--- a/src/reader/wgsl/parser_impl_const_literal_test.cc
+++ b/src/reader/wgsl/parser_impl_const_literal_test.cc
@@ -312,6 +312,16 @@
{"-0x1.", -1.0f},
{"-0x.8", -0.5f},
{"-0x1.8", -1.5f},
+
+ // Examples with a binary exponent and a 'f' suffix.
+ {"0x1.p0f", 1.0f},
+ {"0x.8p2f", 2.0f},
+ {"0x1.8p-1f", 0.75f},
+ {"0x2p-2f", 0.5f}, // No binary point
+ {"-0x1.p0f", -1.0f},
+ {"-0x.8p2f", -2.0f},
+ {"-0x1.8p-1f", -0.75f},
+ {"-0x2p-2f", -0.5f}, // No binary point
};
INSTANTIATE_TEST_SUITE_P(ParserImplFloatLiteralTest_HexFloat,
ParserImplFloatLiteralTest,
diff --git a/src/reader/wgsl/parser_impl_error_msg_test.cc b/src/reader/wgsl/parser_impl_error_msg_test.cc
index a224585..e30177b 100644
--- a/src/reader/wgsl/parser_impl_error_msg_test.cc
+++ b/src/reader/wgsl/parser_impl_error_msg_test.cc
@@ -226,13 +226,6 @@
" ^\n");
}
-TEST_F(ParserImplErrorTest, FloatLiteralSuffixedWithF) {
- EXPECT("var f : f32 = 1.23f;",
- "test.wgsl:1:19 error: float literals must not be suffixed with 'f'\n"
- "var f : f32 = 1.23f;\n"
- " ^\n");
-}
-
TEST_F(ParserImplErrorTest, ForLoopInitializerMissingSemicolon) {
EXPECT("fn f() { for (var i : i32 = 0 i < 8; i=i+1) {} }",
"test.wgsl:1:31 error: expected ';' for initializer in for loop\n"