[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)
Chris B via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 11 09:27:06 PST 2025
================
@@ -0,0 +1,171 @@
+#include "clang/Parse/ParseHLSLRootSignature.h"
+
+namespace clang {
+namespace hlsl {
+
+// Lexer Definitions
+
+static bool IsNumberChar(char C) {
+ // TODO(#120472): extend for float support exponents
+ return isdigit(C); // integer support
+}
+
+bool RootSignatureLexer::LexNumber(RootSignatureToken &Result) {
+ // NumericLiteralParser does not handle the sign so we will manually apply it
+ bool Negative = Buffer.front() == '-';
+ bool Signed = Negative || Buffer.front() == '+';
+ if (Signed)
+ AdvanceBuffer();
+
+ // Retrieve the possible number
+ StringRef NumSpelling = Buffer.take_while(IsNumberChar);
+
+ // Catch this now as the Literal Parser will accept it as valid
+ if (NumSpelling.empty()) {
+ PP.getDiagnostics().Report(Result.TokLoc,
+ diag::err_hlsl_invalid_number_literal);
+ return true;
+ }
+
+ // Parse the numeric value and do semantic checks on its specification
+ clang::NumericLiteralParser Literal(NumSpelling, SourceLoc,
+ PP.getSourceManager(), PP.getLangOpts(),
+ PP.getTargetInfo(), PP.getDiagnostics());
+ if (Literal.hadError)
+ return true; // Error has already been reported so just return
+
+ // Note: if IsNumberChar allows for hexidecimal we will need to turn this
+ // into a diagnostics for potential fixed-point literals
+ assert(Literal.isIntegerLiteral() && "IsNumberChar will only support digits");
+
+ // Retrieve the number value to store into the token
+ Result.Kind = TokenKind::int_literal;
+
+ // NOTE: for compabibility with DXC, we will treat any integer with '+' as an
+ // unsigned integer
+ llvm::APSInt X = llvm::APSInt(32, !Negative);
+ if (Literal.GetIntegerValue(X)) {
+ // Report that the value has overflowed
+ PP.getDiagnostics().Report(Result.TokLoc,
+ diag::err_hlsl_number_literal_overflow)
+ << (unsigned)Signed << NumSpelling;
+ return true;
+ }
+
+ X = Negative ? -X : X;
+ Result.NumLiteral = APValue(X);
+
+ AdvanceBuffer(NumSpelling.size());
+ return false;
+}
+
+bool RootSignatureLexer::Lex(SmallVector<RootSignatureToken> &Tokens) {
+ // Discard any leading whitespace
+ AdvanceBuffer(Buffer.take_while(isspace).size());
+
+ while (!Buffer.empty()) {
+ // Record where this token is in the text for usage in parser diagnostics
+ RootSignatureToken Result(SourceLoc);
+ if (LexToken(Result))
+ return true;
+
+ // Successfully Lexed the token so we can store it
+ Tokens.push_back(Result);
+
+ // Discard any trailing whitespace
+ AdvanceBuffer(Buffer.take_while(isspace).size());
+ }
+
+ return false;
+}
+
+bool RootSignatureLexer::LexToken(RootSignatureToken &Result) {
+ char C = Buffer.front();
+
+ // Punctuators
+ switch (C) {
+#define PUNCTUATOR(X, Y) \
+ case Y: { \
+ Result.Kind = TokenKind::pu_##X; \
+ AdvanceBuffer(); \
+ return false; \
+ }
+#include "clang/Parse/HLSLRootSignatureTokenKinds.def"
+ default:
+ break;
+ }
+
+ // Numeric constant
+ if (isdigit(C) || C == '-' || C == '+')
+ return LexNumber(Result);
+
+ // All following tokens require at least one additional character
+ if (Buffer.size() <= 1) {
+ PP.getDiagnostics().Report(Result.TokLoc, diag::err_hlsl_invalid_token);
----------------
llvm-beanz wrote:
Is it more useful to the user to note a failure in lexing, _or_ is it more useful at the parsing level to be able to recognize that the token was set to invalid when something else was expected?
Clang tends to do the later, which is why you get errors like "expected identifier", because the parser _knows_ the next thing should be an identifier, but the lexer just knows it didn't produce the right result (or any result).
https://github.com/llvm/llvm-project/pull/122981
More information about the cfe-commits
mailing list