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:
David Neto 2021-12-23 22:25:21 +00:00 committed by Tint LUCI CQ
parent 9943de6813
commit 7913982f87
3 changed files with 250 additions and 169 deletions

View File

@ -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 {};

View File

@ -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);

View File

@ -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,192 +152,233 @@ 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>;
{"0.0", 0.0f}, // Zero
{"1.0", 1.0f}, // One FloatLiteralTestCaseList DecimalFloatCases() {
{"-1.0", -1.0f}, // MinusOne return FloatLiteralTestCaseList{
{"1000000000.0", 1e9f}, // Billion {"0.0", 0.0f}, // Zero
{"-0.0", std::copysign(0.0f, -5.0f)}, // NegativeZero {"1.0", 1.0f}, // One
{"0.0", MakeFloat(0, 0, 0)}, // Zero {"-1.0", -1.0f}, // MinusOne
{"-0.0", MakeFloat(1, 0, 0)}, // NegativeZero {"1000000000.0", 1e9f}, // Billion
{"1.0", MakeFloat(0, 127, 0)}, // One {"-0.0", std::copysign(0.0f, -5.0f)}, // NegativeZero
{"-1.0", MakeFloat(1, 127, 0)}, // NegativeOne {"0.0", MakeFloat(0, 0, 0)}, // Zero
}; {"-0.0", MakeFloat(1, 0, 0)}, // NegativeZero
{"1.0", MakeFloat(0, 127, 0)}, // One
{"-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() {
// Regular numbers return FloatLiteralTestCaseList{
{"0x0p+0", 0.f}, // Regular numbers
{"0x1p+0", 1.f}, {"0x0p+0", 0.f},
{"0x1p+1", 2.f}, {"0x1p+0", 1.f},
{"0x1.8p+1", 3.f}, {"0x1p+1", 2.f},
{"0x1.99999ap-4", 0.1f}, {"0x1.8p+1", 3.f},
{"0x1p-1", 0.5f}, {"0x1.99999ap-4", 0.1f},
{"0x1p-2", 0.25f}, {"0x1p-1", 0.5f},
{"0x1.8p-1", 0.75f}, {"0x1p-2", 0.25f},
{"-0x0p+0", -0.f}, {"0x1.8p-1", 0.75f},
{"-0x1p+0", -1.f}, {"-0x0p+0", -0.f},
{"-0x1p-1", -0.5f}, {"-0x1p+0", -1.f},
{"-0x1p-2", -0.25f}, {"-0x1p-1", -0.5f},
{"-0x1.8p-1", -0.75f}, {"-0x1p-2", -0.25f},
{"-0x1.8p-1", -0.75f},
// Large numbers // Large numbers
{"0x1p+9", 512.f}, {"0x1p+9", 512.f},
{"0x1p+10", 1024.f}, {"0x1p+10", 1024.f},
{"0x1.02p+10", 1024.f + 8.f}, {"0x1.02p+10", 1024.f + 8.f},
{"-0x1p+9", -512.f}, {"-0x1p+9", -512.f},
{"-0x1p+10", -1024.f}, {"-0x1p+10", -1024.f},
{"-0x1.02p+10", -1024.f - 8.f}, {"-0x1.02p+10", -1024.f - 8.f},
// Small numbers // Small numbers
{"0x1p-9", 1.0f / 512.f}, {"0x1p-9", 1.0f / 512.f},
{"0x1p-10", 1.0f / 1024.f}, {"0x1p-10", 1.0f / 1024.f},
{"0x1.02p-3", 1.0f / 1024.f + 1.0f / 8.f}, {"0x1.02p-3", 1.0f / 1024.f + 1.0f / 8.f},
{"-0x1p-9", 1.0f / -512.f}, {"-0x1p-9", 1.0f / -512.f},
{"-0x1p-10", 1.0f / -1024.f}, {"-0x1p-10", 1.0f / -1024.f},
{"-0x1.02p-3", 1.0f / -1024.f - 1.0f / 8.f}, {"-0x1.02p-3", 1.0f / -1024.f - 1.0f / 8.f},
// Near lowest non-denorm // Near lowest non-denorm
{"0x1p-124", std::ldexp(1.f * 8.f, -127)}, {"0x1p-124", std::ldexp(1.f * 8.f, -127)},
{"0x1p-125", std::ldexp(1.f * 4.f, -127)}, {"0x1p-125", std::ldexp(1.f * 4.f, -127)},
{"-0x1p-124", -std::ldexp(1.f * 8.f, -127)}, {"-0x1p-124", -std::ldexp(1.f * 8.f, -127)},
{"-0x1p-125", -std::ldexp(1.f * 4.f, -127)}, {"-0x1p-125", -std::ldexp(1.f * 4.f, -127)},
// Lowest non-denorm // Lowest non-denorm
{"0x1p-126", std::ldexp(1.f * 2.f, -127)}, {"0x1p-126", std::ldexp(1.f * 2.f, -127)},
{"-0x1p-126", -std::ldexp(1.f * 2.f, -127)}, {"-0x1p-126", -std::ldexp(1.f * 2.f, -127)},
// Denormalized values // Denormalized values
{"0x1p-127", std::ldexp(1.f, -127)}, {"0x1p-127", std::ldexp(1.f, -127)},
{"0x1p-128", std::ldexp(1.f / 2.f, -127)}, {"0x1p-128", std::ldexp(1.f / 2.f, -127)},
{"0x1p-129", std::ldexp(1.f / 4.f, -127)}, {"0x1p-129", std::ldexp(1.f / 4.f, -127)},
{"0x1p-130", std::ldexp(1.f / 8.f, -127)}, {"0x1p-130", std::ldexp(1.f / 8.f, -127)},
{"-0x1p-127", -std::ldexp(1.f, -127)}, {"-0x1p-127", -std::ldexp(1.f, -127)},
{"-0x1p-128", -std::ldexp(1.f / 2.f, -127)}, {"-0x1p-128", -std::ldexp(1.f / 2.f, -127)},
{"-0x1p-129", -std::ldexp(1.f / 4.f, -127)}, {"-0x1p-129", -std::ldexp(1.f / 4.f, -127)},
{"-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
{"0x1.fffffcp-127", MakeFloat(0, 0, 0x7fffff)}, // +LargestDenormal {"0x1.fffffcp-127", MakeFloat(0, 0, 0x7fffff)}, // +LargestDenormal
{"-0x1p-149", MakeFloat(1, 0, 1)}, // -SmallestDenormal {"-0x1p-149", MakeFloat(1, 0, 1)}, // -SmallestDenormal
{"-0x1p-148", MakeFloat(1, 0, 2)}, // -BiggerDenormal {"-0x1p-148", MakeFloat(1, 0, 2)}, // -BiggerDenormal
{"-0x1.fffffcp-127", MakeFloat(1, 0, 0x7fffff)}, // -LargestDenormal {"-0x1.fffffcp-127", MakeFloat(1, 0, 0x7fffff)}, // -LargestDenormal
{"0x1.2bfaf8p-127", MakeFloat(0, 0, 0xcafebe)}, // +Subnormal {"0x1.2bfaf8p-127", MakeFloat(0, 0, 0xcafebe)}, // +Subnormal
{"-0x1.2bfaf8p-127", MakeFloat(1, 0, 0xcafebe)}, // -Subnormal {"-0x1.2bfaf8p-127", MakeFloat(1, 0, 0xcafebe)}, // -Subnormal
{"0x1.55554p-130", MakeFloat(0, 0, 0xaaaaa)}, // +Subnormal {"0x1.55554p-130", MakeFloat(0, 0, 0xaaaaa)}, // +Subnormal
{"-0x1.55554p-130", MakeFloat(1, 0, 0xaaaaa)}, // -Subnormal {"-0x1.55554p-130", MakeFloat(1, 0, 0xaaaaa)}, // -Subnormal
// Nan -> Infinity // Nan -> Infinity
{"0x1.8p+128", PosInf}, {"0x1.8p+128", PosInf},
{"0x1.0002p+128", PosInf}, {"0x1.0002p+128", PosInf},
{"0x1.0018p+128", PosInf}, {"0x1.0018p+128", PosInf},
{"0x1.01ep+128", PosInf}, {"0x1.01ep+128", PosInf},
{"0x1.fffffep+128", PosInf}, {"0x1.fffffep+128", PosInf},
{"-0x1.8p+128", NegInf}, {"-0x1.8p+128", NegInf},
{"-0x1.0002p+128", NegInf}, {"-0x1.0002p+128", NegInf},
{"-0x1.0018p+128", NegInf}, {"-0x1.0018p+128", NegInf},
{"-0x1.01ep+128", NegInf}, {"-0x1.01ep+128", NegInf},
{"-0x1.fffffep+128", NegInf}, {"-0x1.fffffep+128", NegInf},
// Infinity // Infinity
{"0x1p+128", PosInf}, {"0x1p+128", PosInf},
{"-0x1p+128", NegInf}, {"-0x1p+128", NegInf},
{"0x32p+127", PosInf}, {"0x32p+127", PosInf},
{"0x32p+500", PosInf}, {"0x32p+500", PosInf},
{"-0x32p+127", NegInf}, {"-0x32p+127", NegInf},
{"-0x32p+500", NegInf}, {"-0x32p+500", NegInf},
// Overflow -> Infinity // Overflow -> Infinity
{"0x1p+129", PosInf}, {"0x1p+129", PosInf},
{"0x1.1p+128", PosInf}, {"0x1.1p+128", PosInf},
{"-0x1p+129", NegInf}, {"-0x1p+129", NegInf},
{"-0x1.1p+128", NegInf}, {"-0x1.1p+128", NegInf},
{"0x1.0p2147483520", PosInf}, // INT_MAX - 127 (largest valid exponent) {"0x1.0p2147483520", PosInf}, // INT_MAX - 127 (largest valid exponent)
// Underflow -> Zero // Underflow -> Zero
{"0x1p-500", 0.f}, // Exponent underflows {"0x1p-500", 0.f}, // Exponent underflows
{"-0x1p-500", -0.f}, {"-0x1p-500", -0.f},
{"0x0.00000000001p-126", 0.f}, // Fraction causes underflow {"0x0.00000000001p-126", 0.f}, // Fraction causes underflow
{"-0x0.0000000001p-127", -0.f}, {"-0x0.0000000001p-127", -0.f},
{"0x0.01p-142", 0.f}, {"0x0.01p-142", 0.f},
{"-0x0.01p-142", -0.f}, // Fraction causes additional underflow {"-0x0.01p-142", -0.f}, // Fraction causes additional underflow
{"0x1.0p-2147483520", 0}, // -(INT_MAX - 127) (smallest valid exponent) {"0x1.0p-2147483520", 0}, // -(INT_MAX - 127) (smallest valid exponent)
// Zero with non-zero exponent -> Zero // Zero with non-zero exponent -> Zero
{"0x0p+0", 0.f}, {"0x0p+0", 0.f},
{"0x0p+1", 0.f}, {"0x0p+1", 0.f},
{"0x0p-1", 0.f}, {"0x0p-1", 0.f},
{"0x0p+9999999999", 0.f}, {"0x0p+9999999999", 0.f},
{"0x0p-9999999999", 0.f}, {"0x0p-9999999999", 0.f},
// Same, but with very large positive exponents that would cause overflow // Same, but with very large positive exponents that would cause overflow
// if the mantissa were non-zero. // if the mantissa were non-zero.
{"0x0p+4000000000", 0.f}, // 4 billion: {"0x0p+4000000000", 0.f}, // 4 billion:
{"0x0p+40000000000", 0.f}, // 40 billion {"0x0p+40000000000", 0.f}, // 40 billion
{"-0x0p+40000000000", 0.f}, // As above 2, but negative mantissa {"-0x0p+40000000000", 0.f}, // As above 2, but negative mantissa
{"-0x0p+400000000000", 0.f}, {"-0x0p+400000000000", 0.f},
{"0x0.00p+4000000000", 0.f}, // As above 4, but with fractional part {"0x0.00p+4000000000", 0.f}, // As above 4, but with fractional part
{"0x0.00p+40000000000", 0.f}, {"0x0.00p+40000000000", 0.f},
{"-0x0.00p+40000000000", 0.f}, {"-0x0.00p+40000000000", 0.f},
{"-0x0.00p+400000000000", 0.f}, {"-0x0.00p+400000000000", 0.f},
{"0x0p-4000000000", 0.f}, // As above 8, but with negative exponents {"0x0p-4000000000", 0.f}, // As above 8, but with negative exponents
{"0x0p-40000000000", 0.f}, {"0x0p-40000000000", 0.f},
{"-0x0p-40000000000", 0.f}, {"-0x0p-40000000000", 0.f},
{"-0x0p-400000000000", 0.f}, {"-0x0p-400000000000", 0.f},
{"0x0.00p-4000000000", 0.f}, {"0x0.00p-4000000000", 0.f},
{"0x0.00p-40000000000", 0.f}, {"0x0.00p-40000000000", 0.f},
{"-0x0.00p-40000000000", 0.f}, {"-0x0.00p-40000000000", 0.f},
{"-0x0.00p-400000000000", 0.f}, {"-0x0.00p-400000000000", 0.f},
// Test parsing // Test parsing
{"0x0p0", 0.f}, {"0x0p0", 0.f},
{"0x0p-0", 0.f}, {"0x0p-0", 0.f},
{"0x0p+000", 0.f}, {"0x0p+000", 0.f},
{"0x00000000000000p+000000000000000", 0.f}, {"0x00000000000000p+000000000000000", 0.f},
{"0x00000000000000p-000000000000000", 0.f}, {"0x00000000000000p-000000000000000", 0.f},
{"0x00000000000001p+000000000000000", 1.f}, {"0x00000000000001p+000000000000000", 1.f},
{"0x00000000000001p-000000000000000", 1.f}, {"0x00000000000001p-000000000000000", 1.f},
{"0x0000000000000000000001.99999ap-000000000000000004", 0.1f}, {"0x0000000000000000000001.99999ap-000000000000000004", 0.1f},
{"0x2p+0", 2.f}, {"0x2p+0", 2.f},
{"0xFFp+0", 255.f}, {"0xFFp+0", 255.f},
{"0x0.8p+0", 0.5f}, {"0x0.8p+0", 0.5f},
{"0x0.4p+0", 0.25f}, {"0x0.4p+0", 0.25f},
{"0x0.4p+1", 2 * 0.25f}, {"0x0.4p+1", 2 * 0.25f},
{"0x0.4p+2", 4 * 0.25f}, {"0x0.4p+2", 4 * 0.25f},
{"0x123Ep+1", 9340.f}, {"0x123Ep+1", 9340.f},
{"-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. // Examples without a binary exponent part.
{"0x1.", 1.0f}, {"0x1.", 1.0f},
{"0x.8", 0.5f}, {"0x.8", 0.5f},
{"0x1.8", 1.5f}, {"0x1.8", 1.5f},
{"-0x1.", -1.0f}, {"-0x1.", -1.0f},
{"-0x.8", -0.5f}, {"-0x.8", -0.5f},
{"-0x1.8", -1.5f}, {"-0x1.8", -1.5f},
// Examples with a binary exponent and a 'f' suffix. // Examples with a binary exponent and a 'f' suffix.
{"0x1.p0f", 1.0f}, {"0x1.p0f", 1.0f},
{"0x.8p2f", 2.0f}, {"0x.8p2f", 2.0f},
{"0x1.8p-1f", 0.75f}, {"0x1.8p-1f", 0.75f},
{"0x2p-2f", 0.5f}, // No binary point {"0x2p-2f", 0.5f}, // No binary point
{"-0x1.p0f", -1.0f}, {"-0x1.p0f", -1.0f},
{"-0x.8p2f", -2.0f}, {"-0x.8p2f", -2.0f},
{"-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;