Skip to content

Commit 8345ff1

Browse files
committed
review: defer handling of numeric constants to the parser -> remove error states
- as commented, using the `NumericLiteralParser` during lexing of numeric constants falls more under parsing rather than lexing. this commit removes the use of this completely from the lexer - this implies that (after moving the register error to parsing) there are no longer any errors to report during lexing. instead we will just create an `invalid` or `end_of_stream` token and let the parser provide an error with more context - thus we change the api of `ConsumeToken`/`PeekNextToken` so that it no longer needs to denote an error and will just return a token. this greatly simplifies the lexer implementation as we no longer need to pass down the pre-processor
1 parent ca2a2cb commit 8345ff1

File tree

5 files changed

+73
-304
lines changed

5 files changed

+73
-304
lines changed

clang/include/clang/Basic/DiagnosticLexKinds.td

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,12 +1017,4 @@ Error<"'#pragma unsafe_buffer_usage' was not ended">;
10171017

10181018
def err_pp_pragma_unsafe_buffer_usage_syntax :
10191019
Error<"expected 'begin' or 'end'">;
1020-
1021-
// HLSL Root Signature Lexing Errors
1022-
let CategoryName = "Root Signature Lexical Issue" in {
1023-
def err_hlsl_number_literal_overflow :
1024-
Error<"integer literal '%0' is too large to be represented in a 32-bit integer type">;
1025-
def err_hlsl_invalid_register_literal: Error<"expected unsigned integer literal as part of register">;
1026-
}
1027-
10281020
}

clang/include/clang/Parse/HLSLRootSignatureTokenKinds.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
#endif
5151

5252
// General Tokens:
53-
TOK(error)
5453
TOK(invalid)
5554
TOK(end_of_stream)
5655
TOK(int_literal)

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ struct RootSignatureToken {
3131
#include "clang/Parse/HLSLRootSignatureTokenKinds.def"
3232
};
3333

34-
Kind Kind = Kind::error;
34+
Kind Kind = Kind::invalid;
3535

3636
// Retain the SouceLocation of the token for diagnostics
3737
clang::SourceLocation TokLoc;
3838

39-
APValue NumLiteral = APValue();
39+
// Retain spelling of an numeric constant to be parsed later
40+
StringRef NumSpelling;
4041

4142
// Constructors
42-
RootSignatureToken() : TokLoc(SourceLocation()) {}
4343
RootSignatureToken(clang::SourceLocation TokLoc) : TokLoc(TokLoc) {}
4444
RootSignatureToken(enum Kind Kind, clang::SourceLocation TokLoc)
4545
: Kind(Kind), TokLoc(TokLoc) {}
@@ -48,23 +48,15 @@ using TokenKind = enum RootSignatureToken::Kind;
4848

4949
class RootSignatureLexer {
5050
public:
51-
RootSignatureLexer(StringRef Signature, clang::SourceLocation SourceLoc,
52-
clang::Preprocessor &PP)
53-
: Buffer(Signature), SourceLoc(SourceLoc), PP(PP) {}
51+
RootSignatureLexer(StringRef Signature, clang::SourceLocation SourceLoc)
52+
: Buffer(Signature), SourceLoc(SourceLoc) {}
5453

55-
/// Updates CurToken to the next token. Either it will take the previously
56-
/// lexed NextToken, or it will lex a token.
57-
///
58-
/// The return value denotes if there was a failure.
59-
bool ConsumeToken();
54+
/// Consumes and returns the next token.
55+
RootSignatureToken ConsumeToken();
6056

61-
/// Returns the token that comes after CurToken or std::nullopt if an
62-
/// error is encountered during lexing of the next token.
63-
std::optional<RootSignatureToken> PeekNextToken();
57+
/// Returns the token that proceeds CurToken
58+
RootSignatureToken PeekNextToken();
6459

65-
RootSignatureToken GetCurToken() { return CurToken; }
66-
67-
/// Check if we have reached the end of input
6860
bool EndOfBuffer() {
6961
AdvanceBuffer(Buffer.take_while(isspace).size());
7062
return Buffer.empty();
@@ -74,19 +66,17 @@ class RootSignatureLexer {
7466
// Internal buffer to iterate over
7567
StringRef Buffer;
7668

77-
// Current Token state
78-
RootSignatureToken CurToken;
69+
// Current peek state
7970
std::optional<RootSignatureToken> NextToken = std::nullopt;
8071

8172
// Passed down parameters from Sema
8273
clang::SourceLocation SourceLoc;
83-
clang::Preprocessor &PP;
8474

85-
bool LexNumber(RootSignatureToken &Result);
86-
bool LexToken(RootSignatureToken &Result);
75+
/// Consumes the buffer and returns the lexed token.
76+
RootSignatureToken LexToken();
8777

88-
// Advance the buffer by the specified number of characters. Updates the
89-
// SourceLocation appropriately.
78+
/// Advance the buffer by the specified number of characters.
79+
/// Updates the SourceLocation appropriately.
9080
void AdvanceBuffer(unsigned NumCharacters = 1) {
9181
Buffer = Buffer.drop_front(NumCharacters);
9282
SourceLoc = SourceLoc.getLocWithOffset(NumCharacters);

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 34 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -10,45 +10,15 @@ static bool IsNumberChar(char C) {
1010
return isdigit(C); // integer support
1111
}
1212

13-
bool RootSignatureLexer::LexNumber(RootSignatureToken &Result) {
14-
// Retrieve the possible number
15-
StringRef NumSpelling = Buffer.take_while(IsNumberChar);
16-
17-
// Parse the numeric value and do semantic checks on its specification
18-
clang::NumericLiteralParser Literal(NumSpelling, SourceLoc,
19-
PP.getSourceManager(), PP.getLangOpts(),
20-
PP.getTargetInfo(), PP.getDiagnostics());
21-
if (Literal.hadError)
22-
return true; // Error has already been reported so just return
23-
24-
// Note: if IsNumberChar allows for hexidecimal we will need to turn this
25-
// into a diagnostics for potential fixed-point literals
26-
assert(Literal.isIntegerLiteral() && "IsNumberChar will only support digits");
27-
28-
// Retrieve the number value to store into the token
29-
30-
llvm::APSInt X = llvm::APSInt(32, true);
31-
if (Literal.GetIntegerValue(X)) {
32-
// Report that the value has overflowed
33-
PP.getDiagnostics().Report(Result.TokLoc,
34-
diag::err_hlsl_number_literal_overflow)
35-
<< NumSpelling;
36-
return true;
37-
}
38-
39-
Result.Kind = TokenKind::int_literal;
40-
Result.NumLiteral = APValue(X);
41-
42-
AdvanceBuffer(NumSpelling.size());
43-
return false;
44-
}
45-
46-
bool RootSignatureLexer::LexToken(RootSignatureToken &Result) {
13+
RootSignatureToken RootSignatureLexer::LexToken() {
4714
// Discard any leading whitespace
4815
AdvanceBuffer(Buffer.take_while(isspace).size());
4916

17+
if (EndOfBuffer())
18+
return RootSignatureToken(TokenKind::end_of_stream, SourceLoc);
19+
5020
// Record where this token is in the text for usage in parser diagnostics
51-
Result = RootSignatureToken(SourceLoc);
21+
RootSignatureToken Result(SourceLoc);
5222

5323
char C = Buffer.front();
5424

@@ -58,44 +28,33 @@ bool RootSignatureLexer::LexToken(RootSignatureToken &Result) {
5828
case Y: { \
5929
Result.Kind = TokenKind::pu_##X; \
6030
AdvanceBuffer(); \
61-
return false; \
31+
return Result; \
6232
}
6333
#include "clang/Parse/HLSLRootSignatureTokenKinds.def"
6434
default:
6535
break;
6636
}
6737

68-
// Numeric constant
69-
if (isdigit(C))
70-
return LexNumber(Result);
38+
// Integer literal
39+
if (isdigit(C)) {
40+
Result.Kind = TokenKind::int_literal;
41+
Result.NumSpelling = Buffer.take_while(IsNumberChar);
42+
AdvanceBuffer(Result.NumSpelling.size());
43+
return Result;
44+
}
7145

7246
// All following tokens require at least one additional character
7347
if (Buffer.size() <= 1) {
7448
Result = RootSignatureToken(TokenKind::invalid, SourceLoc);
75-
return false;
49+
return Result;
7650
}
7751

7852
// Peek at the next character to deteremine token type
7953
char NextC = Buffer[1];
8054

8155
// Registers: [tsub][0-9+]
8256
if ((C == 't' || C == 's' || C == 'u' || C == 'b') && isdigit(NextC)) {
83-
AdvanceBuffer();
84-
85-
if (LexNumber(Result))
86-
return true; // Error parsing number which is already reported
87-
88-
// Lex number could also parse a float so ensure it was an unsigned int
89-
if (Result.Kind != TokenKind::int_literal ||
90-
Result.NumLiteral.getInt().isSigned()) {
91-
// Return invalid number literal for register error
92-
PP.getDiagnostics().Report(Result.TokLoc,
93-
diag::err_hlsl_invalid_register_literal);
94-
return true;
95-
}
96-
9757
// Convert character to the register type.
98-
// This is done after LexNumber to override the TokenKind
9958
switch (C) {
10059
case 'b':
10160
Result.Kind = TokenKind::bReg;
@@ -112,7 +71,14 @@ bool RootSignatureLexer::LexToken(RootSignatureToken &Result) {
11271
default:
11372
llvm_unreachable("Switch for an expected token was not provided");
11473
}
115-
return false;
74+
75+
AdvanceBuffer();
76+
77+
// Lex the integer literal
78+
Result.NumSpelling = Buffer.take_while(IsNumberChar);
79+
AdvanceBuffer(Result.NumSpelling.size());
80+
81+
return Result;
11682
}
11783

11884
// Keywords and Enums:
@@ -128,44 +94,26 @@ bool RootSignatureLexer::LexToken(RootSignatureToken &Result) {
12894
// Then attempt to retreive a string from it
12995
Result.Kind = Switch.Default(TokenKind::invalid);
13096
AdvanceBuffer(TokSpelling.size());
131-
return false;
97+
return Result;
13298
}
13399

134-
bool RootSignatureLexer::ConsumeToken() {
135-
// If we previously peeked then just copy the value over
100+
RootSignatureToken RootSignatureLexer::ConsumeToken() {
101+
// If we previously peeked then just return the previous value over
136102
if (NextToken && NextToken->Kind != TokenKind::end_of_stream) {
137-
// Propogate error up if error was encountered during previous peek
138-
if (NextToken->Kind == TokenKind::error)
139-
return true;
140-
CurToken = *NextToken;
103+
RootSignatureToken Result = *NextToken;
141104
NextToken = std::nullopt;
142-
return false;
105+
return Result;
143106
}
144-
145-
// This will be implicity be true if NextToken->Kind == end_of_stream
146-
if (EndOfBuffer()) {
147-
CurToken = RootSignatureToken(TokenKind::end_of_stream, SourceLoc);
148-
return false;
149-
}
150-
151-
return LexToken(CurToken);
107+
return LexToken();
152108
}
153109

154-
std::optional<RootSignatureToken> RootSignatureLexer::PeekNextToken() {
110+
RootSignatureToken RootSignatureLexer::PeekNextToken() {
155111
// Already peeked from the current token
156-
if (NextToken.has_value())
157-
return NextToken;
158-
159-
RootSignatureToken Result;
160-
if (EndOfBuffer()) {
161-
Result = RootSignatureToken(TokenKind::end_of_stream, SourceLoc);
162-
} else if (LexToken(Result)) { // propogate lex error up
163-
// store error token to prevent further peeking
164-
NextToken = RootSignatureToken();
165-
return std::nullopt;
166-
}
167-
NextToken = Result;
168-
return Result;
112+
if (NextToken)
113+
return *NextToken;
114+
115+
NextToken = LexToken();
116+
return *NextToken;
169117
}
170118

171119
} // namespace hlsl

0 commit comments

Comments
 (0)