138 lines · cpp
1//=== LexHLSLRootSignature.cpp - Lex Root Signature -----------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Lex/LexHLSLRootSignature.h"10 11namespace clang {12namespace hlsl {13 14using TokenKind = RootSignatureToken::Kind;15 16// Lexer Definitions17 18static bool isNumberChar(char C) {19 return isdigit(C) // integer support20 || C == '.' // float support21 || C == 'e' || C == 'E' || C == '-' || C == '+' // exponent support22 || C == 'f' || C == 'F'; // explicit float support23}24 25RootSignatureToken RootSignatureLexer::lexToken() {26 // Discard any leading whitespace27 advanceBuffer(Buffer.take_while(isspace).size());28 29 if (isEndOfBuffer())30 return RootSignatureToken(TokenKind::end_of_stream, LocOffset);31 32 // Record where this token is in the text for usage in parser diagnostics33 RootSignatureToken Result(LocOffset);34 35 char C = Buffer.front();36 37 // Punctuators38 switch (C) {39#define PUNCTUATOR(X, Y) \40 case Y: { \41 Result.TokKind = TokenKind::pu_##X; \42 advanceBuffer(); \43 return Result; \44 }45#include "clang/Lex/HLSLRootSignatureTokenKinds.def"46 default:47 break;48 }49 50 // Number literal51 if (isdigit(C) || C == '.') {52 Result.NumSpelling = Buffer.take_while(isNumberChar);53 54 // If all values are digits then we have an int literal55 bool IsInteger = Result.NumSpelling.find_if_not(isdigit) == StringRef::npos;56 57 Result.TokKind =58 IsInteger ? TokenKind::int_literal : TokenKind::float_literal;59 advanceBuffer(Result.NumSpelling.size());60 return Result;61 }62 63 // All following tokens require at least one additional character64 if (Buffer.size() <= 1) {65 Result = RootSignatureToken(TokenKind::invalid, LocOffset);66 return Result;67 }68 69 // Peek at the next character to deteremine token type70 char NextC = Buffer[1];71 72 // Registers: [tsub][0-9+]73 if ((C == 't' || C == 's' || C == 'u' || C == 'b') && isdigit(NextC)) {74 // Convert character to the register type.75 switch (C) {76 case 'b':77 Result.TokKind = TokenKind::bReg;78 break;79 case 't':80 Result.TokKind = TokenKind::tReg;81 break;82 case 'u':83 Result.TokKind = TokenKind::uReg;84 break;85 case 's':86 Result.TokKind = TokenKind::sReg;87 break;88 default:89 llvm_unreachable("Switch for an expected token was not provided");90 }91 92 advanceBuffer();93 94 // Lex the integer literal95 Result.NumSpelling = Buffer.take_while(isNumberChar);96 advanceBuffer(Result.NumSpelling.size());97 98 return Result;99 }100 101 // Keywords and Enums:102 StringRef TokSpelling =103 Buffer.take_while([](char C) { return isalnum(C) || C == '_'; });104 105 // Define a large string switch statement for all the keywords and enums106 auto Switch = llvm::StringSwitch<TokenKind>(TokSpelling);107#define KEYWORD(NAME) Switch.CaseLower(#NAME, TokenKind::kw_##NAME);108#define ENUM(NAME, LIT) Switch.CaseLower(LIT, TokenKind::en_##NAME);109#include "clang/Lex/HLSLRootSignatureTokenKinds.def"110 111 // Then attempt to retreive a string from it112 Result.TokKind = Switch.Default(TokenKind::invalid);113 advanceBuffer(TokSpelling.size());114 return Result;115}116 117RootSignatureToken RootSignatureLexer::consumeToken() {118 // If we previously peeked then just return the previous value over119 if (NextToken && NextToken->TokKind != TokenKind::end_of_stream) {120 RootSignatureToken Result = *NextToken;121 NextToken = std::nullopt;122 return Result;123 }124 return lexToken();125}126 127RootSignatureToken RootSignatureLexer::peekNextToken() {128 // Already peeked from the current token129 if (NextToken)130 return *NextToken;131 132 NextToken = lexToken();133 return *NextToken;134}135 136} // namespace hlsl137} // namespace clang138