Changeset 247171 in webkit
- Timestamp:
- Jul 5, 2019 1:10:36 PM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r247170 r247171 1 2019-07-05 Robin Morisset <rmorisset@apple.com> 2 3 [WHLSL] Optimize the lexer 4 https://bugs.webkit.org/show_bug.cgi?id=199520 5 6 Reviewed by Myles Maxfield. 7 8 This patch includes a number of small optimizations to the lexer: 9 - By creating two new types of Token (Invalid and EOF), we can avoid having to manipulate Optional<Token> everywhere 10 - By combining the lexing of identifiers, keywords and operator names, we can avoid re-reading them several times 11 - By storing mere offsets in the tokens instead of string views, we save space in the common case where the string view is unused (e.g. for keywords) 12 - By storing mere offsets in the tokens instead of line numbers, we can simplify the whitespace and comment lexing; and we can easily recompute the line number on demand 13 - By using templates we can avoid constructing and destructing vectors at runtime every time we call tryTypes, consumeTypes or peekTypes; as well as avoiding a call to find(). 14 - I also hoisted the length check out of the loop in Lexer::string() 15 All of this combined brought the time spent in the parser when running LayoutTests/webgpu/whlsl-test-harness-test.html 5 times on my machine from 612ms to 462ms. 16 17 I also removed the 'anyCharacter' method since it was dead code. 18 I also removed Lexer::position(), but it is directly equivalent now to peek().startOffset. 19 20 No new tests as there is no intended functional change. 21 22 * Modules/webgpu/WHLSL/WHLSLLexer.cpp: 23 (WebCore::WHLSL::Lexer::Token::typeName): 24 (WebCore::WHLSL::Lexer::consumeTokenFromStream): 25 (WebCore::WHLSL::Lexer::lineNumberFromOffset): 26 (WebCore::WHLSL::isWhitespace): 27 (WebCore::WHLSL::isNewline): 28 (WebCore::WHLSL::Lexer::skipWhitespaceAndComments): 29 (WebCore::WHLSL::Lexer::digitStar const): 30 (WebCore::WHLSL::Lexer::completeOperatorName const): 31 * Modules/webgpu/WHLSL/WHLSLLexer.h: 32 (WebCore::WHLSL::Lexer::Lexer): 33 (WebCore::WHLSL::Lexer::Token::stringView): 34 (WebCore::WHLSL::Lexer::consumeToken): 35 (WebCore::WHLSL::Lexer::peek const): 36 (WebCore::WHLSL::Lexer::peekFurther const): 37 (WebCore::WHLSL::Lexer::state const): 38 (WebCore::WHLSL::Lexer::setState): 39 (WebCore::WHLSL::Lexer::isFullyConsumed const): 40 (WebCore::WHLSL::Lexer::errorString): 41 (WebCore::WHLSL::Lexer::string const): 42 * Modules/webgpu/WHLSL/WHLSLNameResolver.h: 43 * Modules/webgpu/WHLSL/WHLSLParser.cpp: 44 (WebCore::WHLSL::Parser::parse): 45 (WebCore::WHLSL::Parser::peek): 46 (WebCore::WHLSL::Parser::peekFurther): 47 (WebCore::WHLSL::Types::includes): 48 (WebCore::WHLSL::Types::appendNameTo): 49 (WebCore::WHLSL::Types<t>::includes): 50 (WebCore::WHLSL::Types<t>::appendNameTo): 51 (WebCore::WHLSL::Parser::peekTypes): 52 (WebCore::WHLSL::Parser::tryType): 53 (WebCore::WHLSL::Parser::tryTypes): 54 (WebCore::WHLSL::Parser::consumeType): 55 (WebCore::WHLSL::Parser::consumeTypes): 56 (WebCore::WHLSL::Parser::consumeIntegralLiteral): 57 (WebCore::WHLSL::Parser::parseConstantExpression): 58 (WebCore::WHLSL::Parser::parseTypeArgument): 59 (WebCore::WHLSL::Parser::parseTypeSuffixAbbreviated): 60 (WebCore::WHLSL::Parser::parseTypeSuffixNonAbbreviated): 61 (WebCore::WHLSL::Parser::parseType): 62 (WebCore::WHLSL::Parser::parseTypeDefinition): 63 (WebCore::WHLSL::Parser::parseBuiltInSemantic): 64 (WebCore::WHLSL::Parser::parseResourceSemantic): 65 (WebCore::WHLSL::Parser::parseQualifiers): 66 (WebCore::WHLSL::Parser::parseStructureElement): 67 (WebCore::WHLSL::Parser::parseStructureDefinition): 68 (WebCore::WHLSL::Parser::parseEnumerationDefinition): 69 (WebCore::WHLSL::Parser::parseEnumerationMember): 70 (WebCore::WHLSL::Parser::parseNativeTypeDeclaration): 71 (WebCore::WHLSL::Parser::parseParameter): 72 (WebCore::WHLSL::Parser::parseComputeFunctionDeclaration): 73 (WebCore::WHLSL::Parser::parseVertexOrFragmentFunctionDeclaration): 74 (WebCore::WHLSL::Parser::parseRegularFunctionDeclaration): 75 (WebCore::WHLSL::Parser::parseBlockBody): 76 (WebCore::WHLSL::Parser::parseSwitchCase): 77 (WebCore::WHLSL::Parser::parseVariableDeclaration): 78 (WebCore::WHLSL::Parser::parseStatement): 79 (WebCore::WHLSL::Parser::parseEffectfulAssignment): 80 (WebCore::WHLSL::Parser::parseLimitedSuffixOperator): 81 (WebCore::WHLSL::Parser::parseSuffixOperator): 82 (WebCore::WHLSL::Parser::completeAssignment): 83 (WebCore::WHLSL::Parser::parsePossibleTernaryConditional): 84 (WebCore::WHLSL::Parser::completePossibleLogicalBinaryOperation): 85 (WebCore::WHLSL::Parser::completePossibleRelationalBinaryOperation): 86 (WebCore::WHLSL::Parser::completePossibleShift): 87 (WebCore::WHLSL::Parser::completePossibleAdd): 88 (WebCore::WHLSL::Parser::completePossibleMultiply): 89 (WebCore::WHLSL::Parser::parsePossiblePrefix): 90 (WebCore::WHLSL::Parser::parseCallExpression): 91 (WebCore::WHLSL::Parser::parseTerm): 92 * Modules/webgpu/WHLSL/WHLSLParser.h: 93 * Modules/webgpu/WHLSL/WHLSLPreserveVariableLifetimes.cpp: 94 (WebCore::WHLSL::anonymousToken): 95 1 96 2019-07-05 Robin Morisset <rmorisset@apple.com> 2 97 -
trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLLexer.cpp
r243091 r247171 248 248 case Type::At: 249 249 return "@"; 250 case Type::EndOfFile: 251 return "EOF"; 252 case Type::Invalid: 253 return "LEXING_ERROR"; 250 254 } 251 255 } … … 373 377 } 374 378 375 auto Lexer::consumeTokenFromStream() -> Optional<Token>376 { 377 auto prepare = [&](unsigned newOffset, Token::Type type) -> Optional<Token>{379 auto Lexer::consumeTokenFromStream() -> Token 380 { 381 auto prepare = [&](unsigned newOffset, Token::Type type) -> Token { 378 382 auto oldOffset = m_offset; 379 383 m_offset = newOffset; 380 384 skipWhitespaceAndComments(); 381 return { { m_stringView.substring(oldOffset, newOffset - oldOffset), m_lineNumber, type }};385 return { oldOffset, newOffset, type }; 382 386 }; 383 387 388 if (auto newOffset = identifier(m_offset)) { 389 if (auto result = recognizeKeyword(*newOffset)) { 390 if (*result == Token::Type::Operator) { 391 if (auto newerOffset = completeOperatorName(*newOffset)) 392 return prepare(*newerOffset, Token::Type::OperatorName); 393 } 394 return prepare(*newOffset, *result); 395 } 396 return prepare(*newOffset, Token::Type::Identifier); 397 } 384 398 if (auto newOffset = floatLiteral(m_offset)) 385 399 return prepare(*newOffset, Token::Type::FloatLiteral); … … 388 402 if (auto newOffset = intLiteral(m_offset)) 389 403 return prepare(*newOffset, Token::Type::IntLiteral); 390 if (auto newOffset = operatorName(m_offset))391 return prepare(*newOffset, Token::Type::OperatorName);392 if (auto newOffset = identifier(m_offset)) {393 if (auto result = recognizeKeyword(*newOffset))394 return prepare(*newOffset, *result);395 return prepare(*newOffset, Token::Type::Identifier);396 }397 404 // Sorted by length, so longer matches are preferable to shorter matches. 398 405 if (auto newOffset = string(">>=", m_offset)) … … 491 498 return prepare(*newOffset, Token::Type::At); 492 499 493 return WTF::nullopt; 494 } 495 496 void Lexer::skipWhitespaceAndComments() 497 { 498 unsigned savedOffset; 499 do { 500 savedOffset = m_offset; 501 skipWhitespace(); 502 skipLineComment(); 503 skipLongComment(); 504 } while (savedOffset != m_offset); 505 } 500 if (m_offset == m_stringView.length()) 501 return prepare(m_offset, Token::Type::EndOfFile); 502 return prepare(m_offset, Token::Type::Invalid); 503 } 504 505 unsigned Lexer::lineNumberFromOffset(unsigned targetOffset) 506 { 507 // Counting from 1 to match most text editors. 508 unsigned lineNumber = 1; 509 for (unsigned offset = 0; offset < targetOffset; ++offset) { 510 if (m_stringView[offset] == '\n') 511 ++lineNumber; 512 } 513 return lineNumber; 514 } 515 516 // We can take advantage of two properties of Unicode: 517 // 1. The consitutent UTF-16 code units for all non-BMP code points are surrogates, 518 // which means we'll never see a false match. If we see a BMP code unit, we 519 // really have a BMP code point. 520 // 2. Everything we're looking for is in BMP 506 521 507 522 static inline bool isWhitespace(UChar codeUnit) … … 529 544 } 530 545 531 // We can take advantage of two properties of Unicode: 532 // 1. The consitutent UTF-16 code units for all non-BMP code points are surrogates, 533 // which means we'll never see a false match. If we see a BMP code unit, we 534 // really have a BMP code point. 535 // 2. Everything we're looking for is in BMP 536 537 void Lexer::skipWhitespace() 538 { 539 for ( ; m_offset < m_stringView.length() && isWhitespace(m_stringView[m_offset]); ++m_offset) { 540 if (m_stringView[m_offset] == '\r' && m_offset + 1 < m_stringView.length() && m_stringView[m_offset + 1] == '\n') { 546 void Lexer::skipWhitespaceAndComments() 547 { 548 while (m_offset < m_stringView.length()) { 549 if (isWhitespace(m_stringView[m_offset])) 541 550 ++m_offset; 542 ++m_lineNumber; 543 } else if (isNewline(m_stringView[m_offset])) 544 ++m_lineNumber; 545 } 546 } 547 548 void Lexer::skipLineComment() 549 { 550 if (m_offset + 1 >= m_stringView.length() || m_stringView[m_offset] != '/' || m_stringView[m_offset + 1] != '/') 551 return; 552 553 m_offset += 2; 554 for ( ; m_offset < m_stringView.length() && !isNewline(m_stringView[m_offset]); ++m_offset) { } 555 } 556 557 void Lexer::skipLongComment() 558 { 559 if (m_offset + 1 >= m_stringView.length() || m_stringView[m_offset] != '/' || m_stringView[m_offset + 1] != '*') 560 return; 561 562 m_offset += 2; 563 do { 564 for ( ; m_offset < m_stringView.length() && m_stringView[m_offset] != '*'; ++m_offset) { 565 if (m_stringView[m_offset] == '\r' && m_offset + 1 < m_stringView.length() && m_stringView[m_offset + 1] == '\n') { 566 ++m_offset; 567 ++m_lineNumber; 568 } else if (isNewline(m_stringView[m_offset])) 569 ++m_lineNumber; 570 } 571 if (m_offset < m_stringView.length()) 572 ++m_offset; 573 if (m_offset < m_stringView.length() && m_stringView[m_offset] == '/') { 574 ++m_offset; 551 else if (m_stringView[m_offset] == '/' && m_offset + 1 < m_stringView.length()) { 552 if (m_stringView[m_offset + 1] == '/') { 553 // Line comment 554 m_offset += 2; 555 // Note that in the case of \r\n this makes the comment end on the \r. It is fine, as the \n after that is simple whitespace. 556 for ( ; m_offset < m_stringView.length() && !isNewline(m_stringView[m_offset]); ++m_offset) { } 557 } else if (m_stringView[m_offset + 1] == '*') { 558 // Long comment 559 for ( ; m_offset < m_stringView.length() ; ++m_offset) { 560 if (m_stringView[m_offset] == '*' && m_offset + 1 < m_stringView.length() && m_stringView[m_offset + 1] == '/') { 561 m_offset += 2; 562 break; 563 } 564 } 565 } 566 } else 575 567 break; 576 } 577 } while (m_offset < m_stringView.length()); 568 } 578 569 } 579 570 … … 677 668 unsigned Lexer::digitStar(unsigned offset) const 678 669 { 679 while (true) { 680 auto result = digit(offset); 681 if (!result) 682 return offset; 670 while (auto result = digit(offset)) 683 671 offset = *result; 684 }672 return offset; 685 673 } 686 674 … … 755 743 } 756 744 757 Optional<unsigned> Lexer::operatorName(unsigned offset) const 758 { 759 if (auto result = string("operator&.", offset)) 745 Optional<unsigned> Lexer::completeOperatorName(unsigned offset) const 746 { 747 // Sorted by length, so longer matches are preferable to shorter matches. 748 if (auto result = string("&[]", offset)) 749 return result; 750 if (auto result = string("[]=", offset)) 751 return result; 752 if (auto result = string(">>", offset)) 753 return result; 754 if (auto result = string("<<", offset)) 755 return result; 756 if (auto result = string("++", offset)) 757 return result; 758 if (auto result = string("--", offset)) 759 return result; 760 if (auto result = string("&&", offset)) 761 return result; 762 if (auto result = string("||", offset)) 763 return result; 764 if (auto result = string(">=", offset)) 765 return result; 766 if (auto result = string("<=", offset)) 767 return result; 768 if (auto result = string("==", offset)) 769 return result; 770 if (auto result = string("[]", offset)) 771 return result; 772 if (auto result = string("&.", offset)) 760 773 return validIdentifier(*result); 761 if (auto result = string("operator.", offset)) { 762 if ((result = validIdentifier(*result))) { 763 if (auto result2 = character('=', *result)) 764 return result2; 765 return *result; 774 if (auto result = character('+', offset)) 775 return result; 776 if (auto result = character('-', offset)) 777 return result; 778 if (auto result = character('*', offset)) 779 return result; 780 if (auto result = character('/', offset)) 781 return result; 782 if (auto result = character('%', offset)) 783 return result; 784 if (auto result = character('<', offset)) 785 return result; 786 if (auto result = character('>', offset)) 787 return result; 788 if (auto result = character('!', offset)) 789 return result; 790 if (auto result = character('~', offset)) 791 return result; 792 if (auto result = character('&', offset)) 793 return result; 794 if (auto result = character('^', offset)) 795 return result; 796 if (auto result = character('|', offset)) 797 return result; 798 if (auto result = character('.', offset)) { 799 if (auto result2 = validIdentifier(*result)) { 800 if (auto result3 = character('=', *result2)) 801 return result3; 802 return *result2; 766 803 } 767 804 } 768 if (auto result = string("operator", offset)) {769 // Sorted by length, so longer matches are preferable to shorter matches.770 if (auto result2 = string("&[]", *result))771 return result2;772 if (auto result2 = string("[]=", *result))773 return result2;774 if (auto result2 = string(">>", *result))775 return result2;776 if (auto result2 = string("<<", *result))777 return result2;778 if (auto result2 = string("++", *result))779 return result2;780 if (auto result2 = string("--", *result))781 return result2;782 if (auto result2 = string("&&", *result))783 return result2;784 if (auto result2 = string("||", *result))785 return result2;786 if (auto result2 = string(">=", *result))787 return result2;788 if (auto result2 = string("<=", *result))789 return result2;790 if (auto result2 = string("==", *result))791 return result2;792 if (auto result2 = string("[]", *result))793 return result2;794 if (auto result2 = character('+', *result))795 return result2;796 if (auto result2 = character('-', *result))797 return result2;798 if (auto result2 = character('*', *result))799 return result2;800 if (auto result2 = character('/', *result))801 return result2;802 if (auto result2 = character('%', *result))803 return result2;804 if (auto result2 = character('<', *result))805 return result2;806 if (auto result2 = character('>', *result))807 return result2;808 if (auto result2 = character('!', *result))809 return result2;810 if (auto result2 = character('~', *result))811 return result2;812 if (auto result2 = character('&', *result))813 return result2;814 if (auto result2 = character('^', *result))815 return result2;816 if (auto result2 = character('|', *result))817 return result2;818 }819 805 return WTF::nullopt; 820 806 } -
trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLLexer.h
r247164 r247171 58 58 59 59 struct Token { 60 Token() = delete; 61 Token(const Token&) = default; 62 Token(Token&&) = default; 63 Token& operator=(const Token&) = default; 64 Token& operator=(Token&&) = default; 65 66 StringView stringView; 67 unsigned lineNumber; 68 enum class Type { 60 unsigned startOffset; 61 unsigned endOffset; 62 enum class Type : uint8_t { 69 63 IntLiteral, 70 64 UintLiteral, … … 173 167 ExclamationPoint, 174 168 At, 175 } type; 169 EndOfFile, 170 Invalid 171 } type {Type::Invalid}; 176 172 177 173 static const char* typeName(Type); 174 175 const StringView stringView(const Lexer& lexer) 176 { 177 return lexer.m_stringView.substring(startOffset, endOffset - startOffset); 178 } 178 179 }; 179 180 180 Optional<Token>consumeToken()181 Token consumeToken() 181 182 { 182 183 auto result = m_ringBuffer[m_ringBufferIndex]; … … 186 187 } 187 188 188 Optional<Token> peek()189 Token peek() const 189 190 { 190 191 return m_ringBuffer[m_ringBufferIndex]; 191 192 } 192 193 193 Optional<Token> peekFurther()194 Token peekFurther() const 194 195 { 195 196 return m_ringBuffer[(m_ringBufferIndex + 1) % 2]; … … 199 200 // https://bugs.webkit.org/show_bug.cgi?id=198357 200 201 struct State { 201 Optional<Token>ringBuffer[2];202 Token ringBuffer[2]; 202 203 unsigned ringBufferIndex; 203 204 unsigned offset; 204 unsigned lineNumber;205 205 }; 206 206 … … 212 212 state.ringBufferIndex = m_ringBufferIndex; 213 213 state.offset = m_offset; 214 state.lineNumber = m_lineNumber;215 214 return state; 216 215 } … … 222 221 m_ringBufferIndex = state.ringBufferIndex; 223 222 m_offset = state.offset; 224 m_lineNumber = state.lineNumber;225 223 226 224 } … … 232 230 m_ringBufferIndex = WTFMove(state.ringBufferIndex); 233 231 m_offset = WTFMove(state.offset); 234 m_lineNumber = WTFMove(state.lineNumber);235 232 } 236 233 237 234 bool isFullyConsumed() const 238 235 { 239 return m_offset == m_stringView.length();236 return peek().type == Token::Type::EndOfFile; 240 237 } 241 238 242 239 String errorString(const Token& token, const String& message) 243 240 { 244 return makeString("Parse error at line ", token.lineNumber, ": ", message);241 return makeString("Parse error at line ", lineNumberFromOffset(token.startOffset), ": ", message); 245 242 } 246 243 247 244 private: 248 Optional<Token>consumeTokenFromStream();245 Token consumeTokenFromStream(); 249 246 250 247 void skipWhitespaceAndComments(); 251 void skipWhitespace(); 252 void skipLineComment(); 253 void skipLongComment(); 248 249 unsigned lineNumberFromOffset(unsigned offset); 254 250 255 251 Optional<Token::Type> recognizeKeyword(unsigned end); … … 266 262 unsigned digitStar(unsigned) const; 267 263 Optional<unsigned> character(char, unsigned) const; 268 template<unsigned length> Optional<unsigned> anyCharacter(const char (&string)[length], unsigned) const;269 264 Optional<unsigned> coreFloatLiteralType1(unsigned) const; 270 265 Optional<unsigned> coreFloatLiteral(unsigned) const; … … 273 268 Optional<unsigned> validIdentifier(unsigned) const; 274 269 Optional<unsigned> identifier(unsigned) const; 275 Optional<unsigned> operatorName(unsigned) const;270 Optional<unsigned> completeOperatorName(unsigned) const; 276 271 277 272 StringView m_stringView; 278 Optional<Token>m_ringBuffer[2];273 Token m_ringBuffer[2]; 279 274 unsigned m_ringBufferIndex { 0 }; 280 275 unsigned m_offset { 0 }; 281 unsigned m_lineNumber { 0 };282 276 }; 283 277 284 278 template<unsigned length> Optional<unsigned> Lexer::string(const char (&string)[length], unsigned offset) const 285 279 { 280 if (offset + length > m_stringView.length()) 281 return WTF::nullopt; 286 282 for (unsigned i = 0; i < length - 1; ++i) { 287 if ( offset + i >= m_stringView.length() ||m_stringView[offset + i] != string[i])283 if (m_stringView[offset + i] != string[i]) 288 284 return WTF::nullopt; 289 285 } … … 291 287 } 292 288 293 template<unsigned length> Optional<unsigned> Lexer::anyCharacter(const char (&string)[length], unsigned offset) const294 {295 if (offset >= m_stringView.length())296 return WTF::nullopt;297 for (unsigned i = 0; i < length - 1; ++i) {298 if (m_stringView[offset] == string[i])299 return offset + 1;300 }301 return WTF::nullopt;302 }303 304 289 } // namespace WHLSL 305 290 -
trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h
r247170 r247171 45 45 virtual ~NameResolver(); 46 46 47 void visit(AST::FunctionDefinition&) override;48 49 47 void setCurrentFunctionDefinition(AST::FunctionDefinition* functionDefinition) 50 48 { … … 53 51 54 52 private: 53 void visit(AST::FunctionDefinition&) override; 55 54 void visit(AST::NativeFunctionDeclaration&) override; 56 55 void visit(AST::TypeReference&) override; -
trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp
r247110 r247171 67 67 while (!m_lexer.isFullyConsumed()) { 68 68 auto token = m_lexer.peek(); 69 if (!token)70 break;71 switch (token->type) {69 switch (token.type) { 70 case Lexer::Token::Type::Invalid: 71 return WTF::nullopt; 72 72 case Lexer::Token::Type::Semicolon: 73 73 m_lexer.consumeToken(); … … 136 136 auto Parser::peek() -> Expected<Lexer::Token, Error> 137 137 { 138 if (auto token = m_lexer.peek()) {139 return *token;140 }138 auto token = m_lexer.peek(); 139 if (token.type != Lexer::Token::Type::Invalid && token.type != Lexer::Token::Type::EndOfFile) 140 return { token }; 141 141 return fail("Cannot consume token"_str, TryToPeek::No); 142 142 } … … 144 144 auto Parser::peekFurther() -> Expected<Lexer::Token, Error> 145 145 { 146 if (auto token = m_lexer.peekFurther()) {147 return *token;148 }146 auto token = m_lexer.peekFurther(); 147 if (token.type != Lexer::Token::Type::Invalid && token.type != Lexer::Token::Type::EndOfFile) 148 return { token }; 149 149 return fail("Cannot consume two tokens"_str, TryToPeek::No); 150 150 } 151 151 152 bool Parser::peekTypes(const Vector<Lexer::Token::Type>& types) 153 { 154 if (auto token = m_lexer.peek()) 155 return std::find(types.begin(), types.end(), token->type) != types.end(); 156 return false; 152 template <Lexer::Token::Type t, Lexer::Token::Type... ts> 153 struct Types { 154 static bool includes(Lexer::Token::Type type) 155 { 156 return t == type || Types<ts...>::includes(type); 157 } 158 159 static void appendNameTo(StringBuilder& builder) 160 { 161 builder.append(Lexer::Token::typeName(t)); 162 builder.append(", "); 163 Types<ts...>::appendNameTo(builder); 164 } 165 }; 166 template <Lexer::Token::Type t> 167 struct Types<t> { 168 static bool includes(Lexer::Token::Type type) 169 { 170 return t == type; 171 } 172 173 static void appendNameTo(StringBuilder& builder) 174 { 175 builder.append(Lexer::Token::typeName(t)); 176 } 177 }; 178 179 template <Lexer::Token::Type... types> 180 bool Parser::peekTypes() 181 { 182 auto token = m_lexer.peek(); 183 return Types<types...>::includes(token.type); 157 184 } 158 185 159 186 Optional<Lexer::Token> Parser::tryType(Lexer::Token::Type type) 160 187 { 161 if (auto token = m_lexer.peek()) { 162 if (token->type == type) 163 return m_lexer.consumeToken(); 164 } 188 auto token = m_lexer.peek(); 189 if (token.type == type) 190 return { m_lexer.consumeToken() }; 165 191 return WTF::nullopt; 166 192 } 167 193 168 Optional<Lexer::Token> Parser::tryTypes(const Vector<Lexer::Token::Type>& types) 169 { 170 if (auto token = m_lexer.peek()){171 if (std::find(types.begin(), types.end(), token->type) != types.end())172 return m_lexer.consumeToken();173 }194 template <Lexer::Token::Type... types> 195 Optional<Lexer::Token> Parser::tryTypes() 196 { 197 auto token = m_lexer.peek(); 198 if (Types<types...>::includes(token.type)) 199 return { m_lexer.consumeToken() }; 174 200 return WTF::nullopt; 175 201 } … … 177 203 auto Parser::consumeType(Lexer::Token::Type type) -> Expected<Lexer::Token, Error> 178 204 { 179 if (auto token = m_lexer.consumeToken()) { 180 if (token->type == type) 181 return *token; 182 return fail(makeString("Unexpected token (expected ", Lexer::Token::typeName(type), " got ", Lexer::Token::typeName(token->type), ")")); 183 } 184 return fail(makeString("Cannot consume token (expected ", Lexer::Token::typeName(type), ")")); 185 } 186 187 auto Parser::consumeTypes(const Vector<Lexer::Token::Type>& types) -> Expected<Lexer::Token, Error> 205 auto token = m_lexer.consumeToken(); 206 if (token.type == type) 207 return { token }; 208 return fail(makeString("Unexpected token (expected ", Lexer::Token::typeName(type), " got ", Lexer::Token::typeName(token.type), ")")); 209 } 210 211 template <Lexer::Token::Type... types> 212 auto Parser::consumeTypes() -> Expected<Lexer::Token, Error> 188 213 { 189 214 auto buildExpectedString = [&]() -> String { 190 215 StringBuilder builder; 191 216 builder.append("["); 192 for (unsigned i = 0; i < types.size(); ++i) { 193 if (i > 0) 194 builder.append(", "); 195 builder.append(Lexer::Token::typeName(types[i])); 196 } 217 Types<types...>::appendNameTo(builder); 197 218 builder.append("]"); 198 219 return builder.toString(); 199 220 }; 200 221 201 if (auto token = m_lexer.consumeToken()) { 202 if (std::find(types.begin(), types.end(), token->type) != types.end()) 203 return *token; 204 return fail(makeString("Unexpected token (expected one of ", buildExpectedString(), " got ", Lexer::Token::typeName(token->type), ")")); 205 } 206 return fail(makeString("Cannot consume token (expected ", buildExpectedString(), ")")); 222 auto token = m_lexer.consumeToken(); 223 if (Types<types...>::includes(token.type)) 224 return { token }; 225 return fail(makeString("Unexpected token (expected one of ", buildExpectedString(), " got ", Lexer::Token::typeName(token.type), ")")); 207 226 } 208 227 … … 280 299 auto Parser::consumeIntegralLiteral() -> Expected<Variant<int, unsigned>, Error> 281 300 { 282 auto integralLiteralToken = consumeTypes ({ Lexer::Token::Type::IntLiteral, Lexer::Token::Type::UintLiteral });301 auto integralLiteralToken = consumeTypes<Lexer::Token::Type::IntLiteral, Lexer::Token::Type::UintLiteral>(); 283 302 if (!integralLiteralToken) 284 303 return Unexpected<Error>(integralLiteralToken.error()); … … 286 305 switch (integralLiteralToken->type) { 287 306 case Lexer::Token::Type::IntLiteral: { 288 auto result = intLiteralToInt(integralLiteralToken->stringView );307 auto result = intLiteralToInt(integralLiteralToken->stringView(m_lexer)); 289 308 if (result) 290 309 return {{ *result }}; … … 293 312 default: { 294 313 ASSERT(integralLiteralToken->type == Lexer::Token::Type::UintLiteral); 295 auto result = uintLiteralToUint(integralLiteralToken->stringView );314 auto result = uintLiteralToUint(integralLiteralToken->stringView(m_lexer)); 296 315 if (result) 297 316 return {{ *result }}; … … 336 355 auto Parser::parseConstantExpression() -> Expected<AST::ConstantExpression, Error> 337 356 { 338 auto type = consumeTypes ({357 auto type = consumeTypes< 339 358 Lexer::Token::Type::IntLiteral, 340 359 Lexer::Token::Type::UintLiteral, … … 343 362 Lexer::Token::Type::True, 344 363 Lexer::Token::Type::False, 345 Lexer::Token::Type::Identifier, 346 }); 364 Lexer::Token::Type::Identifier>(); 347 365 if (!type) 348 366 return Unexpected<Error>(type.error()); … … 350 368 switch (type->type) { 351 369 case Lexer::Token::Type::IntLiteral: { 352 auto value = intLiteralToInt(type->stringView );370 auto value = intLiteralToInt(type->stringView(m_lexer)); 353 371 if (!value) 354 372 return Unexpected<Error>(value.error()); … … 356 374 } 357 375 case Lexer::Token::Type::UintLiteral: { 358 auto value = uintLiteralToUint(type->stringView );376 auto value = uintLiteralToUint(type->stringView(m_lexer)); 359 377 if (!value) 360 378 return Unexpected<Error>(value.error()); … … 362 380 } 363 381 case Lexer::Token::Type::FloatLiteral: { 364 auto value = floatLiteralToFloat(type->stringView );382 auto value = floatLiteralToFloat(type->stringView(m_lexer)); 365 383 if (!value) 366 384 return Unexpected<Error>(value.error()); … … 377 395 CONSUME_TYPE(origin, FullStop); 378 396 CONSUME_TYPE(next, Identifier); 379 return { AST::EnumerationMemberLiteral(WTFMove(*origin), type->stringView .toString(), next->stringView.toString()) };397 return { AST::EnumerationMemberLiteral(WTFMove(*origin), type->stringView(m_lexer).toString(), next->stringView(m_lexer).toString()) }; 380 398 } 381 399 } … … 391 409 } 392 410 CONSUME_TYPE(result, Identifier); 393 return AST::TypeArgument(makeUniqueRef<AST::TypeReference>(Lexer::Token(*result), result->stringView .toString(), AST::TypeArguments()));411 return AST::TypeArgument(makeUniqueRef<AST::TypeReference>(Lexer::Token(*result), result->stringView(m_lexer).toString(), AST::TypeArguments())); 394 412 } 395 413 … … 423 441 auto Parser::parseTypeSuffixAbbreviated() -> Expected<TypeSuffixAbbreviated, Error> 424 442 { 425 auto token = consumeTypes({ Lexer::Token::Type::Star, Lexer::Token::Type::SquareBracketPair, Lexer::Token::Type::LeftSquareBracket }); 443 auto token = consumeTypes< 444 Lexer::Token::Type::Star, 445 Lexer::Token::Type::SquareBracketPair, 446 Lexer::Token::Type::LeftSquareBracket>(); 426 447 if (!token) 427 448 return Unexpected<Error>(token.error()); … … 438 459 auto Parser::parseTypeSuffixNonAbbreviated() -> Expected<TypeSuffixNonAbbreviated, Error> 439 460 { 440 auto token = consumeTypes({ Lexer::Token::Type::Star, Lexer::Token::Type::SquareBracketPair, Lexer::Token::Type::LeftSquareBracket }); 461 auto token = consumeTypes< 462 Lexer::Token::Type::Star, 463 Lexer::Token::Type::SquareBracketPair, 464 Lexer::Token::Type::LeftSquareBracket>(); 441 465 if (!token) 442 466 return Unexpected<Error>(token.error()); … … 448 472 return {{ *token, WTF::nullopt, *numElements }}; 449 473 } 450 auto addressSpaceToken = consumeTypes({ Lexer::Token::Type::Constant, Lexer::Token::Type::Device, Lexer::Token::Type::Threadgroup, Lexer::Token::Type::Thread}); 474 auto addressSpaceToken = consumeTypes< 475 Lexer::Token::Type::Constant, 476 Lexer::Token::Type::Device, 477 Lexer::Token::Type::Threadgroup, 478 Lexer::Token::Type::Thread>(); 451 479 if (!addressSpaceToken) 452 480 return Unexpected<Error>(addressSpaceToken.error()); … … 472 500 auto Parser::parseType() -> Expected<UniqueRef<AST::UnnamedType>, Error> 473 501 { 474 auto addressSpaceToken = tryTypes({ Lexer::Token::Type::Constant, Lexer::Token::Type::Device, Lexer::Token::Type::Threadgroup, Lexer::Token::Type::Thread}); 502 auto addressSpaceToken = tryTypes< 503 Lexer::Token::Type::Constant, 504 Lexer::Token::Type::Device, 505 Lexer::Token::Type::Threadgroup, 506 Lexer::Token::Type::Thread>(); 475 507 476 508 CONSUME_TYPE(name, Identifier); … … 506 538 }; 507 539 PARSE(firstTypeSuffixAbbreviated, TypeSuffixAbbreviated); 508 UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*addressSpaceToken), name->stringView .toString(), WTFMove(*typeArguments));540 UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*addressSpaceToken), name->stringView(m_lexer).toString(), WTFMove(*typeArguments)); 509 541 auto next = constructTypeFromSuffixAbbreviated(*firstTypeSuffixAbbreviated, WTFMove(result)); 510 542 result = WTFMove(next); … … 535 567 } 536 568 }; 537 UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*name), name->stringView .toString(), WTFMove(*typeArguments));569 UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*name), name->stringView(m_lexer).toString(), WTFMove(*typeArguments)); 538 570 while (true) { 539 571 PEEK(nextToken); … … 558 590 PARSE(type, Type); 559 591 CONSUME_TYPE(semicolon, Semicolon); 560 return AST::TypeDefinition(WTFMove(*origin), name->stringView .toString(), WTFMove(*type));592 return AST::TypeDefinition(WTFMove(*origin), name->stringView(m_lexer).toString(), WTFMove(*type)); 561 593 } 562 594 563 595 auto Parser::parseBuiltInSemantic() -> Expected<AST::BuiltInSemantic, Error> 564 596 { 565 auto origin = consumeTypes ({597 auto origin = consumeTypes< 566 598 Lexer::Token::Type::SVInstanceID, 567 599 Lexer::Token::Type::SVVertexID, … … 577 609 Lexer::Token::Type::SVGroupID, 578 610 Lexer::Token::Type::SVGroupIndex, 579 Lexer::Token::Type::SVGroupThreadID });611 Lexer::Token::Type::SVGroupThreadID>(); 580 612 if (!origin) 581 613 return Unexpected<Error>(origin.error()); … … 624 656 625 657 CONSUME_TYPE(info, Identifier); 626 if (info->stringView.length() < 2 || (info->stringView[0] != 'u' 627 && info->stringView[0] != 't' 628 && info->stringView[0] != 'b' 629 && info->stringView[0] != 's')) 630 return Unexpected<Error>(Error(makeString(info->stringView.substring(0, 1), " is not a known resource type ('u', 't', 'b', or 's')"))); 658 auto infoStringView = info->stringView(m_lexer); 659 if (infoStringView.length() < 2 || (infoStringView[0] != 'u' 660 && infoStringView[0] != 't' 661 && infoStringView[0] != 'b' 662 && infoStringView[0] != 's')) 663 return Unexpected<Error>(Error(makeString(infoStringView.substring(0, 1), " is not a known resource type ('u', 't', 'b', or 's')"))); 631 664 632 665 AST::ResourceSemantic::Mode mode; 633 switch (info ->stringView[0]) {666 switch (infoStringView[0]) { 634 667 case 'u': 635 668 mode = AST::ResourceSemantic::Mode::UnorderedAccessView; … … 646 679 } 647 680 648 auto index = recognizeSimpleUnsignedInteger(info ->stringView.substring(1));681 auto index = recognizeSimpleUnsignedInteger(infoStringView.substring(1)); 649 682 if (!index) 650 683 return Unexpected<Error>(index.error()); … … 653 686 if (tryType(Lexer::Token::Type::Comma)) { 654 687 CONSUME_TYPE(spaceToken, Identifier); 688 auto spaceTokenStringView = spaceToken->stringView(m_lexer); 655 689 auto prefix = "space"_str; 656 if (!spaceToken ->stringView.startsWith(StringView(prefix)))657 return Unexpected<Error>(Error(makeString("Second argument to resource semantic ", spaceToken ->stringView, " needs be of the form 'space0'")));658 if (spaceToken ->stringView.length() <= prefix.length())659 return Unexpected<Error>(Error(makeString("Second argument to resource semantic ", spaceToken ->stringView, " needs be of the form 'space0'")));660 auto spaceValue = recognizeSimpleUnsignedInteger(spaceToken ->stringView.substring(prefix.length()));690 if (!spaceTokenStringView.startsWith(StringView(prefix))) 691 return Unexpected<Error>(Error(makeString("Second argument to resource semantic ", spaceTokenStringView, " needs be of the form 'space0'"))); 692 if (spaceTokenStringView.length() <= prefix.length()) 693 return Unexpected<Error>(Error(makeString("Second argument to resource semantic ", spaceTokenStringView, " needs be of the form 'space0'"))); 694 auto spaceValue = recognizeSimpleUnsignedInteger(spaceTokenStringView.substring(prefix.length())); 661 695 if (!spaceValue) 662 696 return Unexpected<Error>(spaceValue.error()); … … 718 752 AST::Qualifiers qualifiers; 719 753 while (auto next = tryType(Lexer::Token::Type::Qualifier)) { 720 if ("nointerpolation" == next->stringView) 754 auto nextStringView = next->stringView(m_lexer); 755 if ("nointerpolation" == nextStringView) 721 756 qualifiers.append(AST::Qualifier::Nointerpolation); 722 else if ("noperspective" == next ->stringView)757 else if ("noperspective" == nextStringView) 723 758 qualifiers.append(AST::Qualifier::Noperspective); 724 else if ("uniform" == next ->stringView)759 else if ("uniform" == nextStringView) 725 760 qualifiers.append(AST::Qualifier::Uniform); 726 else if ("centroid" == next ->stringView)761 else if ("centroid" == nextStringView) 727 762 qualifiers.append(AST::Qualifier::Centroid); 728 763 else { 729 ASSERT("sample" == next ->stringView);764 ASSERT("sample" == nextStringView); 730 765 qualifiers.append(AST::Qualifier::Sample); 731 766 } … … 745 780 CONSUME_TYPE(semicolon, Semicolon); 746 781 747 return AST::StructureElement(WTFMove(*origin), WTFMove(qualifiers), WTFMove(*type), name->stringView .toString(), WTFMove(*semantic));782 return AST::StructureElement(WTFMove(*origin), WTFMove(qualifiers), WTFMove(*type), name->stringView(m_lexer).toString(), WTFMove(*semantic)); 748 783 } 749 784 … … 760 795 } 761 796 762 return AST::StructureDefinition(WTFMove(*origin), name->stringView .toString(), WTFMove(structureElements));797 return AST::StructureDefinition(WTFMove(*origin), name->stringView(m_lexer).toString(), WTFMove(structureElements)); 763 798 } 764 799 … … 782 817 PARSE(firstEnumerationMember, EnumerationMember); 783 818 784 AST::EnumerationDefinition result(WTFMove(*origin), name->stringView .toString(), WTFMove(*type));819 AST::EnumerationDefinition result(WTFMove(*origin), name->stringView(m_lexer).toString(), WTFMove(*type)); 785 820 auto success = result.add(WTFMove(*firstEnumerationMember)); 786 821 if (!success) … … 802 837 { 803 838 CONSUME_TYPE(identifier, Identifier); 804 auto name = identifier->stringView .toString();839 auto name = identifier->stringView(m_lexer).toString(); 805 840 806 841 if (tryType(Lexer::Token::Type::EqualsSign)) { … … 819 854 CONSUME_TYPE(semicolon, Semicolon); 820 855 821 return AST::NativeTypeDeclaration(WTFMove(*origin), name->stringView .toString(), WTFMove(*typeArguments));856 return AST::NativeTypeDeclaration(WTFMove(*origin), name->stringView(m_lexer).toString(), WTFMove(*typeArguments)); 822 857 } 823 858 … … 874 909 String name; 875 910 if (auto token = tryType(Lexer::Token::Type::Identifier)) 876 name = token->stringView .toString();911 name = token->stringView(m_lexer).toString(); 877 912 878 913 PARSE(semantic, Semantic); … … 921 956 PARSE(semantic, Semantic); 922 957 bool isOperator = false; 923 return AST::FunctionDeclaration(WTFMove(*origin), WTFMove(*attributeBlock), AST::EntryPointType::Compute, WTFMove(*type), name->stringView .toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator);958 return AST::FunctionDeclaration(WTFMove(*origin), WTFMove(*attributeBlock), AST::EntryPointType::Compute, WTFMove(*type), name->stringView(m_lexer).toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator); 924 959 } 925 960 926 961 auto Parser::parseVertexOrFragmentFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error> 927 962 { 928 auto entryPoint = consumeTypes ({ Lexer::Token::Type::Vertex, Lexer::Token::Type::Fragment });963 auto entryPoint = consumeTypes<Lexer::Token::Type::Vertex, Lexer::Token::Type::Fragment>(); 929 964 if (!entryPoint) 930 965 return Unexpected<Error>(entryPoint.error()); … … 937 972 938 973 bool isOperator = false; 939 return AST::FunctionDeclaration(WTFMove(*entryPoint), { }, entryPointType, WTFMove(*type), name->stringView .toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator);974 return AST::FunctionDeclaration(WTFMove(*entryPoint), { }, entryPointType, WTFMove(*type), name->stringView(m_lexer).toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator); 940 975 } 941 976 … … 946 981 PARSE(type, Type); 947 982 948 auto name = consumeTypes ({ Lexer::Token::Type::Identifier, Lexer::Token::Type::OperatorName });983 auto name = consumeTypes<Lexer::Token::Type::Identifier, Lexer::Token::Type::OperatorName>(); 949 984 if (!name) 950 985 return Unexpected<Error>(name.error()); … … 954 989 PARSE(semantic, Semantic); 955 990 956 return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), name->stringView .toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator);991 return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), name->stringView(m_lexer).toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator); 957 992 } 958 993 … … 1004 1039 { 1005 1040 AST::Statements statements; 1006 while (!peekTypes ({Lexer::Token::Type::RightCurlyBracket, Lexer::Token::Type::Case, Lexer::Token::Type::Default})) {1041 while (!peekTypes<Lexer::Token::Type::RightCurlyBracket, Lexer::Token::Type::Case, Lexer::Token::Type::Default>()) { 1007 1042 PARSE(statement, Statement); 1008 1043 statements.append(WTFMove(*statement)); … … 1055 1090 auto Parser::parseSwitchCase() -> Expected<AST::SwitchCase, Error> 1056 1091 { 1057 auto origin = consumeTypes ({ Lexer::Token::Type::Case, Lexer::Token::Type::Default });1092 auto origin = consumeTypes<Lexer::Token::Type::Case, Lexer::Token::Type::Default>(); 1058 1093 if (!origin) 1059 1094 return Unexpected<Error>(origin.error()); … … 1162 1197 } 1163 1198 1164 return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView .toString(), WTFMove(*semantic), WTFMove(initializer));1199 return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView(m_lexer).toString(), WTFMove(*semantic), WTFMove(initializer)); 1165 1200 } 1166 1201 … … 1219 1254 auto breakToken = m_lexer.consumeToken(); 1220 1255 CONSUME_TYPE(semicolon, Semicolon); 1221 auto breakObject = AST::Break(WTFMove( *breakToken));1256 auto breakObject = AST::Break(WTFMove(breakToken)); 1222 1257 return { makeUniqueRef<AST::Break>(WTFMove(breakObject)) }; 1223 1258 } … … 1225 1260 auto continueToken = m_lexer.consumeToken(); 1226 1261 CONSUME_TYPE(semicolon, Semicolon); 1227 auto continueObject = AST::Continue(WTFMove( *continueToken));1262 auto continueObject = AST::Continue(WTFMove(continueToken)); 1228 1263 return { makeUniqueRef<AST::Continue>(WTFMove(continueObject)) }; 1229 1264 } … … 1231 1266 auto fallthroughToken = m_lexer.consumeToken(); 1232 1267 CONSUME_TYPE(semicolon, Semicolon); 1233 auto fallthroughObject = AST::Fallthrough(WTFMove( *fallthroughToken));1268 auto fallthroughObject = AST::Fallthrough(WTFMove(fallthroughToken)); 1234 1269 return { makeUniqueRef<AST::Fallthrough>(WTFMove(fallthroughObject)) }; 1235 1270 } … … 1237 1272 auto trapToken = m_lexer.consumeToken(); 1238 1273 CONSUME_TYPE(semicolon, Semicolon); 1239 auto trapObject = AST::Trap(WTFMove( *trapToken));1274 auto trapObject = AST::Trap(WTFMove(trapToken)); 1240 1275 return { makeUniqueRef<AST::Trap>(WTFMove(trapObject)) }; 1241 1276 } … … 1243 1278 auto returnToken = m_lexer.consumeToken(); 1244 1279 if (auto semicolon = tryType(Lexer::Token::Type::Semicolon)) { 1245 auto returnObject = AST::Return(WTFMove( *returnToken), WTF::nullopt);1280 auto returnObject = AST::Return(WTFMove(returnToken), WTF::nullopt); 1246 1281 return { makeUniqueRef<AST::Return>(WTFMove(returnObject)) }; 1247 1282 } 1248 1283 PARSE(expression, Expression); 1249 1284 CONSUME_TYPE(finalSemicolon, Semicolon); 1250 auto returnObject = AST::Return(WTFMove( *returnToken), { WTFMove(*expression) });1285 auto returnObject = AST::Return(WTFMove(returnToken), { WTFMove(*expression) }); 1251 1286 return { makeUniqueRef<AST::Return>(WTFMove(returnObject)) }; 1252 1287 } … … 1322 1357 PARSE(expression, PossiblePrefix, &isEffectful); 1323 1358 1324 if (!isEffectful || peekTypes ({1359 if (!isEffectful || peekTypes< 1325 1360 Lexer::Token::Type::EqualsSign, 1326 1361 Lexer::Token::Type::PlusEquals, … … 1334 1369 Lexer::Token::Type::RightShiftEquals, 1335 1370 Lexer::Token::Type::LeftShiftEquals 1336 })) {1371 >()) { 1337 1372 return completeAssignment(WTFMove(*origin), WTFMove(*expression)); 1338 1373 } … … 1343 1378 auto Parser::parseLimitedSuffixOperator(UniqueRef<AST::Expression>&& previous) -> SuffixExpression 1344 1379 { 1345 auto type = consumeTypes({ Lexer::Token::Type::FullStop, Lexer::Token::Type::Arrow, Lexer::Token::Type::LeftSquareBracket }); 1380 auto type = consumeTypes< 1381 Lexer::Token::Type::FullStop, 1382 Lexer::Token::Type::Arrow, 1383 Lexer::Token::Type::LeftSquareBracket>(); 1346 1384 if (!type) 1347 1385 return SuffixExpression(WTFMove(previous), false); … … 1352 1390 if (!identifier) 1353 1391 return SuffixExpression(WTFMove(previous), false); 1354 return SuffixExpression(makeUniqueRef<AST::DotExpression>(WTFMove(*type), WTFMove(previous), identifier->stringView .toString()), true);1392 return SuffixExpression(makeUniqueRef<AST::DotExpression>(WTFMove(*type), WTFMove(previous), identifier->stringView(m_lexer).toString()), true); 1355 1393 } 1356 1394 case Lexer::Token::Type::Arrow: { … … 1358 1396 if (!identifier) 1359 1397 return SuffixExpression(WTFMove(previous), false); 1360 return SuffixExpression(makeUniqueRef<AST::DotExpression>(Lexer::Token(*type), makeUniqueRef<AST::DereferenceExpression>(WTFMove(*type), WTFMove(previous)), identifier->stringView .toString()), true);1398 return SuffixExpression(makeUniqueRef<AST::DotExpression>(Lexer::Token(*type), makeUniqueRef<AST::DereferenceExpression>(WTFMove(*type), WTFMove(previous)), identifier->stringView(m_lexer).toString()), true); 1361 1399 } 1362 1400 default: { … … 1374 1412 auto Parser::parseSuffixOperator(UniqueRef<AST::Expression>&& previous) -> SuffixExpression 1375 1413 { 1376 auto suffix = consumeTypes({ Lexer::Token::Type::FullStop, Lexer::Token::Type::Arrow, Lexer::Token::Type::LeftSquareBracket, Lexer::Token::Type::PlusPlus, Lexer::Token::Type::MinusMinus }); 1414 auto suffix = consumeTypes< 1415 Lexer::Token::Type::FullStop, 1416 Lexer::Token::Type::Arrow, 1417 Lexer::Token::Type::LeftSquareBracket, 1418 Lexer::Token::Type::PlusPlus, 1419 Lexer::Token::Type::MinusMinus>(); 1377 1420 if (!suffix) 1378 1421 return SuffixExpression(WTFMove(previous), false); … … 1383 1426 if (!identifier) 1384 1427 return SuffixExpression(WTFMove(previous), false); 1385 return SuffixExpression(makeUniqueRef<AST::DotExpression>(WTFMove(*suffix), WTFMove(previous), identifier->stringView .toString()), true);1428 return SuffixExpression(makeUniqueRef<AST::DotExpression>(WTFMove(*suffix), WTFMove(previous), identifier->stringView(m_lexer).toString()), true); 1386 1429 } 1387 1430 case Lexer::Token::Type::Arrow: { … … 1389 1432 if (!identifier) 1390 1433 return SuffixExpression(WTFMove(previous), false); 1391 return SuffixExpression(makeUniqueRef<AST::DotExpression>(Lexer::Token(*suffix), makeUniqueRef<AST::DereferenceExpression>(WTFMove(*suffix), WTFMove(previous)), identifier->stringView .toString()), true);1434 return SuffixExpression(makeUniqueRef<AST::DotExpression>(Lexer::Token(*suffix), makeUniqueRef<AST::DereferenceExpression>(WTFMove(*suffix), WTFMove(previous)), identifier->stringView(m_lexer).toString()), true); 1392 1435 } 1393 1436 case Lexer::Token::Type::LeftSquareBracket: { … … 1452 1495 auto Parser::completeAssignment(Lexer::Token&& origin, UniqueRef<AST::Expression>&& left) -> Expected<UniqueRef<AST::Expression>, Error> 1453 1496 { 1454 auto assignmentOperator = consumeTypes ({1497 auto assignmentOperator = consumeTypes< 1455 1498 Lexer::Token::Type::EqualsSign, 1456 1499 Lexer::Token::Type::PlusEquals, … … 1463 1506 Lexer::Token::Type::OrEquals, 1464 1507 Lexer::Token::Type::RightShiftEquals, 1465 Lexer::Token::Type::LeftShiftEquals 1466 }); 1508 Lexer::Token::Type::LeftShiftEquals>(); 1467 1509 if (!assignmentOperator) 1468 1510 return Unexpected<Error>(assignmentOperator.error()); … … 1523 1565 PARSE(expression, PossiblePrefix); 1524 1566 1525 if (peekTypes ({Lexer::Token::Type::EqualsSign,1567 if (peekTypes<Lexer::Token::Type::EqualsSign, 1526 1568 Lexer::Token::Type::PlusEquals, 1527 1569 Lexer::Token::Type::MinusEquals, … … 1533 1575 Lexer::Token::Type::OrEquals, 1534 1576 Lexer::Token::Type::RightShiftEquals, 1535 Lexer::Token::Type::LeftShiftEquals })) {1577 Lexer::Token::Type::LeftShiftEquals>()) { 1536 1578 return completeAssignment(WTFMove(*origin), WTFMove(*expression)); 1537 1579 } … … 1557 1599 auto Parser::completePossibleLogicalBinaryOperation(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error> 1558 1600 { 1559 while (auto logicalBinaryOperation = tryTypes ({1601 while (auto logicalBinaryOperation = tryTypes< 1560 1602 Lexer::Token::Type::OrOr, 1561 1603 Lexer::Token::Type::AndAnd, … … 1563 1605 Lexer::Token::Type::Xor, 1564 1606 Lexer::Token::Type::And 1565 })) {1607 >()) { 1566 1608 PARSE(next, PossibleRelationalBinaryOperation); 1567 1609 … … 1609 1651 auto Parser::completePossibleRelationalBinaryOperation(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error> 1610 1652 { 1611 while (auto relationalBinaryOperation = tryTypes ({1653 while (auto relationalBinaryOperation = tryTypes< 1612 1654 Lexer::Token::Type::LessThanSign, 1613 1655 Lexer::Token::Type::GreaterThanSign, … … 1616 1658 Lexer::Token::Type::EqualComparison, 1617 1659 Lexer::Token::Type::NotEqual 1618 })) {1660 >()) { 1619 1661 PARSE(next, PossibleShift); 1620 1662 … … 1664 1706 auto Parser::completePossibleShift(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error> 1665 1707 { 1666 while (auto shift = tryTypes ({1708 while (auto shift = tryTypes< 1667 1709 Lexer::Token::Type::LeftShift, 1668 1710 Lexer::Token::Type::RightShift 1669 })) {1711 >()) { 1670 1712 PARSE(next, PossibleAdd); 1671 1713 … … 1698 1740 auto Parser::completePossibleAdd(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error> 1699 1741 { 1700 while (auto add = tryTypes ({1742 while (auto add = tryTypes< 1701 1743 Lexer::Token::Type::Plus, 1702 1744 Lexer::Token::Type::Minus 1703 })) {1745 >()) { 1704 1746 PARSE(next, PossibleMultiply); 1705 1747 … … 1732 1774 auto Parser::completePossibleMultiply(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error> 1733 1775 { 1734 while (auto multiply = tryTypes ({1776 while (auto multiply = tryTypes< 1735 1777 Lexer::Token::Type::Star, 1736 1778 Lexer::Token::Type::Divide, 1737 1779 Lexer::Token::Type::Mod 1738 })) {1780 >()) { 1739 1781 PARSE(next, PossiblePrefix); 1740 1782 … … 1765 1807 auto Parser::parsePossiblePrefix(bool *isEffectful) -> Expected<UniqueRef<AST::Expression>, Error> 1766 1808 { 1767 if (auto prefix = tryTypes ({1809 if (auto prefix = tryTypes< 1768 1810 Lexer::Token::Type::PlusPlus, 1769 1811 Lexer::Token::Type::MinusMinus, … … 1775 1817 Lexer::Token::Type::At, 1776 1818 Lexer::Token::Type::Star 1777 })) {1819 >()) { 1778 1820 PARSE(next, PossiblePrefix); 1779 1821 … … 1878 1920 { 1879 1921 CONSUME_TYPE(name, Identifier); 1880 auto callName = name->stringView .toString();1922 auto callName = name->stringView(m_lexer).toString(); 1881 1923 1882 1924 CONSUME_TYPE(leftParenthesis, LeftParenthesis); … … 1900 1942 auto Parser::parseTerm() -> Expected<UniqueRef<AST::Expression>, Error> 1901 1943 { 1902 auto type = consumeTypes ({1944 auto type = consumeTypes< 1903 1945 Lexer::Token::Type::IntLiteral, 1904 1946 Lexer::Token::Type::UintLiteral, … … 1908 1950 Lexer::Token::Type::False, 1909 1951 Lexer::Token::Type::Identifier, 1910 Lexer::Token::Type::LeftParenthesis 1911 }); 1952 Lexer::Token::Type::LeftParenthesis>(); 1912 1953 if (!type) 1913 1954 return Unexpected<Error>(type.error()); … … 1915 1956 switch (type->type) { 1916 1957 case Lexer::Token::Type::IntLiteral: { 1917 auto value = intLiteralToInt(type->stringView );1958 auto value = intLiteralToInt(type->stringView(m_lexer)); 1918 1959 if (!value) 1919 1960 return Unexpected<Error>(value.error()); … … 1921 1962 } 1922 1963 case Lexer::Token::Type::UintLiteral: { 1923 auto value = uintLiteralToUint(type->stringView );1964 auto value = uintLiteralToUint(type->stringView(m_lexer)); 1924 1965 if (!value) 1925 1966 return Unexpected<Error>(value.error()); … … 1927 1968 } 1928 1969 case Lexer::Token::Type::FloatLiteral: { 1929 auto value = floatLiteralToFloat(type->stringView );1970 auto value = floatLiteralToFloat(type->stringView(m_lexer)); 1930 1971 if (!value) 1931 1972 return Unexpected<Error>(value.error()); … … 1939 1980 return { makeUniqueRef<AST::BooleanLiteral>(WTFMove(*type), false) }; 1940 1981 case Lexer::Token::Type::Identifier: { 1941 auto name = type->stringView .toString();1982 auto name = type->stringView(m_lexer).toString(); 1942 1983 return { makeUniqueRef<AST::VariableReference>(WTFMove(*type), WTFMove(name)) }; 1943 1984 } -
trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h
r247124 r247171 144 144 Expected<Lexer::Token, Error> peek(); 145 145 Expected<Lexer::Token, Error> peekFurther(); 146 bool peekTypes(const Vector<Lexer::Token::Type>&); 146 template <Lexer::Token::Type... types> 147 bool peekTypes(); 147 148 Optional<Lexer::Token> tryType(Lexer::Token::Type); 148 Optional<Lexer::Token> tryTypes(const Vector<Lexer::Token::Type>&); 149 template <Lexer::Token::Type... types> 150 Optional<Lexer::Token> tryTypes(); 149 151 Expected<Lexer::Token, Error> consumeType(Lexer::Token::Type); 150 Expected<Lexer::Token, Error> consumeTypes(const Vector<Lexer::Token::Type>&); 152 template <Lexer::Token::Type... types> 153 Expected<Lexer::Token, Error> consumeTypes(); 151 154 152 155 Expected<Variant<int, unsigned>, Error> consumeIntegralLiteral(); -
trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPreserveVariableLifetimes.cpp
r247164 r247171 94 94 static ALWAYS_INLINE Lexer::Token anonymousToken(Lexer::Token::Type type) 95 95 { 96 return Lexer::Token { { }, 0, type };96 return Lexer::Token { 0, 0, type }; 97 97 } 98 98
Note: See TracChangeset
for help on using the changeset viewer.