wgsl reader: Allow 0X as a hex prefix for ints and floats
Fixed: tint:1353 Change-Id: I8252cc9d055657e361c4bceadcc59f7703f98c23 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/74380 Reviewed-by: Antonio Maiorano <amaiorano@google.com> Auto-Submit: David Neto <dneto@google.com> Reviewed-by: David Neto <dneto@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: David Neto <dneto@google.com>
This commit is contained in:
parent
9943de6813
commit
7913982f87
|
@ -342,7 +342,7 @@ Token Lexer::try_hex_float() {
|
||||||
auto source = begin_source();
|
auto source = begin_source();
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
// -?0x([0-9a-fA-F]*.?[0-9a-fA-F]+ | [0-9a-fA-F]+.[0-9a-fA-F]*)(p|P)(+|-)?[0-9]+ // NOLINT
|
// -?0[xX]([0-9a-fA-F]*.?[0-9a-fA-F]+ | [0-9a-fA-F]+.[0-9a-fA-F]*)(p|P)(+|-)?[0-9]+ // NOLINT
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
// -?
|
// -?
|
||||||
|
@ -351,8 +351,8 @@ Token Lexer::try_hex_float() {
|
||||||
sign_bit = 1;
|
sign_bit = 1;
|
||||||
end++;
|
end++;
|
||||||
}
|
}
|
||||||
// 0x
|
// 0[xX]
|
||||||
if (matches(end, "0x")) {
|
if (matches(end, "0x") || matches(end, "0X")) {
|
||||||
end += 2;
|
end += 2;
|
||||||
} else {
|
} else {
|
||||||
return {};
|
return {};
|
||||||
|
@ -663,7 +663,7 @@ Token Lexer::try_hex_integer() {
|
||||||
end++;
|
end++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matches(end, "0x")) {
|
if (matches(end, "0x") || matches(end, "0X")) {
|
||||||
end += 2;
|
end += 2;
|
||||||
} else {
|
} else {
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -394,11 +394,17 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
IntegerTest_HexSigned,
|
IntegerTest_HexSigned,
|
||||||
testing::Values(
|
testing::Values(
|
||||||
HexSignedIntData{"0x0", 0},
|
HexSignedIntData{"0x0", 0},
|
||||||
|
HexSignedIntData{"0X0", 0},
|
||||||
HexSignedIntData{"0x42", 66},
|
HexSignedIntData{"0x42", 66},
|
||||||
|
HexSignedIntData{"0X42", 66},
|
||||||
HexSignedIntData{"-0x42", -66},
|
HexSignedIntData{"-0x42", -66},
|
||||||
|
HexSignedIntData{"-0X42", -66},
|
||||||
HexSignedIntData{"0xeF1Abc9", 250719177},
|
HexSignedIntData{"0xeF1Abc9", 250719177},
|
||||||
|
HexSignedIntData{"0XeF1Abc9", 250719177},
|
||||||
HexSignedIntData{"-0x80000000", std::numeric_limits<int32_t>::min()},
|
HexSignedIntData{"-0x80000000", std::numeric_limits<int32_t>::min()},
|
||||||
HexSignedIntData{"0x7FFFFFFF", std::numeric_limits<int32_t>::max()}));
|
HexSignedIntData{"-0X80000000", std::numeric_limits<int32_t>::min()},
|
||||||
|
HexSignedIntData{"0x7FFFFFFF", std::numeric_limits<int32_t>::max()},
|
||||||
|
HexSignedIntData{"0X7FFFFFFF", std::numeric_limits<int32_t>::max()}));
|
||||||
|
|
||||||
TEST_F(LexerTest, HexPrefixOnly_IsError) {
|
TEST_F(LexerTest, HexPrefixOnly_IsError) {
|
||||||
// Could be the start of a hex integer or hex float, but is neither.
|
// Could be the start of a hex integer or hex float, but is neither.
|
||||||
|
@ -411,6 +417,17 @@ TEST_F(LexerTest, HexPrefixOnly_IsError) {
|
||||||
"integer or float hex literal has no significant digits");
|
"integer or float hex literal has no significant digits");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(LexerTest, HexPrefixUpperCaseOnly_IsError) {
|
||||||
|
// Could be the start of a hex integer or hex float, but is neither.
|
||||||
|
Source::FileContent content("0X");
|
||||||
|
Lexer l("test.wgsl", &content);
|
||||||
|
|
||||||
|
auto t = l.next();
|
||||||
|
ASSERT_TRUE(t.Is(Token::Type::kError));
|
||||||
|
EXPECT_EQ(t.to_str(),
|
||||||
|
"integer or float hex literal has no significant digits");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(LexerTest, NegativeHexPrefixOnly_IsError) {
|
TEST_F(LexerTest, NegativeHexPrefixOnly_IsError) {
|
||||||
// Could be the start of a hex integer or hex float, but is neither.
|
// Could be the start of a hex integer or hex float, but is neither.
|
||||||
Source::FileContent content("-0x");
|
Source::FileContent content("-0x");
|
||||||
|
@ -422,6 +439,17 @@ TEST_F(LexerTest, NegativeHexPrefixOnly_IsError) {
|
||||||
"integer or float hex literal has no significant digits");
|
"integer or float hex literal has no significant digits");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(LexerTest, NegativeHexPrefixUpperCaseOnly_IsError) {
|
||||||
|
// Could be the start of a hex integer or hex float, but is neither.
|
||||||
|
Source::FileContent content("-0X");
|
||||||
|
Lexer l("test.wgsl", &content);
|
||||||
|
|
||||||
|
auto t = l.next();
|
||||||
|
ASSERT_TRUE(t.Is(Token::Type::kError));
|
||||||
|
EXPECT_EQ(t.to_str(),
|
||||||
|
"integer or float hex literal has no significant digits");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(LexerTest, IntegerTest_HexSignedTooLarge) {
|
TEST_F(LexerTest, IntegerTest_HexSignedTooLarge) {
|
||||||
Source::FileContent content("0x80000000");
|
Source::FileContent content("0x80000000");
|
||||||
Lexer l("test.wgsl", &content);
|
Lexer l("test.wgsl", &content);
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace reader {
|
namespace reader {
|
||||||
namespace wgsl {
|
namespace wgsl {
|
||||||
|
@ -115,9 +117,19 @@ TEST_F(ParserImplTest, ConstLiteral_InvalidFloat_TooLargePositive) {
|
||||||
ASSERT_EQ(c.value, nullptr);
|
ASSERT_EQ(c.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if the given non-Nan float numbers are equal.
|
||||||
|
bool FloatEqual(float a, float b) {
|
||||||
|
// Avoid Clang complaining about equality test on float.
|
||||||
|
// -Wfloat-equal.
|
||||||
|
return (a <= b) && (a >= b);
|
||||||
|
}
|
||||||
|
|
||||||
struct FloatLiteralTestCase {
|
struct FloatLiteralTestCase {
|
||||||
const char* input;
|
std::string input;
|
||||||
float expected;
|
float expected;
|
||||||
|
bool operator==(const FloatLiteralTestCase& other) const {
|
||||||
|
return (input == other.input) && FloatEqual(expected, other.expected);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& out, FloatLiteralTestCase data) {
|
inline std::ostream& operator<<(std::ostream& out, FloatLiteralTestCase data) {
|
||||||
|
@ -140,7 +152,10 @@ TEST_P(ParserImplFloatLiteralTest, Parse) {
|
||||||
EXPECT_FLOAT_EQ(c->As<ast::FloatLiteralExpression>()->value, params.expected);
|
EXPECT_FLOAT_EQ(c->As<ast::FloatLiteralExpression>()->value, params.expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatLiteralTestCase float_literal_test_cases[] = {
|
using FloatLiteralTestCaseList = std::vector<FloatLiteralTestCase>;
|
||||||
|
|
||||||
|
FloatLiteralTestCaseList DecimalFloatCases() {
|
||||||
|
return FloatLiteralTestCaseList{
|
||||||
{"0.0", 0.0f}, // Zero
|
{"0.0", 0.0f}, // Zero
|
||||||
{"1.0", 1.0f}, // One
|
{"1.0", 1.0f}, // One
|
||||||
{"-1.0", -1.0f}, // MinusOne
|
{"-1.0", -1.0f}, // MinusOne
|
||||||
|
@ -151,13 +166,16 @@ FloatLiteralTestCase float_literal_test_cases[] = {
|
||||||
{"1.0", MakeFloat(0, 127, 0)}, // One
|
{"1.0", MakeFloat(0, 127, 0)}, // One
|
||||||
{"-1.0", MakeFloat(1, 127, 0)}, // NegativeOne
|
{"-1.0", MakeFloat(1, 127, 0)}, // NegativeOne
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(ParserImplFloatLiteralTest_Float,
|
INSTANTIATE_TEST_SUITE_P(ParserImplFloatLiteralTest_Float,
|
||||||
ParserImplFloatLiteralTest,
|
ParserImplFloatLiteralTest,
|
||||||
testing::ValuesIn(float_literal_test_cases));
|
testing::ValuesIn(DecimalFloatCases()));
|
||||||
|
|
||||||
const float NegInf = MakeFloat(1, 255, 0);
|
const float NegInf = MakeFloat(1, 255, 0);
|
||||||
const float PosInf = MakeFloat(0, 255, 0);
|
const float PosInf = MakeFloat(0, 255, 0);
|
||||||
FloatLiteralTestCase hexfloat_literal_test_cases[] = {
|
FloatLiteralTestCaseList HexFloatCases() {
|
||||||
|
return FloatLiteralTestCaseList{
|
||||||
// Regular numbers
|
// Regular numbers
|
||||||
{"0x0p+0", 0.f},
|
{"0x0p+0", 0.f},
|
||||||
{"0x1p+0", 1.f},
|
{"0x1p+0", 1.f},
|
||||||
|
@ -210,7 +228,8 @@ FloatLiteralTestCase hexfloat_literal_test_cases[] = {
|
||||||
{"-0x1p-130", -std::ldexp(1.f / 8.f, -127)},
|
{"-0x1p-130", -std::ldexp(1.f / 8.f, -127)},
|
||||||
|
|
||||||
{"0x1.8p-127", std::ldexp(1.f, -127) + (std::ldexp(1.f, -127) / 2.f)},
|
{"0x1.8p-127", std::ldexp(1.f, -127) + (std::ldexp(1.f, -127) / 2.f)},
|
||||||
{"0x1.8p-128", std::ldexp(1.f, -127) / 2.f + (std::ldexp(1.f, -127) / 4.f)},
|
{"0x1.8p-128",
|
||||||
|
std::ldexp(1.f, -127) / 2.f + (std::ldexp(1.f, -127) / 4.f)},
|
||||||
|
|
||||||
{"0x1p-149", MakeFloat(0, 0, 1)}, // +SmallestDenormal
|
{"0x1p-149", MakeFloat(0, 0, 1)}, // +SmallestDenormal
|
||||||
{"0x1p-148", MakeFloat(0, 0, 2)}, // +BiggerDenormal
|
{"0x1p-148", MakeFloat(0, 0, 2)}, // +BiggerDenormal
|
||||||
|
@ -323,9 +342,43 @@ FloatLiteralTestCase hexfloat_literal_test_cases[] = {
|
||||||
{"-0x1.8p-1f", -0.75f},
|
{"-0x1.8p-1f", -0.75f},
|
||||||
{"-0x2p-2f", -0.5f}, // No binary point
|
{"-0x2p-2f", -0.5f}, // No binary point
|
||||||
};
|
};
|
||||||
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P(ParserImplFloatLiteralTest_HexFloat,
|
INSTANTIATE_TEST_SUITE_P(ParserImplFloatLiteralTest_HexFloat,
|
||||||
ParserImplFloatLiteralTest,
|
ParserImplFloatLiteralTest,
|
||||||
testing::ValuesIn(hexfloat_literal_test_cases));
|
testing::ValuesIn(HexFloatCases()));
|
||||||
|
|
||||||
|
// Now test all the same hex float cases, but with 0X instead of 0x
|
||||||
|
template <typename ARR>
|
||||||
|
std::vector<FloatLiteralTestCase> UpperCase0X(const ARR& cases) {
|
||||||
|
std::vector<FloatLiteralTestCase> result;
|
||||||
|
result.reserve(cases.size());
|
||||||
|
for (const auto& c : cases) {
|
||||||
|
result.emplace_back(c);
|
||||||
|
auto& input = result.back().input;
|
||||||
|
const auto where = input.find("0x");
|
||||||
|
if (where != std::string::npos) {
|
||||||
|
input[where+1] = 'X';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
using UpperCase0XTest = ::testing::Test;
|
||||||
|
TEST_F(UpperCase0XTest, Samples) {
|
||||||
|
const auto cases = FloatLiteralTestCaseList{
|
||||||
|
{"absent", 0.0}, {"0x", 1.0}, {"0X", 2.0}, {"-0x", 3.0},
|
||||||
|
{"-0X", 4.0}, {" 0x1p1", 5.0}, {" -0x1p", 6.0}, {" examine ", 7.0}};
|
||||||
|
const auto expected = FloatLiteralTestCaseList{
|
||||||
|
{"absent", 0.0}, {"0X", 1.0}, {"0X", 2.0}, {"-0X", 3.0},
|
||||||
|
{"-0X", 4.0}, {" 0X1p1", 5.0}, {" -0X1p", 6.0}, {" examine ", 7.0}};
|
||||||
|
|
||||||
|
auto result = UpperCase0X(cases);
|
||||||
|
EXPECT_THAT(result, ::testing::ElementsAreArray(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(ParserImplFloatLiteralTest_HexFloat_UpperCase0X,
|
||||||
|
ParserImplFloatLiteralTest,
|
||||||
|
testing::ValuesIn(UpperCase0X(HexFloatCases())));
|
||||||
|
|
||||||
struct InvalidLiteralTestCase {
|
struct InvalidLiteralTestCase {
|
||||||
const char* input;
|
const char* input;
|
||||||
|
|
Loading…
Reference in New Issue