[HLSL][RootSignature] Add lexing support for floating points (#137720)

- this takes care to add support to match the [behaviour of
DXC](34b6d0f91e/tools/clang/lib/Parse/HLSLRootSignature.cpp (L74))
acceptable floating point integers

Namely:
- Allow for specifying the decimal '.'
- Allow for specifying exponents with 'e' or 'E' and allow for 'f' to
denote an otherwise interpreted integer as a float

This pr is simply responsible of creating a token that could be
interpeted as a floating point integer by `NumericLiteralParser`. As
such, we are not required to validate that the special characters only
occur once and that 'f' is only at the end of the string. These will be
validated when invoking `NumericLiteralParser` during parsing.

Resolves #126565
This commit is contained in:
Finn Plummer
2025-04-30 09:41:08 -07:00
committed by GitHub
parent ea3959e841
commit 8e4dd21e63
3 changed files with 58 additions and 9 deletions

View File

@@ -55,6 +55,7 @@
TOK(invalid, "invalid identifier")
TOK(end_of_stream, "end of stream")
TOK(int_literal, "integer literal")
TOK(float_literal, "float literal")
// Register Tokens:
TOK(bReg, "b register")

View File

@@ -16,8 +16,10 @@ using TokenKind = RootSignatureToken::Kind;
// Lexer Definitions
static bool isNumberChar(char C) {
// TODO(#126565): extend for float support exponents
return isdigit(C); // integer support
return isdigit(C) // integer support
|| C == '.' // float support
|| C == 'e' || C == 'E' || C == '-' || C == '+' // exponent support
|| C == 'f' || C == 'F'; // explicit float support
}
RootSignatureToken RootSignatureLexer::lexToken() {
@@ -45,10 +47,15 @@ RootSignatureToken RootSignatureLexer::lexToken() {
break;
}
// Integer literal
if (isdigit(C)) {
Result.TokKind = TokenKind::int_literal;
// Number literal
if (isdigit(C) || C == '.') {
Result.NumSpelling = Buffer.take_while(isNumberChar);
// If all values are digits then we have an int literal
bool IsInteger = Result.NumSpelling.find_if_not(isdigit) == StringRef::npos;
Result.TokKind =
IsInteger ? TokenKind::int_literal : TokenKind::float_literal;
advanceBuffer(Result.NumSpelling.size());
return Result;
}

View File

@@ -43,6 +43,10 @@ TEST_F(LexHLSLRootSignatureTest, ValidLexNumbersTest) {
// This test will check that we can lex different number tokens
const llvm::StringLiteral Source = R"cc(
-42 42 +42 +2147483648
42. 4.2 .42
42f 4.2F
.42e+3 4.2E-12
42.e+10f
)cc";
auto TokLoc = SourceLocation();
@@ -51,9 +55,14 @@ TEST_F(LexHLSLRootSignatureTest, ValidLexNumbersTest) {
SmallVector<hlsl::RootSignatureToken> Tokens;
SmallVector<TokenKind> Expected = {
TokenKind::pu_minus, TokenKind::int_literal, TokenKind::int_literal,
TokenKind::pu_plus, TokenKind::int_literal, TokenKind::pu_plus,
TokenKind::int_literal,
TokenKind::pu_minus, TokenKind::int_literal,
TokenKind::int_literal, TokenKind::pu_plus,
TokenKind::int_literal, TokenKind::pu_plus,
TokenKind::int_literal, TokenKind::float_literal,
TokenKind::float_literal, TokenKind::float_literal,
TokenKind::float_literal, TokenKind::float_literal,
TokenKind::float_literal, TokenKind::float_literal,
TokenKind::float_literal,
};
checkTokens(Lexer, Tokens, Expected);
@@ -73,13 +82,45 @@ TEST_F(LexHLSLRootSignatureTest, ValidLexNumbersTest) {
// is treated as an unsigned integer instead
IntToken = Tokens[6];
ASSERT_EQ(IntToken.NumSpelling, "2147483648");
// Sample decimal end
hlsl::RootSignatureToken FloatToken = Tokens[7];
ASSERT_EQ(FloatToken.NumSpelling, "42.");
// Sample decimal middle
FloatToken = Tokens[8];
ASSERT_EQ(FloatToken.NumSpelling, "4.2");
// Sample decimal start
FloatToken = Tokens[9];
ASSERT_EQ(FloatToken.NumSpelling, ".42");
// Sample float lower
FloatToken = Tokens[10];
ASSERT_EQ(FloatToken.NumSpelling, "42f");
// Sample float upper
FloatToken = Tokens[11];
ASSERT_EQ(FloatToken.NumSpelling, "4.2F");
// Sample exp +
FloatToken = Tokens[12];
ASSERT_EQ(FloatToken.NumSpelling, ".42e+3");
// Sample exp -
FloatToken = Tokens[13];
ASSERT_EQ(FloatToken.NumSpelling, "4.2E-12");
// Sample all combined
FloatToken = Tokens[14];
ASSERT_EQ(FloatToken.NumSpelling, "42.e+10f");
}
TEST_F(LexHLSLRootSignatureTest, ValidLexAllTokensTest) {
// This test will check that we can lex all defined tokens as defined in
// HLSLRootSignatureTokenKinds.def, plus some additional integer variations
const llvm::StringLiteral Source = R"cc(
42
42 42.0f
b0 t43 u987 s234