WebKit Bugzilla
Attachment 371228 Details for
Bug 192890
: [WHLSL] Parsing and lexing the standard library is slow
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for landing
patch192890 (text/plain), 122.24 KB, created by
Robin Morisset
on 2019-06-03 16:42:48 PDT
(
hide
)
Description:
Patch for landing
Filename:
MIME Type:
Creator:
Robin Morisset
Created:
2019-06-03 16:42:48 PDT
Size:
122.24 KB
patch
obsolete
>diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 039281ee253..a01f2a73b2d 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,116 @@ >+2019-06-03 Robin Morisset <rmorisset@apple.com> >+ >+ [WHLSL] Parsing and lexing the standard library is slow >+ https://bugs.webkit.org/show_bug.cgi?id=192890 >+ <rdar://problem/50746335> >+ >+ Reviewed by Myles Maxfield. >+ >+ The main idea is to avoid backtracking by instead peeking at the next token (and occasionally at the one after that). >+ This implies a few things: >+ - We can replace the stack of tokens by a trivial ring buffer of size 2 (holding the next token and the one after, or WTF::nullopt if we are at the end of the file). >+ - We now have "completeFooExpression" functions, to avoid having to reparse the prefix of some expression, if we find half-way through what it is. >+ >+ I also fixed the following parser bug: >+ - https://bugs.webkit.org/show_bug.cgi?id=198305 [WHLSL] Multiple variables with initializers in a declaration statement crashes the compiler >+ which was due to a mistake I made in the grammar >+ >+ Finally I added two new macros: CONSUME_TYPE and PARSE to eliminate about 500 lines of error propagation boilerplate. >+ >+ There are still lots of ways of improving the parser and lexer, such as: >+ - finishing the conversion of tokens in the lexer, not bothering with allocating string views >+ - make two special tokens Invalid and EOF, to remove the overhead of Optional >+ - make peekTypes and consumeTypes use templates to avoid constructing a Vector and calling find on it. >+ - Turn the entire lexer into a proper automata, not going through the same characters again and again (this is certainly the largest win by far) >+ - Remove the last few pieces of backtracking from the parser. >+ >+ The current patch is already enough to make parsing the full standard library (something like 85k lines) approximately 260ms. >+ This is still longer than I would like, but nowhere near the bottleneck any longer because of some other parts of the compiler. >+ >+ * Modules/webgpu/WHLSL/WHLSLLexer.h: >+ (WebCore::WHLSL::Lexer::Lexer): >+ (WebCore::WHLSL::Lexer::consumeToken): >+ (WebCore::WHLSL::Lexer::peek): >+ (WebCore::WHLSL::Lexer::peekFurther): >+ (WebCore::WHLSL::Lexer::state const): >+ (WebCore::WHLSL::Lexer::setState): >+ (WebCore::WHLSL::Lexer::unconsumeToken): Deleted. >+ * Modules/webgpu/WHLSL/WHLSLParser.cpp: >+ (WebCore::WHLSL::Parser::parse): >+ (WebCore::WHLSL::Parser::peek): >+ (WebCore::WHLSL::Parser::peekTypes): >+ (WebCore::WHLSL::Parser::tryType): >+ (WebCore::WHLSL::Parser::tryTypes): >+ (WebCore::WHLSL::Parser::consumeTypes): >+ (WebCore::WHLSL::Parser::parseConstantExpression): >+ (WebCore::WHLSL::Parser::parseTypeArgument): >+ (WebCore::WHLSL::Parser::parseTypeArguments): >+ (WebCore::WHLSL::Parser::parseTypeSuffixAbbreviated): >+ (WebCore::WHLSL::Parser::parseTypeSuffixNonAbbreviated): >+ (WebCore::WHLSL::Parser::parseType): >+ (WebCore::WHLSL::Parser::parseTypeDefinition): >+ (WebCore::WHLSL::Parser::parseResourceSemantic): >+ (WebCore::WHLSL::Parser::parseSpecializationConstantSemantic): >+ (WebCore::WHLSL::Parser::parseStageInOutSemantic): >+ (WebCore::WHLSL::Parser::parseSemantic): >+ (WebCore::WHLSL::Parser::parseQualifiers): >+ (WebCore::WHLSL::Parser::parseStructureElement): >+ (WebCore::WHLSL::Parser::parseStructureDefinition): >+ (WebCore::WHLSL::Parser::parseEnumerationDefinition): >+ (WebCore::WHLSL::Parser::parseEnumerationMember): >+ (WebCore::WHLSL::Parser::parseNativeTypeDeclaration): >+ (WebCore::WHLSL::Parser::parseNumThreadsFunctionAttribute): >+ (WebCore::WHLSL::Parser::parseAttributeBlock): >+ (WebCore::WHLSL::Parser::parseParameter): >+ (WebCore::WHLSL::Parser::parseParameters): >+ (WebCore::WHLSL::Parser::parseFunctionDefinition): >+ (WebCore::WHLSL::Parser::parseComputeFunctionDeclaration): >+ (WebCore::WHLSL::Parser::parseVertexFragmentFunctionDeclaration): >+ (WebCore::WHLSL::Parser::parseRegularFunctionDeclaration): >+ (WebCore::WHLSL::Parser::parseOperatorFunctionDeclaration): >+ (WebCore::WHLSL::Parser::parseFunctionDeclaration): >+ (WebCore::WHLSL::Parser::parseNativeFunctionDeclaration): >+ (WebCore::WHLSL::Parser::parseBlock): >+ (WebCore::WHLSL::Parser::parseBlockBody): >+ (WebCore::WHLSL::Parser::parseIfStatement): >+ (WebCore::WHLSL::Parser::parseSwitchStatement): >+ (WebCore::WHLSL::Parser::parseSwitchCase): >+ (WebCore::WHLSL::Parser::parseForLoop): >+ (WebCore::WHLSL::Parser::parseWhileLoop): >+ (WebCore::WHLSL::Parser::parseDoWhileLoop): >+ (WebCore::WHLSL::Parser::parseVariableDeclaration): >+ (WebCore::WHLSL::Parser::parseVariableDeclarations): >+ (WebCore::WHLSL::Parser::parseStatement): >+ (WebCore::WHLSL::Parser::parseEffectfulExpression): >+ (WebCore::WHLSL::Parser::parseEffectfulAssignment): >+ (WebCore::WHLSL::Parser::parseExpression): >+ (WebCore::WHLSL::Parser::parseTernaryConditional): >+ (WebCore::WHLSL::Parser::completeTernaryConditional): >+ (WebCore::WHLSL::Parser::parseAssignment): >+ (WebCore::WHLSL::Parser::completeAssignment): >+ (WebCore::WHLSL::Parser::parsePossibleTernaryConditional): >+ (WebCore::WHLSL::Parser::parsePossibleLogicalBinaryOperation): >+ (WebCore::WHLSL::Parser::completePossibleLogicalBinaryOperation): >+ (WebCore::WHLSL::Parser::parsePossibleRelationalBinaryOperation): >+ (WebCore::WHLSL::Parser::completePossibleRelationalBinaryOperation): >+ (WebCore::WHLSL::Parser::parsePossibleShift): >+ (WebCore::WHLSL::Parser::completePossibleShift): >+ (WebCore::WHLSL::Parser::parsePossibleAdd): >+ (WebCore::WHLSL::Parser::completePossibleAdd): >+ (WebCore::WHLSL::Parser::parsePossibleMultiply): >+ (WebCore::WHLSL::Parser::completePossibleMultiply): >+ (WebCore::WHLSL::Parser::parsePossiblePrefix): >+ (WebCore::WHLSL::Parser::parsePossibleSuffix): >+ (WebCore::WHLSL::Parser::parseCallExpression): >+ (WebCore::WHLSL::Parser::parseTerm): >+ (WebCore::WHLSL::Parser::parseAddressSpaceType): Deleted. >+ (WebCore::WHLSL::Parser::parseNonAddressSpaceType): Deleted. >+ (WebCore::WHLSL::Parser::parseEntryPointFunctionDeclaration): Deleted. >+ (WebCore::WHLSL::Parser::parseEffectfulPrefix): Deleted. >+ (WebCore::WHLSL::Parser::parseEffectfulSuffix): Deleted. >+ * Modules/webgpu/WHLSL/WHLSLParser.h: >+ (WebCore::WHLSL::Parser::Error::dump const): >+ > 2019-06-03 Youenn Fablet <youenn@apple.com> > > Allow resizing of camera video feeds to very small resolutions >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLLexer.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLLexer.h >index b08b477bc81..bbde9fe4f8b 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLLexer.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLLexer.h >@@ -46,6 +46,8 @@ public: > : m_stringView(stringView) > { > skipWhitespaceAndComments(); >+ m_ringBuffer[0] = consumeTokenFromStream(); >+ m_ringBuffer[1] = consumeTokenFromStream(); > } > > Lexer(const Lexer&) = delete; >@@ -177,37 +179,57 @@ public: > > Optional<Token> consumeToken() > { >- if (!m_stack.isEmpty()) >- return m_stack.takeLast(); >- return consumeTokenFromStream(); >+ auto result = m_ringBuffer[m_ringBufferIndex]; >+ m_ringBuffer[m_ringBufferIndex] = consumeTokenFromStream(); >+ m_ringBufferIndex = (m_ringBufferIndex + 1) % 2; >+ return result; > } > >- void unconsumeToken(Token&& token) >+ Optional<Token> peek() > { >- m_stack.append(WTFMove(token)); >+ return m_ringBuffer[m_ringBufferIndex]; > } > >+ Optional<Token> peekFurther() >+ { >+ return m_ringBuffer[(m_ringBufferIndex + 1) % 2]; >+ } >+ >+ // FIXME: We should not need this >+ // https://bugs.webkit.org/show_bug.cgi?id=198357 > struct State { >- Vector<Token> stack; >+ Optional<Token> ringBuffer[2]; >+ unsigned ringBufferIndex; > unsigned offset; > unsigned lineNumber; > }; > > State state() const > { >- return { m_stack, m_offset, m_lineNumber }; >+ State state; >+ state.ringBuffer[0] = m_ringBuffer[0]; >+ state.ringBuffer[1] = m_ringBuffer[1]; >+ state.ringBufferIndex = m_ringBufferIndex; >+ state.offset = m_offset; >+ state.lineNumber = m_lineNumber; >+ return state; > } > > void setState(const State& state) > { >- m_stack = state.stack; >+ m_ringBuffer[0] = state.ringBuffer[0]; >+ m_ringBuffer[1] = state.ringBuffer[1]; >+ m_ringBufferIndex = state.ringBufferIndex; > m_offset = state.offset; > m_lineNumber = state.lineNumber; >+ > } > > void setState(State&& state) > { >- m_stack = WTFMove(state.stack); >+ m_ringBuffer[0] = WTFMove(state.ringBuffer[0]); >+ m_ringBuffer[1] = WTFMove(state.ringBuffer[1]); >+ m_ringBufferIndex = WTFMove(state.ringBufferIndex); > m_offset = WTFMove(state.offset); > m_lineNumber = WTFMove(state.lineNumber); > } >@@ -253,7 +275,8 @@ private: > Optional<unsigned> operatorName(unsigned) const; > > StringView m_stringView; >- Vector<Token> m_stack; >+ Optional<Token> m_ringBuffer[2]; >+ unsigned m_ringBufferIndex { 0 }; > unsigned m_offset { 0 }; > unsigned m_lineNumber { 0 }; > }; >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp >index 94752382fbe..f19aeca2c40 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp >@@ -38,6 +38,26 @@ namespace WebCore { > > namespace WHLSL { > >+#define PARSE(name, element, ...) \ >+ auto name = parse##element(__VA_ARGS__); \ >+ if (!name) \ >+ return Unexpected<Error>(name.error()); >+ >+#define CONSUME_TYPE(name, type) \ >+ auto name = consumeType(Lexer::Token::Type::type); \ >+ if (!name) \ >+ return Unexpected<Error>(name.error()); >+ >+#define PEEK(name) \ >+ auto name = peek(); \ >+ if (!name) \ >+ return Unexpected<Error>(name.error()); >+ >+#define PEEK_FURTHER(name) \ >+ auto name = peekFurther(); \ >+ if (!name) \ >+ return Unexpected<Error>(name.error()); >+ > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195682 Return a better error code from this, and report it to JavaScript. > auto Parser::parse(Program& program, StringView stringView, Mode mode) -> Optional<Error> > { >@@ -45,87 +65,62 @@ auto Parser::parse(Program& program, StringView stringView, Mode mode) -> Option > m_mode = mode; > > while (!m_lexer.isFullyConsumed()) { >- if (tryType(Lexer::Token::Type::Semicolon)) { >+ auto token = m_lexer.peek(); >+ if (!token) >+ break; >+ switch (token->type) { >+ case Lexer::Token::Type::Semicolon: > m_lexer.consumeToken(); > continue; >+ case Lexer::Token::Type::Typedef: { >+ auto typeDefinition = parseTypeDefinition(); >+ if (!typeDefinition) >+ return typeDefinition.error(); >+ program.append(WTFMove(*typeDefinition)); >+ continue; > } >- >- { >- auto typeDefinition = backtrackingScope<Expected<AST::TypeDefinition, Error>>([&]() { >- return parseTypeDefinition(); >- }); >- if (typeDefinition) { >- auto success = program.append(WTFMove(*typeDefinition)); >- if (!success) >- return WTF::nullopt; >- continue; >- } >- } >- >- { >- auto structureDefinition = backtrackingScope<Expected<AST::StructureDefinition, Error>>([&]() { >- return parseStructureDefinition(); >- }); >- if (structureDefinition) { >- auto success = program.append(WTFMove(*structureDefinition)); >- if (!success) >- return WTF::nullopt; >- continue; >- } >+ case Lexer::Token::Type::Struct: { >+ auto structureDefinition = parseStructureDefinition(); >+ if (!structureDefinition) >+ return structureDefinition.error(); >+ program.append(WTFMove(*structureDefinition)); >+ continue; > } >- >- { >- auto enumerationDefinition = backtrackingScope<Expected<AST::EnumerationDefinition, Error>>([&]() { >- return parseEnumerationDefinition(); >- }); >- if (enumerationDefinition) { >- auto success = program.append(WTFMove(*enumerationDefinition)); >- if (!success) >- return WTF::nullopt; >- continue; >- } >+ case Lexer::Token::Type::Enum: { >+ auto enumerationDefinition = parseEnumerationDefinition(); >+ if (!enumerationDefinition) >+ return enumerationDefinition.error(); >+ program.append(WTFMove(*enumerationDefinition)); >+ continue; > } >- >- Optional<Error> error; >- { >- auto functionDefinition = backtrackingScope<Expected<AST::FunctionDefinition, Error>>([&]() { >- return parseFunctionDefinition(); >- }); >- if (functionDefinition) { >- auto success = program.append(WTFMove(*functionDefinition)); >- if (!success) >- return WTF::nullopt; >+ case Lexer::Token::Type::Native: { >+ ASSERT(m_mode == Mode::StandardLibrary); >+ auto furtherToken = peekFurther(); >+ if (!furtherToken) >+ return WTF::nullopt; >+ if (furtherToken->type == Lexer::Token::Type::Typedef) { >+ auto nativeTypeDeclaration = parseNativeTypeDeclaration(); >+ if (!nativeTypeDeclaration) >+ return nativeTypeDeclaration.error(); >+ program.append(WTFMove(*nativeTypeDeclaration)); > continue; > } >- error = functionDefinition.error(); >+ auto nativeFunctionDeclaration = parseNativeFunctionDeclaration(); >+ if (!nativeFunctionDeclaration) >+ return nativeFunctionDeclaration.error(); >+ program.append(WTFMove(*nativeFunctionDeclaration)); >+ continue; > } >- >- if (m_mode == Mode::StandardLibrary) { >- auto nativeFunctionDeclaration = backtrackingScope<Expected<AST::NativeFunctionDeclaration, Error>>([&]() { >- return parseNativeFunctionDeclaration(); >- }); >- if (nativeFunctionDeclaration) { >- auto success = program.append(WTFMove(*nativeFunctionDeclaration)); >- if (!success) >- return WTF::nullopt; >- continue; >- } >+ default: { >+ auto functionDefinition = parseFunctionDefinition(); >+ if (!functionDefinition) >+ return functionDefinition.error(); >+ program.append(WTFMove(*functionDefinition)); >+ continue; > } >- >- if (m_mode == Mode::StandardLibrary) { >- auto nativeTypeDeclaration = backtrackingScope<Expected<AST::NativeTypeDeclaration, Error>>([&]() { >- return parseNativeTypeDeclaration(); >- }); >- if (nativeTypeDeclaration) { >- auto success = program.append(WTFMove(*nativeTypeDeclaration)); >- if (!success) >- return WTF::nullopt; >- continue; >- } > } >- >- return WTFMove(*error); > } >+ > return WTF::nullopt; > } > >@@ -140,29 +135,41 @@ auto Parser::fail(const String& message, TryToPeek tryToPeek) -> Unexpected<Erro > > auto Parser::peek() -> Expected<Lexer::Token, Error> > { >- if (auto token = m_lexer.consumeToken()) { >- m_lexer.unconsumeToken(Lexer::Token(*token)); >+ if (auto token = m_lexer.peek()) { > return *token; > } > return fail("Cannot consume token"_str, TryToPeek::No); > } > >+auto Parser::peekFurther() -> Expected<Lexer::Token, Error> >+{ >+ if (auto token = m_lexer.peekFurther()) { >+ return *token; >+ } >+ return fail("Cannot consume two tokens"_str, TryToPeek::No); >+} >+ >+bool Parser::peekTypes(const Vector<Lexer::Token::Type>& types) >+{ >+ if (auto token = m_lexer.peek()) >+ return std::find(types.begin(), types.end(), token->type) != types.end(); >+ return false; >+} >+ > Optional<Lexer::Token> Parser::tryType(Lexer::Token::Type type) > { >- if (auto token = m_lexer.consumeToken()) { >+ if (auto token = m_lexer.peek()) { > if (token->type == type) >- return token; >- m_lexer.unconsumeToken(Lexer::Token(*token)); >+ return m_lexer.consumeToken(); > } > return WTF::nullopt; > } > >-Optional<Lexer::Token> Parser::tryTypes(Vector<Lexer::Token::Type> types) >+Optional<Lexer::Token> Parser::tryTypes(const Vector<Lexer::Token::Type>& types) > { >- if (auto token = m_lexer.consumeToken()) { >+ if (auto token = m_lexer.peek()) { > if (std::find(types.begin(), types.end(), token->type) != types.end()) >- return token; >- m_lexer.unconsumeToken(Lexer::Token(*token)); >+ return m_lexer.consumeToken(); > } > return WTF::nullopt; > } >@@ -177,7 +184,7 @@ auto Parser::consumeType(Lexer::Token::Type type) -> Expected<Lexer::Token, Erro > return fail(makeString("Cannot consume token (expected ", Lexer::Token::typeName(type), ")")); > } > >-auto Parser::consumeTypes(Vector<Lexer::Token::Type> types) -> Expected<Lexer::Token, Error> >+auto Parser::consumeTypes(const Vector<Lexer::Token::Type>& types) -> Expected<Lexer::Token, Error> > { > auto buildExpectedString = [&]() -> String { > StringBuilder builder; >@@ -367,12 +374,8 @@ auto Parser::parseConstantExpression() -> Expected<AST::ConstantExpression, Erro > return { AST::BooleanLiteral(WTFMove(*type), false) }; > default: { > ASSERT(type->type == Lexer::Token::Type::Identifier); >- auto origin = consumeType(Lexer::Token::Type::FullStop); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- auto next = consumeType(Lexer::Token::Type::Identifier); >- if (!next) >- return Unexpected<Error>(next.error()); >+ CONSUME_TYPE(origin, FullStop); >+ CONSUME_TYPE(next, Identifier); > return { AST::EnumerationMemberLiteral(WTFMove(*origin), type->stringView.toString(), next->stringView.toString()) }; > } > } >@@ -380,55 +383,41 @@ auto Parser::parseConstantExpression() -> Expected<AST::ConstantExpression, Erro > > auto Parser::parseTypeArgument() -> Expected<AST::TypeArgument, Error> > { >- auto constantExpression = backtrackingScope<Expected<AST::ConstantExpression, Error>>([&]() { >- return parseConstantExpression(); >- }); >- if (constantExpression) >+ PEEK(nextToken); >+ PEEK_FURTHER(furtherToken); >+ if (nextToken->type != Lexer::Token::Type::Identifier || furtherToken->type == Lexer::Token::Type::FullStop) { >+ PARSE(constantExpression, ConstantExpression); > return AST::TypeArgument(WTFMove(*constantExpression)); >- auto result = consumeType(Lexer::Token::Type::Identifier); >- if (!result) >- return Unexpected<Error>(result.error()); >+ } >+ CONSUME_TYPE(result, Identifier); > return AST::TypeArgument(makeUniqueRef<AST::TypeReference>(Lexer::Token(*result), result->stringView.toString(), AST::TypeArguments())); > } > > auto Parser::parseTypeArguments() -> Expected<AST::TypeArguments, Error> > { >- auto typeArguments = backtrackingScope<Optional<AST::TypeArguments>>([&]() -> Optional<AST::TypeArguments> { >- auto lessThanSign = consumeType(Lexer::Token::Type::LessThanSign); >- if (!lessThanSign) >- return WTF::nullopt; >- AST::TypeArguments typeArguments; >- auto typeArgument = parseTypeArgument(); >- if (!typeArgument) >- return WTF::nullopt; >- typeArguments.append(WTFMove(*typeArgument)); >- while (tryType(Lexer::Token::Type::Comma)) { >- auto typeArgument = parseTypeArgument(); >- if (!typeArgument) >- return WTF::nullopt; >- typeArguments.append(WTFMove(*typeArgument)); >- } >- auto greaterThanSign = consumeType(Lexer::Token::Type::GreaterThanSign); >- if (!greaterThanSign) >- return WTF::nullopt; >+ AST::TypeArguments typeArguments; >+ auto lessThanSign = tryType(Lexer::Token::Type::LessThanSign); >+ if (!lessThanSign) > return typeArguments; >- }); >- if (typeArguments) >- return WTFMove(*typeArguments); > >- typeArguments = backtrackingScope<Optional<AST::TypeArguments>>([&]() -> Optional<AST::TypeArguments> { >- auto lessThanSign = consumeType(Lexer::Token::Type::LessThanSign); >- if (!lessThanSign) >- return WTF::nullopt; >- auto greaterThanSign = consumeType(Lexer::Token::Type::GreaterThanSign); >- if (!greaterThanSign) >- return WTF::nullopt; >- return {{ }}; >- }); >- if (typeArguments) >- return WTFMove(*typeArguments); >+ auto greaterThanSign = tryType(Lexer::Token::Type::GreaterThanSign); >+ if (greaterThanSign) >+ return typeArguments; >+ >+ PARSE(typeArgument, TypeArgument); >+ typeArguments.append(WTFMove(*typeArgument)); >+ >+ while (true) { >+ auto greaterThanSign = tryType(Lexer::Token::Type::GreaterThanSign); >+ if (greaterThanSign) >+ break; > >- return AST::TypeArguments(); >+ CONSUME_TYPE(comma, Comma); >+ PARSE(typeArgument, TypeArgument); >+ typeArguments.append(WTFMove(*typeArgument)); >+ } >+ >+ return typeArguments; > } > > auto Parser::parseTypeSuffixAbbreviated() -> Expected<TypeSuffixAbbreviated, Error> >@@ -440,9 +429,7 @@ auto Parser::parseTypeSuffixAbbreviated() -> Expected<TypeSuffixAbbreviated, Err > auto numElements = consumeNonNegativeIntegralLiteral(); > if (!numElements) > return Unexpected<Error>(numElements.error()); >- auto rightSquareBracket = consumeType(Lexer::Token::Type::RightSquareBracket); >- if (!rightSquareBracket) >- return Unexpected<Error>(rightSquareBracket.error()); >+ CONSUME_TYPE(rightSquareBracket, RightSquareBracket); > return {{ *token, *numElements }}; > } > return {{ *token, WTF::nullopt }}; >@@ -457,9 +444,7 @@ auto Parser::parseTypeSuffixNonAbbreviated() -> Expected<TypeSuffixNonAbbreviate > auto numElements = consumeNonNegativeIntegralLiteral(); > if (!numElements) > return Unexpected<Error>(numElements.error()); >- auto rightSquareBracket = consumeType(Lexer::Token::Type::RightSquareBracket); >- if (!rightSquareBracket) >- return Unexpected<Error>(rightSquareBracket.error()); >+ CONSUME_TYPE(rightSquareBracket, RightSquareBracket); > return {{ *token, WTF::nullopt, *numElements }}; > } > auto addressSpaceToken = consumeTypes({ Lexer::Token::Type::Constant, Lexer::Token::Type::Device, Lexer::Token::Type::Threadgroup, Lexer::Token::Type::Thread}); >@@ -484,78 +469,60 @@ auto Parser::parseTypeSuffixNonAbbreviated() -> Expected<TypeSuffixNonAbbreviate > return {{ *token, { addressSpace }, WTF::nullopt }}; > } > >-auto Parser::parseAddressSpaceType() -> Expected<UniqueRef<AST::UnnamedType>, Error> >+auto Parser::parseType() -> Expected<UniqueRef<AST::UnnamedType>, Error> > { >- auto addressSpaceToken = consumeTypes({ Lexer::Token::Type::Constant, Lexer::Token::Type::Device, Lexer::Token::Type::Threadgroup, Lexer::Token::Type::Thread}); >- if (!addressSpaceToken) >- return Unexpected<Error>(addressSpaceToken.error()); >- AST::AddressSpace addressSpace; >- switch (addressSpaceToken->type) { >- case Lexer::Token::Type::Constant: >- addressSpace = AST::AddressSpace::Constant; >- break; >- case Lexer::Token::Type::Device: >- addressSpace = AST::AddressSpace::Device; >- break; >- case Lexer::Token::Type::Threadgroup: >- addressSpace = AST::AddressSpace::Threadgroup; >- break; >- default: >- ASSERT(addressSpaceToken->type == Lexer::Token::Type::Thread); >- addressSpace = AST::AddressSpace::Thread; >- break; >- } >- auto name = consumeType(Lexer::Token::Type::Identifier); >- if (!name) >- return Unexpected<Error>(name.error()); >- auto typeArguments = parseTypeArguments(); >- if (!typeArguments) >- return Unexpected<Error>(typeArguments.error()); >+ auto addressSpaceToken = tryTypes({ Lexer::Token::Type::Constant, Lexer::Token::Type::Device, Lexer::Token::Type::Threadgroup, Lexer::Token::Type::Thread}); > >- auto constructTypeFromSuffixAbbreviated = [&](const TypeSuffixAbbreviated& typeSuffixAbbreviated, UniqueRef<AST::UnnamedType>&& previous) -> UniqueRef<AST::UnnamedType> { >- switch (typeSuffixAbbreviated.token.type) { >- case Lexer::Token::Type::Star: >- return { makeUniqueRef<AST::PointerType>(Lexer::Token(typeSuffixAbbreviated.token), addressSpace, WTFMove(previous)) }; >- case Lexer::Token::Type::SquareBracketPair: >- return { makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(typeSuffixAbbreviated.token), addressSpace, WTFMove(previous)) }; >- default: >- ASSERT(typeSuffixAbbreviated.token.type == Lexer::Token::Type::LeftSquareBracket); >- return { makeUniqueRef<AST::ArrayType>(Lexer::Token(typeSuffixAbbreviated.token), WTFMove(previous), *typeSuffixAbbreviated.numElements) }; >- } >- }; >+ CONSUME_TYPE(name, Identifier); >+ PARSE(typeArguments, TypeArguments); > >- auto firstTypeSuffixAbbreviated = parseTypeSuffixAbbreviated(); >- if (!firstTypeSuffixAbbreviated) >- return Unexpected<Error>(firstTypeSuffixAbbreviated.error()); >- UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*addressSpaceToken), name->stringView.toString(), WTFMove(*typeArguments)); >- auto next = constructTypeFromSuffixAbbreviated(*firstTypeSuffixAbbreviated, WTFMove(result)); >- result = WTFMove(next); >- while (true) { >- auto typeSuffixAbbreviated = backtrackingScope<Expected<TypeSuffixAbbreviated, Error>>([&]() { >- return parseTypeSuffixAbbreviated(); >- }); >- if (!typeSuffixAbbreviated) >+ if (addressSpaceToken) { >+ AST::AddressSpace addressSpace; >+ switch (addressSpaceToken->type) { >+ case Lexer::Token::Type::Constant: >+ addressSpace = AST::AddressSpace::Constant; > break; >- // FIXME: The nesting here might be in the wrong order. >- next = constructTypeFromSuffixAbbreviated(*typeSuffixAbbreviated, WTFMove(result)); >+ case Lexer::Token::Type::Device: >+ addressSpace = AST::AddressSpace::Device; >+ break; >+ case Lexer::Token::Type::Threadgroup: >+ addressSpace = AST::AddressSpace::Threadgroup; >+ break; >+ default: >+ ASSERT(addressSpaceToken->type == Lexer::Token::Type::Thread); >+ addressSpace = AST::AddressSpace::Thread; >+ break; >+ } >+ auto constructTypeFromSuffixAbbreviated = [&](const TypeSuffixAbbreviated& typeSuffixAbbreviated, UniqueRef<AST::UnnamedType>&& previous) -> UniqueRef<AST::UnnamedType> { >+ switch (typeSuffixAbbreviated.token.type) { >+ case Lexer::Token::Type::Star: >+ return { makeUniqueRef<AST::PointerType>(Lexer::Token(typeSuffixAbbreviated.token), addressSpace, WTFMove(previous)) }; >+ case Lexer::Token::Type::SquareBracketPair: >+ return { makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(typeSuffixAbbreviated.token), addressSpace, WTFMove(previous)) }; >+ default: >+ ASSERT(typeSuffixAbbreviated.token.type == Lexer::Token::Type::LeftSquareBracket); >+ return { makeUniqueRef<AST::ArrayType>(Lexer::Token(typeSuffixAbbreviated.token), WTFMove(previous), *typeSuffixAbbreviated.numElements) }; >+ } >+ }; >+ PARSE(firstTypeSuffixAbbreviated, TypeSuffixAbbreviated); >+ UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*addressSpaceToken), name->stringView.toString(), WTFMove(*typeArguments)); >+ auto next = constructTypeFromSuffixAbbreviated(*firstTypeSuffixAbbreviated, WTFMove(result)); > result = WTFMove(next); >+ while (true) { >+ PEEK(nextToken); >+ if (nextToken->type != Lexer::Token::Type::Star >+ && nextToken->type != Lexer::Token::Type::SquareBracketPair >+ && nextToken->type != Lexer::Token::Type::LeftSquareBracket) { >+ break; >+ } >+ PARSE(typeSuffixAbbreviated, TypeSuffixAbbreviated); >+ // FIXME: The nesting here might be in the wrong order. >+ next = constructTypeFromSuffixAbbreviated(*typeSuffixAbbreviated, WTFMove(result)); >+ result = WTFMove(next); >+ } >+ return WTFMove(result); > } > >- return WTFMove(result); >-} >- >-auto Parser::parseNonAddressSpaceType() -> Expected<UniqueRef<AST::UnnamedType>, Error> >-{ >- auto origin = peek(); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- auto name = consumeType(Lexer::Token::Type::Identifier); >- if (!name) >- return Unexpected<Error>(name.error()); >- auto typeArguments = parseTypeArguments(); >- if (!typeArguments) >- return Unexpected<Error>(typeArguments.error()); >- > auto constructTypeFromSuffixNonAbbreviated = [&](const TypeSuffixNonAbbreviated& typeSuffixNonAbbreviated, UniqueRef<AST::UnnamedType>&& previous) -> UniqueRef<AST::UnnamedType> { > switch (typeSuffixNonAbbreviated.token.type) { > case Lexer::Token::Type::Star: >@@ -567,58 +534,29 @@ auto Parser::parseNonAddressSpaceType() -> Expected<UniqueRef<AST::UnnamedType>, > return { makeUniqueRef<AST::ArrayType>(Lexer::Token(typeSuffixNonAbbreviated.token), WTFMove(previous), *typeSuffixNonAbbreviated.numElements) }; > } > }; >- >- UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*origin), name->stringView.toString(), WTFMove(*typeArguments)); >+ UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*name), name->stringView.toString(), WTFMove(*typeArguments)); > while (true) { >- auto typeSuffixNonAbbreviated = backtrackingScope<Expected<TypeSuffixNonAbbreviated, Error>>([&]() { >- return parseTypeSuffixNonAbbreviated(); >- }); >- if (!typeSuffixNonAbbreviated) >+ PEEK(nextToken); >+ if (nextToken->type != Lexer::Token::Type::Star >+ && nextToken->type != Lexer::Token::Type::SquareBracketPair >+ && nextToken->type != Lexer::Token::Type::LeftSquareBracket) { > break; >+ } >+ PARSE(typeSuffixNonAbbreviated, TypeSuffixNonAbbreviated); > // FIXME: The nesting here might be in the wrong order. > auto next = constructTypeFromSuffixNonAbbreviated(*typeSuffixNonAbbreviated, WTFMove(result)); > result = WTFMove(next); > } >- > return WTFMove(result); > } > >-auto Parser::parseType() -> Expected<UniqueRef<AST::UnnamedType>, Error> >-{ >- { >- auto type = backtrackingScope<Expected<UniqueRef<AST::UnnamedType>, Error>>([&]() { >- return parseAddressSpaceType(); >- }); >- if (type) >- return type; >- } >- >- auto type = backtrackingScope<Expected<UniqueRef<AST::UnnamedType>, Error>>([&]() { >- return parseNonAddressSpaceType(); >- }); >- if (type) >- return type; >- >- return Unexpected<Error>(type.error()); >-} >- > auto Parser::parseTypeDefinition() -> Expected<AST::TypeDefinition, Error> > { >- auto origin = consumeType(Lexer::Token::Type::Typedef); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- auto name = consumeType(Lexer::Token::Type::Identifier); >- if (!name) >- return Unexpected<Error>(name.error()); >- auto equals = consumeType(Lexer::Token::Type::EqualsSign); >- if (!equals) >- return Unexpected<Error>(equals.error()); >- auto type = parseType(); >- if (!type) >- return Unexpected<Error>(type.error()); >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >+ CONSUME_TYPE(origin, Typedef); >+ CONSUME_TYPE(name, Identifier); >+ CONSUME_TYPE(equals, EqualsSign); >+ PARSE(type, Type); >+ CONSUME_TYPE(semicolon, Semicolon); > return AST::TypeDefinition(WTFMove(*origin), name->stringView.toString(), WTFMove(*type)); > } > >@@ -681,17 +619,10 @@ auto Parser::parseBuiltInSemantic() -> Expected<AST::BuiltInSemantic, Error> > > auto Parser::parseResourceSemantic() -> Expected<AST::ResourceSemantic, Error> > { >- auto origin = consumeType(Lexer::Token::Type::Register); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ CONSUME_TYPE(origin, Register); >+ CONSUME_TYPE(leftParenthesis, LeftParenthesis); > >- auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >- if (!leftParenthesis) >- return Unexpected<Error>(leftParenthesis.error()); >- >- auto info = consumeType(Lexer::Token::Type::Identifier); >- if (!info) >- return Unexpected<Error>(info.error()); >+ CONSUME_TYPE(info, Identifier); > if (info->stringView.length() < 2 || (info->stringView[0] != 'u' > && info->stringView[0] != 't' > && info->stringView[0] != 'b' >@@ -720,9 +651,7 @@ auto Parser::parseResourceSemantic() -> Expected<AST::ResourceSemantic, Error> > > unsigned space = 0; > if (tryType(Lexer::Token::Type::Comma)) { >- auto spaceToken = consumeType(Lexer::Token::Type::Identifier); >- if (!spaceToken) >- return Unexpected<Error>(spaceToken.error()); >+ CONSUME_TYPE(spaceToken, Identifier); > auto prefix = "space"_str; > if (!spaceToken->stringView.startsWith(StringView(prefix))) > return Unexpected<Error>(Error(makeString("Second argument to resource semantic ", spaceToken->stringView, " needs be of the form 'space0'"))); >@@ -734,175 +663,113 @@ auto Parser::parseResourceSemantic() -> Expected<AST::ResourceSemantic, Error> > space = *spaceValue; > } > >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >+ CONSUME_TYPE(rightParenthesis, RightParenthesis); > > return AST::ResourceSemantic(WTFMove(*origin), mode, *index, space); > } > > auto Parser::parseSpecializationConstantSemantic() -> Expected<AST::SpecializationConstantSemantic, Error> > { >- auto origin = consumeType(Lexer::Token::Type::Specialized); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ CONSUME_TYPE(origin, Specialized); > return AST::SpecializationConstantSemantic(WTFMove(*origin)); > } > > auto Parser::parseStageInOutSemantic() -> Expected<AST::StageInOutSemantic, Error> > { >- auto origin = consumeType(Lexer::Token::Type::Attribute); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >- if (!leftParenthesis) >- return Unexpected<Error>(leftParenthesis.error()); >+ CONSUME_TYPE(origin, Attribute); >+ CONSUME_TYPE(leftParenthesis, LeftParenthesis); > > auto index = consumeNonNegativeIntegralLiteral(); > if (!index) > return Unexpected<Error>(index.error()); > >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >+ CONSUME_TYPE(rightParenthesis, RightParenthesis); > > return AST::StageInOutSemantic(WTFMove(*origin), *index); > } > >-auto Parser::parseSemantic() -> Expected<AST::Semantic, Error> >+auto Parser::parseSemantic() -> Expected<Optional<AST::Semantic>, Error> > { >- auto builtInSemantic = backtrackingScope<Expected<AST::BuiltInSemantic, Error>>([&]() { >- return parseBuiltInSemantic(); >- }); >- if (builtInSemantic) >- return AST::Semantic(WTFMove(*builtInSemantic)); >- >- auto resourceSemantic = backtrackingScope<Expected<AST::ResourceSemantic, Error>>([&]() { >- return parseResourceSemantic(); >- }); >- if (resourceSemantic) >- return AST::Semantic(WTFMove(*resourceSemantic)); >- >- auto specializationConstantSemantic = backtrackingScope<Expected<AST::SpecializationConstantSemantic, Error>>([&]() { >- return parseSpecializationConstantSemantic(); >- }); >- if (specializationConstantSemantic) >- return AST::Semantic(WTFMove(*specializationConstantSemantic)); >- >- auto stageInOutSemantic = backtrackingScope<Expected<AST::StageInOutSemantic, Error>>([&]() { >- return parseStageInOutSemantic(); >- }); >- if (stageInOutSemantic) >- return AST::Semantic(WTFMove(*stageInOutSemantic)); >+ if (!tryType(Lexer::Token::Type::Colon)) >+ return { WTF::nullopt }; > >- return Unexpected<Error>(stageInOutSemantic.error()); >+ PEEK(token); >+ switch (token->type) { >+ case Lexer::Token::Type::Attribute: { >+ PARSE(result, StageInOutSemantic); >+ return { AST::Semantic(WTFMove(*result)) }; >+ } >+ case Lexer::Token::Type::Specialized: { >+ PARSE(result, SpecializationConstantSemantic); >+ return { AST::Semantic(WTFMove(*result)) }; >+ } >+ case Lexer::Token::Type::Register: { >+ PARSE(result, ResourceSemantic); >+ return { AST::Semantic(WTFMove(*result)) }; >+ } >+ default: { >+ PARSE(result, BuiltInSemantic); >+ return { AST::Semantic(WTFMove(*result)) }; >+ } >+ } > } > AST::Qualifiers Parser::parseQualifiers() > { > AST::Qualifiers qualifiers; >- while (true) { >- if (auto next = tryType(Lexer::Token::Type::Qualifier)) { >- if ("nointerpolation" == next->stringView) >- qualifiers.append(AST::Qualifier::Nointerpolation); >- else if ("noperspective" == next->stringView) >- qualifiers.append(AST::Qualifier::Noperspective); >- else if ("uniform" == next->stringView) >- qualifiers.append(AST::Qualifier::Uniform); >- else if ("centroid" == next->stringView) >- qualifiers.append(AST::Qualifier::Centroid); >- else { >- ASSERT("sample" == next->stringView); >- qualifiers.append(AST::Qualifier::Sample); >- } >- } else >- break; >+ while (auto next = tryType(Lexer::Token::Type::Qualifier)) { >+ if ("nointerpolation" == next->stringView) >+ qualifiers.append(AST::Qualifier::Nointerpolation); >+ else if ("noperspective" == next->stringView) >+ qualifiers.append(AST::Qualifier::Noperspective); >+ else if ("uniform" == next->stringView) >+ qualifiers.append(AST::Qualifier::Uniform); >+ else if ("centroid" == next->stringView) >+ qualifiers.append(AST::Qualifier::Centroid); >+ else { >+ ASSERT("sample" == next->stringView); >+ qualifiers.append(AST::Qualifier::Sample); >+ } > } > return qualifiers; > } > > auto Parser::parseStructureElement() -> Expected<AST::StructureElement, Error> > { >- auto origin = peek(); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ PEEK(origin); > > AST::Qualifiers qualifiers = parseQualifiers(); > >- auto type = parseType(); >- if (!type) >- return Unexpected<Error>(type.error()); >- >- auto name = consumeType(Lexer::Token::Type::Identifier); >- if (!name) >- return Unexpected<Error>(name.error()); >- >- if (tryType(Lexer::Token::Type::Colon)) { >- auto semantic = parseSemantic(); >- if (!semantic) >- return Unexpected<Error>(semantic.error()); >+ PARSE(type, Type); >+ CONSUME_TYPE(name, Identifier); >+ PARSE(semantic, Semantic); >+ CONSUME_TYPE(semicolon, Semicolon); > >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >- >- return AST::StructureElement(WTFMove(*origin), WTFMove(qualifiers), WTFMove(*type), name->stringView.toString(), WTFMove(*semantic)); >- } >- >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >- >- return AST::StructureElement(WTFMove(*origin), WTFMove(qualifiers), WTFMove(*type), name->stringView.toString(), WTF::nullopt); >+ return AST::StructureElement(WTFMove(*origin), WTFMove(qualifiers), WTFMove(*type), name->stringView.toString(), WTFMove(*semantic)); > } > > auto Parser::parseStructureDefinition() -> Expected<AST::StructureDefinition, Error> > { >- auto origin = consumeType(Lexer::Token::Type::Struct); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto name = consumeType(Lexer::Token::Type::Identifier); >- if (!name) >- return Unexpected<Error>(name.error()); >- >- auto leftCurlyBracket = consumeType(Lexer::Token::Type::LeftCurlyBracket); >- if (!leftCurlyBracket) >- return Unexpected<Error>(leftCurlyBracket.error()); >+ CONSUME_TYPE(origin, Struct); >+ CONSUME_TYPE(name, Identifier); >+ CONSUME_TYPE(leftCurlyBracket, LeftCurlyBracket); > > AST::StructureElements structureElements; >- while (true) { >- auto structureElement = backtrackingScope<Expected<AST::StructureElement, Error>>([&]() { >- return parseStructureElement(); >- }); >- if (structureElement) >- structureElements.append(WTFMove(*structureElement)); >- else >- break; >+ while (!tryType(Lexer::Token::Type::RightCurlyBracket)) { >+ PARSE(structureElement, StructureElement); >+ structureElements.append(WTFMove(*structureElement)); > } > >- auto rightCurlyBracket = consumeType(Lexer::Token::Type::RightCurlyBracket); >- if (!rightCurlyBracket) >- return Unexpected<Error>(rightCurlyBracket.error()); >- > return AST::StructureDefinition(WTFMove(*origin), name->stringView.toString(), WTFMove(structureElements)); > } > > auto Parser::parseEnumerationDefinition() -> Expected<AST::EnumerationDefinition, Error> > { >- auto origin = consumeType(Lexer::Token::Type::Enum); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto name = consumeType(Lexer::Token::Type::Identifier); >- if (!name) >- return Unexpected<Error>(name.error()); >+ CONSUME_TYPE(origin, Enum); >+ CONSUME_TYPE(name, Identifier); > > auto type = ([&]() -> Expected<UniqueRef<AST::UnnamedType>, Error> { > if (tryType(Lexer::Token::Type::Colon)) { >- auto parsedType = parseType(); >- if (!parsedType) >- return Unexpected<Error>(parsedType.error()); >+ PARSE(parsedType, Type); > return WTFMove(*parsedType); > } > return { makeUniqueRef<AST::TypeReference>(Lexer::Token(*origin), "int"_str, AST::TypeArguments()) }; >@@ -910,13 +777,9 @@ auto Parser::parseEnumerationDefinition() -> Expected<AST::EnumerationDefinition > if (!type) > return Unexpected<Error>(type.error()); > >- auto leftCurlyBracket = consumeType(Lexer::Token::Type::LeftCurlyBracket); >- if (!leftCurlyBracket) >- return Unexpected<Error>(leftCurlyBracket.error()); >+ CONSUME_TYPE(leftCurlyBracket, LeftCurlyBracket); > >- auto firstEnumerationMember = parseEnumerationMember(); >- if (!firstEnumerationMember) >- return Unexpected<Error>(firstEnumerationMember.error()); >+ PARSE(firstEnumerationMember, EnumerationMember); > > AST::EnumerationDefinition result(WTFMove(*origin), name->stringView.toString(), WTFMove(*type)); > auto success = result.add(WTFMove(*firstEnumerationMember)); >@@ -924,32 +787,24 @@ auto Parser::parseEnumerationDefinition() -> Expected<AST::EnumerationDefinition > return fail("Cannot add enumeration member"_str); > > while (tryType(Lexer::Token::Type::Comma)) { >- auto member = parseEnumerationMember(); >- if (!member) >- return Unexpected<Error>(member.error()); >+ PARSE(member, EnumerationMember); > success = result.add(WTFMove(*member)); > if (!success) > return fail("Cannot add enumeration member"_str); > } > >- auto rightCurlyBracket = consumeType(Lexer::Token::Type::RightCurlyBracket); >- if (!rightCurlyBracket) >- return Unexpected<Error>(rightCurlyBracket.error()); >+ CONSUME_TYPE(rightCurlyBracket, RightCurlyBracket); > > return WTFMove(result); > } > > auto Parser::parseEnumerationMember() -> Expected<AST::EnumerationMember, Error> > { >- auto identifier = consumeType(Lexer::Token::Type::Identifier); >- if (!identifier) >- return Unexpected<Error>(identifier.error()); >+ CONSUME_TYPE(identifier, Identifier); > auto name = identifier->stringView.toString(); > > if (tryType(Lexer::Token::Type::EqualsSign)) { >- auto constantExpression = parseConstantExpression(); >- if (!constantExpression) >- return Unexpected<Error>(constantExpression.error()); >+ PARSE(constantExpression, ConstantExpression); > return AST::EnumerationMember(Lexer::Token(*identifier), WTFMove(name), WTFMove(*constantExpression)); > } > return AST::EnumerationMember(Lexer::Token(*identifier), WTFMove(name)); >@@ -957,71 +812,44 @@ auto Parser::parseEnumerationMember() -> Expected<AST::EnumerationMember, Error> > > auto Parser::parseNativeTypeDeclaration() -> Expected<AST::NativeTypeDeclaration, Error> > { >- auto origin = consumeType(Lexer::Token::Type::Native); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto parsedTypedef = consumeType(Lexer::Token::Type::Typedef); >- if (!parsedTypedef) >- return Unexpected<Error>(parsedTypedef.error()); >- >- auto name = consumeType(Lexer::Token::Type::Identifier); >- if (!name) >- return Unexpected<Error>(name.error()); >- >- auto typeArguments = parseTypeArguments(); >- if (!typeArguments) >- return Unexpected<Error>(typeArguments.error()); >- >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >+ CONSUME_TYPE(origin, Native); >+ CONSUME_TYPE(parsedTypedef, Typedef); >+ CONSUME_TYPE(name, Identifier); >+ PARSE(typeArguments, TypeArguments); >+ CONSUME_TYPE(semicolon, Semicolon); > > return AST::NativeTypeDeclaration(WTFMove(*origin), name->stringView.toString(), WTFMove(*typeArguments)); > } > > auto Parser::parseNumThreadsFunctionAttribute() -> Expected<AST::NumThreadsFunctionAttribute, Error> > { >- auto origin = consumeType(Lexer::Token::Type::NumThreads); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >- if (!leftParenthesis) >- return Unexpected<Error>(leftParenthesis.error()); >+ CONSUME_TYPE(origin, NumThreads); >+ CONSUME_TYPE(leftParenthesis, LeftParenthesis); > > auto width = consumeNonNegativeIntegralLiteral(); > if (!width) > return Unexpected<Error>(width.error()); > >- auto comma = consumeType(Lexer::Token::Type::Comma); >- if (!comma) >- return Unexpected<Error>(comma.error()); >+ CONSUME_TYPE(comma, Comma); > > auto height = consumeNonNegativeIntegralLiteral(); > if (!height) > return Unexpected<Error>(height.error()); > >- comma = consumeType(Lexer::Token::Type::Comma); >- if (!comma) >- return Unexpected<Error>(comma.error()); >+ CONSUME_TYPE(secondComma, Comma); > > auto depth = consumeNonNegativeIntegralLiteral(); > if (!depth) > return Unexpected<Error>(depth.error()); > >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >+ CONSUME_TYPE(rightParenthesis, RightParenthesis); > > return AST::NumThreadsFunctionAttribute(WTFMove(*origin), *width, *height, *depth); > } > > auto Parser::parseAttributeBlock() -> Expected<AST::AttributeBlock, Error> > { >- auto leftSquareBracket = consumeType(Lexer::Token::Type::LeftSquareBracket); >- if (!leftSquareBracket) >- return Unexpected<Error>(leftSquareBracket.error()); >+ CONSUME_TYPE(leftSquareBracket, LeftSquareBracket); > > AST::AttributeBlock result; > >@@ -1037,295 +865,169 @@ auto Parser::parseAttributeBlock() -> Expected<AST::AttributeBlock, Error> > break; > } > >- auto rightSquareBracket = consumeType(Lexer::Token::Type::RightSquareBracket); >- if (!rightSquareBracket) >- return Unexpected<Error>(rightSquareBracket.error()); >+ CONSUME_TYPE(rightSquareBracket, RightSquareBracket); > > return WTFMove(result); > } > > auto Parser::parseParameter() -> Expected<AST::VariableDeclaration, Error> > { >- auto origin = peek(); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ PEEK(origin); > > AST::Qualifiers qualifiers = parseQualifiers(); > >- auto type = parseType(); >- if (!type) >- return Unexpected<Error>(type.error()); >+ PARSE(type, Type); > > String name; > if (auto token = tryType(Lexer::Token::Type::Identifier)) > name = token->stringView.toString(); > >- if (tryType(Lexer::Token::Type::Colon)) { >- auto semantic = parseSemantic(); >- if (!semantic) >- return Unexpected<Error>(semantic.error()); >- return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), Optional<UniqueRef<AST::UnnamedType>>(WTFMove(*type)), WTFMove(name), WTFMove(*semantic), WTF::nullopt); >- } >+ PARSE(semantic, Semantic); > >- return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(*type) }, WTFMove(name), WTF::nullopt, WTF::nullopt); >+ return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(*type) }, WTFMove(name), WTFMove(*semantic), WTF::nullopt); > } > > auto Parser::parseParameters() -> Expected<AST::VariableDeclarations, Error> > { >- auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >- if (!leftParenthesis) >- return Unexpected<Error>(leftParenthesis.error()); >- > AST::VariableDeclarations parameters; >+ >+ CONSUME_TYPE(leftParenthesis, LeftParenthesis); >+ > if (tryType(Lexer::Token::Type::RightParenthesis)) > return WTFMove(parameters); > >- auto firstParameter = parseParameter(); >- if (!firstParameter) >- return Unexpected<Error>(firstParameter.error()); >+ PARSE(firstParameter, Parameter); > parameters.append(makeUniqueRef<AST::VariableDeclaration>(WTFMove(*firstParameter))); > > while (tryType(Lexer::Token::Type::Comma)) { >- auto parameter = parseParameter(); >- if (!parameter) >- return Unexpected<Error>(parameter.error()); >+ PARSE(parameter, Parameter); > parameters.append(makeUniqueRef<AST::VariableDeclaration>(WTFMove(*parameter))); > } > >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >+ CONSUME_TYPE(rightParenthesis, RightParenthesis); > > return WTFMove(parameters); > } > > auto Parser::parseFunctionDefinition() -> Expected<AST::FunctionDefinition, Error> > { >- auto functionDeclaration = parseFunctionDeclaration(); >- if (!functionDeclaration) >- return Unexpected<Error>(functionDeclaration.error()); >- >- auto block = parseBlock(); >- if (!block) >- return Unexpected<Error>(block.error()); >- >+ PARSE(functionDeclaration, FunctionDeclaration); >+ PARSE(block, Block); > return AST::FunctionDefinition(WTFMove(*functionDeclaration), WTFMove(*block)); > } > >-auto Parser::parseEntryPointFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error> >+auto Parser::parseComputeFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error> > { >- auto origin = peek(); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- AST::AttributeBlock attributeBlock; >- AST::EntryPointType entryPointType; >- >- auto parsedAttributeBlock = backtrackingScope<Expected<AST::AttributeBlock, Error>>([&]() { >- return parseAttributeBlock(); >- }); >- if (parsedAttributeBlock) { >- auto compute = consumeType(Lexer::Token::Type::Compute); >- if (!compute) >- return Unexpected<Error>(compute.error()); >- attributeBlock = WTFMove(*parsedAttributeBlock); >- entryPointType = AST::EntryPointType::Compute; >- } else { >- auto type = consumeTypes({ Lexer::Token::Type::Vertex, Lexer::Token::Type::Fragment }); >- if (!type) >- return Unexpected<Error>(type.error()); >- >- switch (origin->type) { >- case Lexer::Token::Type::Vertex: >- entryPointType = AST::EntryPointType::Vertex; >- break; >- default: >- ASSERT(origin->type == Lexer::Token::Type::Fragment); >- entryPointType = AST::EntryPointType::Fragment; >- break; >- } >- } >+ PEEK(origin); > >- auto type = parseType(); >- if (!type) >- return Unexpected<Error>(type.error()); >+ PARSE(attributeBlock, AttributeBlock); >+ CONSUME_TYPE(compute, Compute); >+ PARSE(type, Type); >+ CONSUME_TYPE(name, Identifier); >+ PARSE(parameters, Parameters); >+ PARSE(semantic, Semantic); >+ bool isOperator = false; >+ return AST::FunctionDeclaration(WTFMove(*origin), WTFMove(*attributeBlock), AST::EntryPointType::Compute, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator); >+} > >- auto name = consumeType(Lexer::Token::Type::Identifier); >- if (!name) >- return Unexpected<Error>(name.error()); >+auto Parser::parseVertexOrFragmentFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error> >+{ >+ auto entryPoint = consumeTypes({ Lexer::Token::Type::Vertex, Lexer::Token::Type::Fragment }); >+ if (!entryPoint) >+ return Unexpected<Error>(entryPoint.error()); >+ auto entryPointType = (entryPoint->type == Lexer::Token::Type::Vertex) ? AST::EntryPointType::Vertex : AST::EntryPointType::Fragment; > >- auto parameters = parseParameters(); >- if (!parameters) >- return Unexpected<Error>(parameters.error()); >+ PARSE(type, Type); >+ CONSUME_TYPE(name, Identifier); >+ PARSE(parameters, Parameters); >+ PARSE(semantic, Semantic); > > bool isOperator = false; >- >- if (tryType(Lexer::Token::Type::Colon)) { >- auto semantic = parseSemantic(); >- if (!semantic) >- return Unexpected<Error>(semantic.error()); >- return AST::FunctionDeclaration(WTFMove(*origin), WTFMove(attributeBlock), entryPointType, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator); >- } >- >- return AST::FunctionDeclaration(WTFMove(*origin), WTFMove(attributeBlock), entryPointType, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTF::nullopt, isOperator); >+ return AST::FunctionDeclaration(WTFMove(*entryPoint), { }, entryPointType, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator); > } > > auto Parser::parseRegularFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error> > { >- auto origin = peek(); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ PEEK(origin); > >- auto type = parseType(); >- if (!type) >- return Unexpected<Error>(type.error()); >+ PARSE(type, Type); > > auto name = consumeTypes({ Lexer::Token::Type::Identifier, Lexer::Token::Type::OperatorName }); > if (!name) > return Unexpected<Error>(name.error()); > auto isOperator = name->type == Lexer::Token::Type::OperatorName; > >- auto parameters = parseParameters(); >- if (!parameters) >- return Unexpected<Error>(parameters.error()); >+ PARSE(parameters, Parameters); >+ PARSE(semantic, Semantic); > >- if (tryType(Lexer::Token::Type::Colon)) { >- auto semantic = parseSemantic(); >- if (!semantic) >- return Unexpected<Error>(semantic.error()); >- return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator); >- } >- >- return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTF::nullopt, isOperator); >+ return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator); > } > > auto Parser::parseOperatorFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error> > { >- auto origin = consumeType(Lexer::Token::Type::Operator); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto type = parseType(); >- if (!type) >- return Unexpected<Error>(type.error()); >- >- auto parameters = parseParameters(); >- if (!parameters) >- return Unexpected<Error>(parameters.error()); >+ CONSUME_TYPE(origin, Operator); >+ PARSE(type, Type); >+ PARSE(parameters, Parameters); >+ PARSE(semantic, Semantic); > > bool isOperator = true; >- >- if (tryType(Lexer::Token::Type::Colon)) { >- auto semantic = parseSemantic(); >- if (!semantic) >- return Unexpected<Error>(semantic.error()); >- return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), "operator cast"_str, WTFMove(*parameters), WTFMove(*semantic), isOperator); >- } >- >- return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), "operator cast"_str, WTFMove(*parameters), WTF::nullopt, isOperator); >+ return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), "operator cast"_str, WTFMove(*parameters), WTFMove(*semantic), isOperator); > } > > auto Parser::parseFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error> > { >- auto entryPointFunctionDeclaration = backtrackingScope<Expected<AST::FunctionDeclaration, Error>>([&]() { >- return parseEntryPointFunctionDeclaration(); >- }); >- if (entryPointFunctionDeclaration) >- return WTFMove(*entryPointFunctionDeclaration); >- >- auto regularFunctionDeclaration = backtrackingScope<Expected<AST::FunctionDeclaration, Error>>([&]() { >- return parseRegularFunctionDeclaration(); >- }); >- if (regularFunctionDeclaration) >- return WTFMove(*regularFunctionDeclaration); >- >- auto operatorFunctionDeclaration = backtrackingScope<Expected<AST::FunctionDeclaration, Error>>([&]() { >+ PEEK(token); >+ switch (token->type) { >+ case Lexer::Token::Type::Operator: > return parseOperatorFunctionDeclaration(); >- }); >- if (operatorFunctionDeclaration) >- return WTFMove(*operatorFunctionDeclaration); >- >- return Unexpected<Error>(operatorFunctionDeclaration.error()); >+ case Lexer::Token::Type::Vertex: >+ case Lexer::Token::Type::Fragment: >+ return parseVertexOrFragmentFunctionDeclaration(); >+ case Lexer::Token::Type::LeftSquareBracket: >+ return parseComputeFunctionDeclaration(); >+ default: >+ return parseRegularFunctionDeclaration(); >+ } > } > > auto Parser::parseNativeFunctionDeclaration() -> Expected<AST::NativeFunctionDeclaration, Error> > { >- Optional<Lexer::Token> origin; >+ CONSUME_TYPE(native, Native); >+ PARSE(functionDeclaration, FunctionDeclaration); >+ CONSUME_TYPE(semicolon, Semicolon); > >- auto native = consumeType(Lexer::Token::Type::Native); >- if (!native) >- return Unexpected<Error>(native.error()); >- if (!origin) >- origin = *native; >- >- auto functionDeclaration = parseFunctionDeclaration(); >- if (!functionDeclaration) >- return Unexpected<Error>(functionDeclaration.error()); >- >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >- >- return AST::NativeFunctionDeclaration(WTFMove(*functionDeclaration)); >-} >+ return AST::NativeFunctionDeclaration(WTFMove(*functionDeclaration)); >+} > > auto Parser::parseBlock() -> Expected<AST::Block, Error> > { >- auto origin = consumeType(Lexer::Token::Type::LeftCurlyBracket); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto result = parseBlockBody(WTFMove(*origin)); >- >- auto rightCurlyBracket = consumeType(Lexer::Token::Type::RightCurlyBracket); >- if (!rightCurlyBracket) >- return Unexpected<Error>(rightCurlyBracket.error()); >- >- return WTFMove(result); >+ CONSUME_TYPE(origin, LeftCurlyBracket); >+ PARSE(result, BlockBody, WTFMove(*origin)); >+ CONSUME_TYPE(rightCurlyBracket, RightCurlyBracket); >+ return WTFMove(*result); > } > >-AST::Block Parser::parseBlockBody(Lexer::Token&& origin) >+auto Parser::parseBlockBody(Lexer::Token&& origin) -> Expected<AST::Block, Error> > { > AST::Statements statements; >- while (true) { >- auto statement = backtrackingScope<Expected<UniqueRef<AST::Statement>, Error>>([&]() { >- return parseStatement(); >- }); >- if (statement) >- statements.append(WTFMove(*statement)); >- else >- break; >+ while (!peekTypes({Lexer::Token::Type::RightCurlyBracket, Lexer::Token::Type::Case, Lexer::Token::Type::Default})) { >+ PARSE(statement, Statement); >+ statements.append(WTFMove(*statement)); > } > return AST::Block(WTFMove(origin), WTFMove(statements)); > } > > auto Parser::parseIfStatement() -> Expected<AST::IfStatement, Error> > { >- auto origin = consumeType(Lexer::Token::Type::If); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >- if (!leftParenthesis) >- return Unexpected<Error>(leftParenthesis.error()); >- >- auto conditional = parseExpression(); >- if (!conditional) >- return Unexpected<Error>(conditional.error()); >- >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >- >- auto body = parseStatement(); >- if (!body) >- return Unexpected<Error>(body.error()); >+ CONSUME_TYPE(origin, If); >+ CONSUME_TYPE(leftParenthesis, LeftParenthesis); >+ PARSE(conditional, Expression); >+ CONSUME_TYPE(rightParenthesis, RightParenthesis); >+ PARSE(body, Statement); > > Optional<UniqueRef<AST::Statement>> elseBody; > if (tryType(Lexer::Token::Type::Else)) { >- auto parsedElseBody = parseStatement(); >- if (!parsedElseBody) >- return Unexpected<Error>(parsedElseBody.error()); >+ PARSE(parsedElseBody, Statement); > elseBody = WTFMove(*parsedElseBody); > } > >@@ -1337,40 +1039,20 @@ auto Parser::parseIfStatement() -> Expected<AST::IfStatement, Error> > > auto Parser::parseSwitchStatement() -> Expected<AST::SwitchStatement, Error> > { >- auto origin = consumeType(Lexer::Token::Type::Switch); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >- if (!leftParenthesis) >- return Unexpected<Error>(leftParenthesis.error()); >- >- auto value = parseExpression(); >- if (!value) >- return Unexpected<Error>(value.error()); >- >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >- >- auto leftCurlyBracket = consumeType(Lexer::Token::Type::LeftCurlyBracket); >- if (!leftCurlyBracket) >- return Unexpected<Error>(leftCurlyBracket.error()); >+ CONSUME_TYPE(origin, Switch); >+ CONSUME_TYPE(leftParenthesis, LeftParenthesis); >+ PARSE(value, Expression); >+ CONSUME_TYPE(rightParenthesis, RightParenthesis); >+ CONSUME_TYPE(leftCurlyBracket, LeftCurlyBracket); > > Vector<AST::SwitchCase> switchCases; >- while (true) { >- auto switchCase = backtrackingScope<Expected<AST::SwitchCase, Error>>([&]() { >- return parseSwitchCase(); >- }); >- if (switchCase) >- switchCases.append(WTFMove(*switchCase)); >- else >- break; >+ PEEK(nextToken); >+ while (nextToken->type != Lexer::Token::Type::RightCurlyBracket) { >+ PARSE(switchCase, SwitchCase); >+ switchCases.append(WTFMove(*switchCase)); > } > >- auto rightCurlyBracket = consumeType(Lexer::Token::Type::RightCurlyBracket); >- if (!rightCurlyBracket) >- return Unexpected<Error>(rightCurlyBracket.error()); >+ m_lexer.consumeToken(); > > return AST::SwitchStatement(WTFMove(*origin), WTFMove(*value), WTFMove(switchCases)); > } >@@ -1383,186 +1065,112 @@ auto Parser::parseSwitchCase() -> Expected<AST::SwitchCase, Error> > > switch (origin->type) { > case Lexer::Token::Type::Case: { >- auto value = parseConstantExpression(); >- if (!value) >- return Unexpected<Error>(value.error()); >- >- auto origin = consumeType(Lexer::Token::Type::Colon); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ PARSE(value, ConstantExpression); >+ CONSUME_TYPE(colon, Colon); > >- auto block = parseBlockBody(Lexer::Token(*origin)); >+ PARSE(block, BlockBody, Lexer::Token(*origin)); > >- return AST::SwitchCase(WTFMove(*origin), WTFMove(*value), WTFMove(block)); >+ return AST::SwitchCase(WTFMove(*origin), WTFMove(*value), WTFMove(*block)); > } > default: { > ASSERT(origin->type == Lexer::Token::Type::Default); >- auto origin = consumeType(Lexer::Token::Type::Colon); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ CONSUME_TYPE(colon, Colon); > >- auto block = parseBlockBody(Lexer::Token(*origin)); >+ PARSE(block, BlockBody, Lexer::Token(*origin)); > >- return AST::SwitchCase(WTFMove(*origin), WTF::nullopt, WTFMove(block)); >+ return AST::SwitchCase(WTFMove(*origin), WTF::nullopt, WTFMove(*block)); > } > } > } > > auto Parser::parseForLoop() -> Expected<AST::ForLoop, Error> > { >- auto origin = consumeType(Lexer::Token::Type::For); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ CONSUME_TYPE(origin, For); >+ CONSUME_TYPE(leftParenthesis, LeftParenthesis); > > auto parseRemainder = [&](Variant<AST::VariableDeclarationsStatement, UniqueRef<AST::Expression>>&& initialization) -> Expected<AST::ForLoop, Error> { >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >+ CONSUME_TYPE(semicolon, Semicolon); > >- auto condition = backtrackingScope<Optional<UniqueRef<AST::Expression>>>([&]() -> Optional<UniqueRef<AST::Expression>> { >+ Optional<UniqueRef<AST::Expression>> condition = WTF::nullopt; >+ if (!tryType(Lexer::Token::Type::Semicolon)) { > if (auto expression = parseExpression()) >- return { WTFMove(*expression) }; >- return WTF::nullopt; >- }); >- >- semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >+ condition = { WTFMove(*expression) }; >+ else >+ return Unexpected<Error>(expression.error()); >+ CONSUME_TYPE(secondSemicolon, Semicolon); >+ } > >- auto increment = backtrackingScope<Optional<UniqueRef<AST::Expression>>>([&]() -> Optional<UniqueRef<AST::Expression>> { >+ Optional<UniqueRef<AST::Expression>> increment = WTF::nullopt; >+ if (!tryType(Lexer::Token::Type::RightParenthesis)) { > if (auto expression = parseExpression()) >- return { WTFMove(*expression) }; >- return WTF::nullopt; >- }); >- >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >+ increment = { WTFMove(*expression) }; >+ else >+ return Unexpected<Error>(expression.error()); >+ CONSUME_TYPE(rightParenthesis, RightParenthesis); >+ } > >- auto body = parseStatement(); >- if (!body) >- return Unexpected<Error>(body.error()); >+ PARSE(body, Statement); > > return AST::ForLoop(WTFMove(*origin), WTFMove(initialization), WTFMove(condition), WTFMove(increment), WTFMove(*body)); > }; > >- auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >- if (!leftParenthesis) >- return Unexpected<Error>(leftParenthesis.error()); >- > auto variableDeclarations = backtrackingScope<Expected<AST::VariableDeclarationsStatement, Error>>([&]() { > return parseVariableDeclarations(); > }); > if (variableDeclarations) > return parseRemainder(WTFMove(*variableDeclarations)); > >- auto effectfulExpression = parseEffectfulExpression(); >- if (!effectfulExpression) >- return Unexpected<Error>(effectfulExpression.error()); >+ PARSE(effectfulExpression, EffectfulExpression); > > return parseRemainder(WTFMove(*effectfulExpression)); > } > > auto Parser::parseWhileLoop() -> Expected<AST::WhileLoop, Error> > { >- auto origin = consumeType(Lexer::Token::Type::While); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >- if (!leftParenthesis) >- return Unexpected<Error>(leftParenthesis.error()); >- >- auto conditional = parseExpression(); >- if (!conditional) >- return Unexpected<Error>(conditional.error()); >- >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >- >- auto body = parseStatement(); >- if (!body) >- return Unexpected<Error>(body.error()); >+ CONSUME_TYPE(origin, While); >+ CONSUME_TYPE(leftParenthesis, LeftParenthesis); >+ PARSE(conditional, Expression); >+ CONSUME_TYPE(rightParenthesis, RightParenthesis); >+ PARSE(body, Statement); > > return AST::WhileLoop(WTFMove(*origin), WTFMove(*conditional), WTFMove(*body)); > } > > auto Parser::parseDoWhileLoop() -> Expected<AST::DoWhileLoop, Error> > { >- auto origin = consumeType(Lexer::Token::Type::Do); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto body = parseStatement(); >- if (!body) >- return Unexpected<Error>(body.error()); >- >- auto whileKeyword = consumeType(Lexer::Token::Type::While); >- if (!whileKeyword) >- return Unexpected<Error>(whileKeyword.error()); >- >- auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >- if (!leftParenthesis) >- return Unexpected<Error>(leftParenthesis.error()); >- >- auto conditional = parseExpression(); >- if (!conditional) >- return Unexpected<Error>(conditional.error()); >- >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >+ CONSUME_TYPE(origin, Do); >+ PARSE(body, Statement); >+ CONSUME_TYPE(whileKeyword, While); >+ CONSUME_TYPE(leftParenthesis, LeftParenthesis); >+ PARSE(conditional, Expression); >+ CONSUME_TYPE(rightParenthesis, RightParenthesis); >+ CONSUME_TYPE(semicolon, Semicolon); > > return AST::DoWhileLoop(WTFMove(*origin), WTFMove(*body), WTFMove(*conditional)); > } > > auto Parser::parseVariableDeclaration(UniqueRef<AST::UnnamedType>&& type) -> Expected<AST::VariableDeclaration, Error> > { >- auto origin = peek(); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ PEEK(origin); > > auto qualifiers = parseQualifiers(); > >- auto name = consumeType(Lexer::Token::Type::Identifier); >- if (!name) >- return Unexpected<Error>(name.error()); >- >- if (tryType(Lexer::Token::Type::Colon)) { >- auto semantic = parseSemantic(); >- if (!semantic) >- return Unexpected<Error>(semantic.error()); >- >- if (tryType(Lexer::Token::Type::EqualsSign)) { >- auto initializer = parseExpression(); >- if (!initializer) >- return Unexpected<Error>(initializer.error()); >- return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTFMove(*semantic), WTFMove(*initializer)); >- } >- >- return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTFMove(*semantic), WTF::nullopt); >- } >+ CONSUME_TYPE(name, Identifier); >+ PARSE(semantic, Semantic); > > if (tryType(Lexer::Token::Type::EqualsSign)) { >- auto initializer = parseExpression(); >- if (!initializer) >- return Unexpected<Error>(initializer.error()); >- return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTF::nullopt, WTFMove(*initializer)); >+ PARSE(initializer, PossibleTernaryConditional); >+ return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTFMove(*semantic), WTFMove(*initializer)); > } > >- return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTF::nullopt, WTF::nullopt); >+ return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTFMove(*semantic), WTF::nullopt); > } > > auto Parser::parseVariableDeclarations() -> Expected<AST::VariableDeclarationsStatement, Error> > { >- auto origin = peek(); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ PEEK(origin); > >- auto type = parseType(); >- if (!type) >- return Unexpected<Error>(type.error()); >+ PARSE(type, Type); > > auto firstVariableDeclaration = parseVariableDeclaration((*type)->clone()); > if (!firstVariableDeclaration) >@@ -1583,205 +1191,123 @@ auto Parser::parseVariableDeclarations() -> Expected<AST::VariableDeclarationsSt > > auto Parser::parseStatement() -> Expected<UniqueRef<AST::Statement>, Error> > { >- { >- auto block = backtrackingScope<Expected<AST::Block, Error>>([&]() { >- return parseBlock(); >- }); >- if (block) >- return { makeUniqueRef<AST::Block>(WTFMove(*block)) }; >- } >- >- { >- auto ifStatement = backtrackingScope<Expected<AST::IfStatement, Error>>([&]() { >- return parseIfStatement(); >- }); >- if (ifStatement) >- return { makeUniqueRef<AST::IfStatement>(WTFMove(*ifStatement)) }; >- } >- >- { >- auto switchStatement = backtrackingScope<Expected<AST::SwitchStatement, Error>>([&]() { >- return parseSwitchStatement(); >- }); >- if (switchStatement) >- return { makeUniqueRef<AST::SwitchStatement>(WTFMove(*switchStatement)) }; >- } >- >- { >- auto forLoop = backtrackingScope<Expected<AST::ForLoop, Error>>([&]() { >- return parseForLoop(); >- }); >- if (forLoop) >- return { makeUniqueRef<AST::ForLoop>(WTFMove(*forLoop)) }; >- } >- >- { >- auto whileLoop = backtrackingScope<Expected<AST::WhileLoop, Error>>([&]() { >- return parseWhileLoop(); >- }); >- if (whileLoop) >- return { makeUniqueRef<AST::WhileLoop>(WTFMove(*whileLoop)) }; >- } >- >- { >- auto doWhileLoop = backtrackingScope<Expected<AST::DoWhileLoop, Error>>([&]() -> Expected<AST::DoWhileLoop, Error> { >- auto result = parseDoWhileLoop(); >- if (!result) >- return Unexpected<Error>(result.error()); >- >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >- >- return result; >- }); >- if (doWhileLoop) >- return { makeUniqueRef<AST::DoWhileLoop>(WTFMove(*doWhileLoop)) }; >- } >- >- { >- auto breakObject = backtrackingScope<Expected<AST::Break, Error>>([&]() -> Expected<AST::Break, Error> { >- auto origin = consumeType(Lexer::Token::Type::Break); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >- >- return AST::Break(WTFMove(*origin)); >- }); >- if (breakObject) >- return { makeUniqueRef<AST::Break>(WTFMove(*breakObject)) }; >- } >- >- { >- auto continueObject = backtrackingScope<Expected<AST::Continue, Error>>([&]() -> Expected<AST::Continue, Error> { >- auto origin = consumeType(Lexer::Token::Type::Continue); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >- >- return AST::Continue(WTFMove(*origin)); >- }); >- if (continueObject) >- return { makeUniqueRef<AST::Continue>(WTFMove(*continueObject)) }; >+ PEEK(token); >+ switch (token->type) { >+ case Lexer::Token::Type::LeftCurlyBracket: { >+ PARSE(block, Block); >+ return { makeUniqueRef<AST::Block>(WTFMove(*block)) }; >+ } >+ case Lexer::Token::Type::If: { >+ PARSE(ifStatement, IfStatement); >+ return { makeUniqueRef<AST::IfStatement>(WTFMove(*ifStatement)) }; >+ } >+ case Lexer::Token::Type::Switch: { >+ PARSE(switchStatement, SwitchStatement); >+ return { makeUniqueRef<AST::SwitchStatement>(WTFMove(*switchStatement)) }; >+ } >+ case Lexer::Token::Type::For: { >+ PARSE(forLoop, ForLoop); >+ return { makeUniqueRef<AST::ForLoop>(WTFMove(*forLoop)) }; >+ } >+ case Lexer::Token::Type::While: { >+ PARSE(whileLoop, WhileLoop); >+ return { makeUniqueRef<AST::WhileLoop>(WTFMove(*whileLoop)) }; >+ } >+ case Lexer::Token::Type::Do: { >+ PARSE(doWhileLoop, DoWhileLoop); >+ return { makeUniqueRef<AST::DoWhileLoop>(WTFMove(*doWhileLoop)) }; >+ } >+ case Lexer::Token::Type::Break: { >+ auto breakToken = m_lexer.consumeToken(); >+ CONSUME_TYPE(semicolon, Semicolon); >+ auto breakObject = AST::Break(WTFMove(*breakToken)); >+ return { makeUniqueRef<AST::Break>(WTFMove(breakObject)) }; >+ } >+ case Lexer::Token::Type::Continue: { >+ auto continueToken = m_lexer.consumeToken(); >+ CONSUME_TYPE(semicolon, Semicolon); >+ auto continueObject = AST::Continue(WTFMove(*continueToken)); >+ return { makeUniqueRef<AST::Continue>(WTFMove(continueObject)) }; >+ } >+ case Lexer::Token::Type::Fallthrough: { >+ auto fallthroughToken = m_lexer.consumeToken(); >+ CONSUME_TYPE(semicolon, Semicolon); >+ auto fallthroughObject = AST::Fallthrough(WTFMove(*fallthroughToken)); >+ return { makeUniqueRef<AST::Fallthrough>(WTFMove(fallthroughObject)) }; >+ } >+ case Lexer::Token::Type::Trap: { >+ auto trapToken = m_lexer.consumeToken(); >+ CONSUME_TYPE(semicolon, Semicolon); >+ auto trapObject = AST::Trap(WTFMove(*trapToken)); >+ return { makeUniqueRef<AST::Trap>(WTFMove(trapObject)) }; >+ } >+ case Lexer::Token::Type::Return: { >+ auto returnToken = m_lexer.consumeToken(); >+ if (auto semicolon = tryType(Lexer::Token::Type::Semicolon)) { >+ auto returnObject = AST::Return(WTFMove(*returnToken), WTF::nullopt); >+ return { makeUniqueRef<AST::Return>(WTFMove(returnObject)) }; >+ } >+ PARSE(expression, Expression); >+ CONSUME_TYPE(finalSemicolon, Semicolon); >+ auto returnObject = AST::Return(WTFMove(*returnToken), { WTFMove(*expression) }); >+ return { makeUniqueRef<AST::Return>(WTFMove(returnObject)) }; > } >- >- { >- auto fallthroughObject = backtrackingScope<Expected<AST::Fallthrough, Error>>([&]() -> Expected<AST::Fallthrough, Error> { >- auto origin = consumeType(Lexer::Token::Type::Fallthrough); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >- >- return AST::Fallthrough(WTFMove(*origin)); >- }); >- if (fallthroughObject) >- return { makeUniqueRef<AST::Fallthrough>(WTFMove(*fallthroughObject)) }; >+ case Lexer::Token::Type::Constant: >+ case Lexer::Token::Type::Device: >+ case Lexer::Token::Type::Threadgroup: >+ case Lexer::Token::Type::Thread: { >+ PARSE(variableDeclarations, VariableDeclarations); >+ CONSUME_TYPE(semicolon, Semicolon); >+ return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) }; > } >- >- { >- auto trapObject = backtrackingScope<Expected<AST::Trap, Error>>([&]() -> Expected<AST::Trap, Error> { >- auto origin = consumeType(Lexer::Token::Type::Trap); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >- >- return AST::Trap(WTFMove(*origin)); >- }); >- if (trapObject) >- return { makeUniqueRef<AST::Trap>(WTFMove(*trapObject)) }; >+ case Lexer::Token::Type::Identifier: { >+ PEEK_FURTHER(nextToken); >+ switch (nextToken->type) { >+ case Lexer::Token::Type::Identifier: >+ case Lexer::Token::Type::LessThanSign: >+ case Lexer::Token::Type::Star: >+ case Lexer::Token::Type::Qualifier: { >+ PARSE(variableDeclarations, VariableDeclarations); >+ CONSUME_TYPE(semicolon, Semicolon); >+ return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) }; >+ } >+ default: >+ break; >+ } >+ break; > } >- >- { >- auto returnObject = backtrackingScope<Expected<AST::Return, Error>>([&]() -> Expected<AST::Return, Error> { >- auto origin = consumeType(Lexer::Token::Type::Return); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- if (auto semicolon = tryType(Lexer::Token::Type::Semicolon)) >- return AST::Return(WTFMove(*origin), WTF::nullopt); >- >- auto expression = parseExpression(); >- if (!expression) >- return Unexpected<Error>(expression.error()); >- >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >- >- return AST::Return(WTFMove(*origin), { WTFMove(*expression) }); >- }); >- if (returnObject) >- return { makeUniqueRef<AST::Return>(WTFMove(*returnObject)) }; >+ default: >+ break; > } > > { >- auto variableDeclarations = backtrackingScope<Expected<AST::VariableDeclarationsStatement, Error>>([&]() -> Expected<AST::VariableDeclarationsStatement, Error> { >- auto result = parseVariableDeclarations(); >- if (!result) >- return Unexpected<Error>(result.error()); >- >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >- >+ auto effectfulExpression = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> { >+ PARSE(result, EffectfulExpression); >+ CONSUME_TYPE(semicolon, Semicolon); > return result; > }); >- if (variableDeclarations) >- return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) }; >+ if (effectfulExpression) >+ return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(*effectfulExpression)) }; > } > >- auto effectfulExpression = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> { >- auto result = parseEffectfulExpression(); >- if (!result) >- return Unexpected<Error>(result.error()); >- >- auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >- if (!semicolon) >- return Unexpected<Error>(semicolon.error()); >- >- return result; >- }); >- if (effectfulExpression) >- return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(*effectfulExpression)) }; >- >- return Unexpected<Error>(effectfulExpression.error()); >+ PARSE(variableDeclarations, VariableDeclarations); >+ CONSUME_TYPE(semicolon, Semicolon); >+ return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) }; > } > > auto Parser::parseEffectfulExpression() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto origin = peek(); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ PEEK(origin); > > Vector<UniqueRef<AST::Expression>> expressions; >- >- auto first = backtrackingScope<Optional<UniqueRef<AST::Expression>>>([&]() -> Optional<UniqueRef<AST::Expression>> { >- auto effectfulExpression = parseEffectfulAssignment(); >- if (!effectfulExpression) >- return WTF::nullopt; >- return { WTFMove(*effectfulExpression) }; >- }); >- if (!first) >+ if (origin->type == Lexer::Token::Type::Semicolon) > return { makeUniqueRef<AST::CommaExpression>(WTFMove(*origin), WTFMove(expressions)) }; > >- expressions.append(WTFMove(*first)); >+ PARSE(effectfulExpression, EffectfulAssignment); >+ expressions.append(WTFMove(*effectfulExpression)); > > while (tryType(Lexer::Token::Type::Comma)) { >- auto expression = parseEffectfulAssignment(); >- if (!expression) >- return Unexpected<Error>(expression.error()); >+ PARSE(expression, EffectfulAssignment); > expressions.append(WTFMove(*expression)); > } > >@@ -1792,111 +1318,28 @@ auto Parser::parseEffectfulExpression() -> Expected<UniqueRef<AST::Expression>, > > auto Parser::parseEffectfulAssignment() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto assignment = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() { >- return parseAssignment(); >- }); >- if (assignment) >- return assignment; >- >- assignment = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() { >- return parseEffectfulPrefix(); >- }); >- if (assignment) >- return assignment; >+ PEEK(origin); > >- return Unexpected<Error>(assignment.error()); >-} >+ bool isEffectful = false; >+ PARSE(expression, PossiblePrefix, &isEffectful); > >-auto Parser::parseEffectfulPrefix() -> Expected<UniqueRef<AST::Expression>, Error> >-{ >- auto prefix = consumeTypes({ Lexer::Token::Type::PlusPlus, Lexer::Token::Type::MinusMinus }); >- if (!prefix) >- return parseEffectfulSuffix(); >- >- auto previous = parsePossiblePrefix(); >- if (!previous) >- return Unexpected<Error>(previous.error()); >- >- switch (prefix->type) { >- case Lexer::Token::Type::PlusPlus: { >- auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*prefix), WTFMove(*previous)); >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(result->oldVariableReference()); >- result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(*prefix), "operator++"_str, WTFMove(callArguments))); >- result->setResultExpression(result->newVariableReference()); >- return { WTFMove(result) }; >- } >- default: { >- ASSERT(prefix->type == Lexer::Token::Type::MinusMinus); >- auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*prefix), WTFMove(*previous)); >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(result->oldVariableReference()); >- result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(*prefix), "operator--"_str, WTFMove(callArguments))); >- result->setResultExpression(result->newVariableReference()); >- return { WTFMove(result) }; >- } >+ if (!isEffectful || peekTypes({ >+ Lexer::Token::Type::EqualsSign, >+ Lexer::Token::Type::PlusEquals, >+ Lexer::Token::Type::MinusEquals, >+ Lexer::Token::Type::TimesEquals, >+ Lexer::Token::Type::DivideEquals, >+ Lexer::Token::Type::ModEquals, >+ Lexer::Token::Type::XorEquals, >+ Lexer::Token::Type::AndEquals, >+ Lexer::Token::Type::OrEquals, >+ Lexer::Token::Type::RightShiftEquals, >+ Lexer::Token::Type::LeftShiftEquals >+ })) { >+ return completeAssignment(WTFMove(*origin), WTFMove(*expression)); > } >-} >- >-auto Parser::parseEffectfulSuffix() -> Expected<UniqueRef<AST::Expression>, Error> >-{ >- auto effectfulSuffix = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> { >- auto previous = parsePossibleSuffix(); >- if (!previous) >- return Unexpected<Error>(previous.error()); >- >- auto suffix = consumeTypes({ Lexer::Token::Type::PlusPlus, Lexer::Token::Type::MinusMinus }); >- if (!suffix) >- return Unexpected<Error>(suffix.error()); >- >- switch (suffix->type) { >- case Lexer::Token::Type::PlusPlus: { >- auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*suffix), WTFMove(*previous)); >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(result->oldVariableReference()); >- result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(*suffix), "operator++"_str, WTFMove(callArguments))); >- result->setResultExpression(result->oldVariableReference()); >- return { WTFMove(result) }; >- } >- default: { >- ASSERT(suffix->type == Lexer::Token::Type::MinusMinus); >- auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*suffix), WTFMove(*previous)); >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(result->oldVariableReference()); >- result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(*suffix), "operator--"_str, WTFMove(callArguments))); >- result->setResultExpression(result->oldVariableReference()); >- return { WTFMove(result) }; >- } >- } >- }); >- if (effectfulSuffix) >- return effectfulSuffix; > >- effectfulSuffix = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() { >- return parseCallExpression(); >- }); >- if (effectfulSuffix) >- return effectfulSuffix; >- >- effectfulSuffix = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> { >- auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >- if (!leftParenthesis) >- return Unexpected<Error>(leftParenthesis.error()); >- >- auto expression = parseExpression(); >- if (!expression) >- return Unexpected<Error>(expression.error()); >- >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >- >- return { WTFMove(*expression) }; >- }); >- if (effectfulSuffix) >- return effectfulSuffix; >- >- return Unexpected<Error>(effectfulSuffix.error()); >+ return expression; > } > > auto Parser::parseLimitedSuffixOperator(UniqueRef<AST::Expression>&& previous) -> SuffixExpression >@@ -1979,21 +1422,14 @@ auto Parser::parseSuffixOperator(UniqueRef<AST::Expression>&& previous) -> Suffi > > auto Parser::parseExpression() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto origin = peek(); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto first = parsePossibleTernaryConditional(); >- if (!first) >- return Unexpected<Error>(first.error()); >+ PEEK(origin); > >+ PARSE(first, PossibleTernaryConditional); > Vector<UniqueRef<AST::Expression>> expressions; > expressions.append(WTFMove(*first)); > > while (tryType(Lexer::Token::Type::Comma)) { >- auto expression = parsePossibleTernaryConditional(); >- if (!expression) >- return Unexpected<Error>(expression.error()); >+ PARSE(expression, PossibleTernaryConditional); > expressions.append(WTFMove(*expression)); > } > >@@ -2004,46 +1440,37 @@ auto Parser::parseExpression() -> Expected<UniqueRef<AST::Expression>, Error> > > auto Parser::parseTernaryConditional() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto origin = peek(); >- if (!origin) >- return Unexpected<Error>(origin.error()); >- >- auto predicate = parsePossibleLogicalBinaryOperation(); >- if (!predicate) >- return Unexpected<Error>(predicate.error()); >- >- auto questionMark = consumeType(Lexer::Token::Type::QuestionMark); >- if (!questionMark) >- return Unexpected<Error>(questionMark.error()); >+ PEEK(origin); > >- auto bodyExpression = parseExpression(); >- if (!bodyExpression) >- return Unexpected<Error>(bodyExpression.error()); >+ PARSE(predicate, PossibleLogicalBinaryOperation); > >- auto colon = consumeType(Lexer::Token::Type::Colon); >- if (!colon) >- return Unexpected<Error>(colon.error()); >+ return completeTernaryConditional(WTFMove(*origin), WTFMove(*predicate)); >+} > >- auto elseExpression = parsePossibleTernaryConditional(); >- if (!elseExpression) >- return Unexpected<Error>(elseExpression.error()); >+auto Parser::completeTernaryConditional(Lexer::Token&& origin, UniqueRef<AST::Expression>&& predicate) -> Expected<UniqueRef<AST::Expression>, Error> >+{ >+ CONSUME_TYPE(questionMark, QuestionMark); >+ PARSE(bodyExpression, Expression); >+ CONSUME_TYPE(colon, Colon); >+ PARSE(elseExpression, PossibleTernaryConditional); > > Vector<UniqueRef<AST::Expression>> castArguments; >- castArguments.append(WTFMove(*predicate)); >- auto boolCast = makeUniqueRef<AST::CallExpression>(Lexer::Token(*origin), "bool"_str, WTFMove(castArguments)); >- return { makeUniqueRef<AST::TernaryExpression>(WTFMove(*origin), WTFMove(boolCast), WTFMove(*bodyExpression), WTFMove(*elseExpression)) }; >+ castArguments.append(WTFMove(predicate)); >+ auto boolCast = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), "bool"_str, WTFMove(castArguments)); >+ return { makeUniqueRef<AST::TernaryExpression>(WTFMove(origin), WTFMove(boolCast), WTFMove(*bodyExpression), WTFMove(*elseExpression)) }; > } > > auto Parser::parseAssignment() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto origin = peek(); >- if (!origin) >- return Unexpected<Error>(origin.error()); >+ PEEK(origin); > >- auto left = parsePossiblePrefix(); >- if (!left) >- return Unexpected<Error>(left.error()); >+ PARSE(left, PossiblePrefix); >+ >+ return completeAssignment(WTFMove(*origin), WTFMove(*left)); >+} > >+auto Parser::completeAssignment(Lexer::Token&& origin, UniqueRef<AST::Expression>&& left) -> Expected<UniqueRef<AST::Expression>, Error> >+{ > auto assignmentOperator = consumeTypes({ > Lexer::Token::Type::EqualsSign, > Lexer::Token::Type::PlusEquals, >@@ -2060,12 +1487,10 @@ auto Parser::parseAssignment() -> Expected<UniqueRef<AST::Expression>, Error> > if (!assignmentOperator) > return Unexpected<Error>(assignmentOperator.error()); > >- auto right = parsePossibleTernaryConditional(); >- if (!right) >- return Unexpected<Error>(right.error()); >+ PARSE(right, PossibleTernaryConditional); > > if (assignmentOperator->type == Lexer::Token::Type::EqualsSign) >- return { makeUniqueRef<AST::AssignmentExpression>(WTFMove(*origin), WTFMove(*left), WTFMove(*right))}; >+ return { makeUniqueRef<AST::AssignmentExpression>(WTFMove(origin), WTFMove(left), WTFMove(*right))}; > > String name; > switch (assignmentOperator->type) { >@@ -2102,45 +1527,55 @@ auto Parser::parseAssignment() -> Expected<UniqueRef<AST::Expression>, Error> > break; > } > >- auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*origin), WTFMove(*left)); >+ auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(origin), WTFMove(left)); > Vector<UniqueRef<AST::Expression>> callArguments; > callArguments.append(result->oldVariableReference()); > callArguments.append(WTFMove(*right)); >- result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(*origin), WTFMove(name), WTFMove(callArguments))); >+ result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(origin), WTFMove(name), WTFMove(callArguments))); > result->setResultExpression(result->newVariableReference()); > return { WTFMove(result) }; > } > > auto Parser::parsePossibleTernaryConditional() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto ternaryExpression = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() { >- return parseTernaryConditional(); >- }); >- if (ternaryExpression) >- return ternaryExpression; >+ PEEK(origin); > >- auto assignmentExpression = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() { >- return parseAssignment(); >- }); >- if (assignmentExpression) >- return assignmentExpression; >+ PARSE(expression, PossiblePrefix); > >- auto binaryOperation = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() { >- return parsePossibleLogicalBinaryOperation(); >- }); >- if (binaryOperation) >- return binaryOperation; >+ if (tryTypes({Lexer::Token::Type::EqualsSign, >+ Lexer::Token::Type::PlusEquals, >+ Lexer::Token::Type::MinusEquals, >+ Lexer::Token::Type::TimesEquals, >+ Lexer::Token::Type::DivideEquals, >+ Lexer::Token::Type::ModEquals, >+ Lexer::Token::Type::XorEquals, >+ Lexer::Token::Type::AndEquals, >+ Lexer::Token::Type::OrEquals, >+ Lexer::Token::Type::RightShiftEquals, >+ Lexer::Token::Type::LeftShiftEquals})) { >+ return completeAssignment(WTFMove(*origin), WTFMove(*expression)); >+ } > >- return Unexpected<Error>(binaryOperation.error()); >+ expression = completePossibleShift(WTFMove(*expression)); >+ expression = completePossibleMultiply(WTFMove(*expression)); >+ expression = completePossibleAdd(WTFMove(*expression)); >+ expression = completePossibleRelationalBinaryOperation(WTFMove(*expression)); >+ expression = completePossibleLogicalBinaryOperation(WTFMove(*expression)); >+ >+ PEEK(nextToken); >+ if (nextToken->type == Lexer::Token::Type::QuestionMark) >+ return completeTernaryConditional(WTFMove(*origin), WTFMove(*expression)); >+ return expression; > } > > auto Parser::parsePossibleLogicalBinaryOperation() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto parsedPrevious = parsePossibleRelationalBinaryOperation(); >- if (!parsedPrevious) >- return Unexpected<Error>(parsedPrevious.error()); >- UniqueRef<AST::Expression> previous = WTFMove(*parsedPrevious); >+ PARSE(parsedPrevious, PossibleRelationalBinaryOperation); >+ return completePossibleLogicalBinaryOperation(WTFMove(*parsedPrevious)); >+} > >+auto Parser::completePossibleLogicalBinaryOperation(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error> >+{ > while (auto logicalBinaryOperation = tryTypes({ > Lexer::Token::Type::OrOr, > Lexer::Token::Type::AndAnd, >@@ -2148,9 +1583,7 @@ auto Parser::parsePossibleLogicalBinaryOperation() -> Expected<UniqueRef<AST::Ex > Lexer::Token::Type::Xor, > Lexer::Token::Type::And > })) { >- auto next = parsePossibleRelationalBinaryOperation(); >- if (!next) >- return Unexpected<Error>(next.error()); >+ PARSE(next, PossibleRelationalBinaryOperation); > > switch (logicalBinaryOperation->type) { > case Lexer::Token::Type::OrOr: >@@ -2189,11 +1622,12 @@ auto Parser::parsePossibleLogicalBinaryOperation() -> Expected<UniqueRef<AST::Ex > > auto Parser::parsePossibleRelationalBinaryOperation() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto parsedPrevious = parsePossibleShift(); >- if (!parsedPrevious) >- return Unexpected<Error>(parsedPrevious.error()); >- UniqueRef<AST::Expression> previous = WTFMove(*parsedPrevious); >+ PARSE(parsedPrevious, PossibleShift); >+ return completePossibleRelationalBinaryOperation(WTFMove(*parsedPrevious)); >+} > >+auto Parser::completePossibleRelationalBinaryOperation(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error> >+{ > while (auto relationalBinaryOperation = tryTypes({ > Lexer::Token::Type::LessThanSign, > Lexer::Token::Type::GreaterThanSign, >@@ -2202,51 +1636,35 @@ auto Parser::parsePossibleRelationalBinaryOperation() -> Expected<UniqueRef<AST: > Lexer::Token::Type::EqualComparison, > Lexer::Token::Type::NotEqual > })) { >- auto next = parsePossibleShift(); >- if (!next) >- return Unexpected<Error>(next.error()); >+ PARSE(next, PossibleShift); >+ >+ Vector<UniqueRef<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); > > switch (relationalBinaryOperation->type) { > case Lexer::Token::Type::LessThanSign: { >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*relationalBinaryOperation), "operator<"_str, WTFMove(callArguments)); > break; > } > case Lexer::Token::Type::GreaterThanSign: { >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*relationalBinaryOperation), "operator>"_str, WTFMove(callArguments)); > break; > } > case Lexer::Token::Type::LessThanOrEqualTo: { >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*relationalBinaryOperation), "operator<="_str, WTFMove(callArguments)); > break; > } > case Lexer::Token::Type::GreaterThanOrEqualTo: { >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*relationalBinaryOperation), "operator>="_str, WTFMove(callArguments)); > break; > } > case Lexer::Token::Type::EqualComparison: { >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*relationalBinaryOperation), "operator=="_str, WTFMove(callArguments)); > break; > } > default: { > ASSERT(relationalBinaryOperation->type == Lexer::Token::Type::NotEqual); >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(Lexer::Token(*relationalBinaryOperation), "operator=="_str, WTFMove(callArguments)); > previous = makeUniqueRef<AST::LogicalNotExpression>(WTFMove(*relationalBinaryOperation), WTFMove(previous)); > break; >@@ -2259,32 +1677,29 @@ auto Parser::parsePossibleRelationalBinaryOperation() -> Expected<UniqueRef<AST: > > auto Parser::parsePossibleShift() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto parsedPrevious = parsePossibleAdd(); >- if (!parsedPrevious) >- return Unexpected<Error>(parsedPrevious.error()); >- UniqueRef<AST::Expression> previous = WTFMove(*parsedPrevious); >+ PARSE(parsedPrevious, PossibleAdd); >+ return completePossibleShift(WTFMove(*parsedPrevious)); >+} > >+auto Parser::completePossibleShift(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error> >+{ > while (auto shift = tryTypes({ > Lexer::Token::Type::LeftShift, > Lexer::Token::Type::RightShift > })) { >- auto next = parsePossibleAdd(); >- if (!next) >- return Unexpected<Error>(next.error()); >+ PARSE(next, PossibleAdd); >+ >+ Vector<UniqueRef<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); > > switch (shift->type) { > case Lexer::Token::Type::LeftShift: { >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*shift), "operator<<"_str, WTFMove(callArguments)); > break; > } > default: { > ASSERT(shift->type == Lexer::Token::Type::RightShift); >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*shift), "operator>>"_str, WTFMove(callArguments)); > break; > } >@@ -2296,32 +1711,29 @@ auto Parser::parsePossibleShift() -> Expected<UniqueRef<AST::Expression>, Error> > > auto Parser::parsePossibleAdd() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto parsedPrevious = parsePossibleMultiply(); >- if (!parsedPrevious) >- return Unexpected<Error>(parsedPrevious.error()); >- UniqueRef<AST::Expression> previous = WTFMove(*parsedPrevious); >+ PARSE(parsedPrevious, PossibleMultiply); >+ return completePossibleAdd(WTFMove(*parsedPrevious)); >+} > >+auto Parser::completePossibleAdd(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error> >+{ > while (auto add = tryTypes({ > Lexer::Token::Type::Plus, > Lexer::Token::Type::Minus > })) { >- auto next = parsePossibleMultiply(); >- if (!next) >- return Unexpected<Error>(next.error()); >+ PARSE(next, PossibleMultiply); >+ >+ Vector<UniqueRef<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); > > switch (add->type) { > case Lexer::Token::Type::Plus: { >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*add), "operator+"_str, WTFMove(callArguments)); > break; > } > default: { > ASSERT(add->type == Lexer::Token::Type::Minus); >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*add), "operator-"_str, WTFMove(callArguments)); > break; > } >@@ -2333,40 +1745,34 @@ auto Parser::parsePossibleAdd() -> Expected<UniqueRef<AST::Expression>, Error> > > auto Parser::parsePossibleMultiply() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto parsedPrevious = parsePossiblePrefix(); >- if (!parsedPrevious) >- return Unexpected<Error>(parsedPrevious.error()); >- UniqueRef<AST::Expression> previous = WTFMove(*parsedPrevious); >+ PARSE(parsedPrevious, PossiblePrefix); >+ return completePossibleMultiply(WTFMove(*parsedPrevious)); >+} > >+auto Parser::completePossibleMultiply(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error> >+{ > while (auto multiply = tryTypes({ > Lexer::Token::Type::Star, > Lexer::Token::Type::Divide, > Lexer::Token::Type::Mod > })) { >- auto next = parsePossiblePrefix(); >- if (!next) >- return Unexpected<Error>(next.error()); >+ PARSE(next, PossiblePrefix); >+ >+ Vector<UniqueRef<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); > > switch (multiply->type) { > case Lexer::Token::Type::Star: { >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*multiply), "operator*"_str, WTFMove(callArguments)); > break; > } > case Lexer::Token::Type::Divide: { >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*multiply), "operator/"_str, WTFMove(callArguments)); > break; > } > default: { > ASSERT(multiply->type == Lexer::Token::Type::Mod); >- Vector<UniqueRef<AST::Expression>> callArguments; >- callArguments.append(WTFMove(previous)); >- callArguments.append(WTFMove(*next)); > previous = makeUniqueRef<AST::CallExpression>(WTFMove(*multiply), "operator%"_str, WTFMove(callArguments)); > break; > } >@@ -2376,7 +1782,7 @@ auto Parser::parsePossibleMultiply() -> Expected<UniqueRef<AST::Expression>, Err > return WTFMove(previous); > } > >-auto Parser::parsePossiblePrefix() -> Expected<UniqueRef<AST::Expression>, Error> >+auto Parser::parsePossiblePrefix(bool *isEffectful) -> Expected<UniqueRef<AST::Expression>, Error> > { > if (auto prefix = tryTypes({ > Lexer::Token::Type::PlusPlus, >@@ -2389,12 +1795,12 @@ auto Parser::parsePossiblePrefix() -> Expected<UniqueRef<AST::Expression>, Error > Lexer::Token::Type::At, > Lexer::Token::Type::Star > })) { >- auto next = parsePossiblePrefix(); >- if (!next) >- return Unexpected<Error>(next.error()); >+ PARSE(next, PossiblePrefix); > > switch (prefix->type) { > case Lexer::Token::Type::PlusPlus: { >+ if (isEffectful) >+ *isEffectful = true; > auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*prefix), WTFMove(*next)); > Vector<UniqueRef<AST::Expression>> callArguments; > callArguments.append(result->oldVariableReference()); >@@ -2403,6 +1809,8 @@ auto Parser::parsePossiblePrefix() -> Expected<UniqueRef<AST::Expression>, Error > return { WTFMove(result) }; > } > case Lexer::Token::Type::MinusMinus: { >+ if (isEffectful) >+ *isEffectful = true; > auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*prefix), WTFMove(*next)); > Vector<UniqueRef<AST::Expression>> callArguments; > callArguments.append(result->oldVariableReference()); >@@ -2441,79 +1849,70 @@ auto Parser::parsePossiblePrefix() -> Expected<UniqueRef<AST::Expression>, Error > } > } > >- return parsePossibleSuffix(); >+ return parsePossibleSuffix(isEffectful); > } > >-auto Parser::parsePossibleSuffix() -> Expected<UniqueRef<AST::Expression>, Error> >+auto Parser::parsePossibleSuffix(bool *isEffectful) -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto suffix = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> { >- auto expression = parseCallExpression(); >- if (!expression) >- return Unexpected<Error>(expression.error()); >+ PEEK(token); >+ PEEK_FURTHER(nextToken); > >+ if (token->type == Lexer::Token::Type::Identifier && nextToken->type == Lexer::Token::Type::LeftParenthesis) { >+ PARSE(expression, CallExpression); >+ if (isEffectful) >+ *isEffectful = true; > while (true) { >- auto result = backtrackingScope<SuffixExpression>([&]() -> SuffixExpression { >- return parseLimitedSuffixOperator(WTFMove(*expression)); >- }); >- expression = WTFMove(result.result); >- if (!result) >+ PEEK(suffixToken); >+ if (suffixToken->type != Lexer::Token::Type::FullStop && suffixToken->type != Lexer::Token::Type::Arrow && suffixToken->type != Lexer::Token::Type::LeftSquareBracket) > break; >+ auto result = parseLimitedSuffixOperator(WTFMove(*expression)); >+ expression = WTFMove(result.result); > } > return expression; >- }); >- if (suffix) >- return suffix; >+ } > >- suffix = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> { >- auto expression = parseTerm(); >- if (!expression) >- return Unexpected<Error>(expression.error()); >+ if (token->type == Lexer::Token::Type::LeftParenthesis && isEffectful) >+ *isEffectful = true; > >- while (true) { >- auto result = backtrackingScope<SuffixExpression>([&]() -> SuffixExpression { >- return parseSuffixOperator(WTFMove(*expression)); >- }); >- expression = WTFMove(result.result); >- if (!result) >- break; >+ PARSE(expression, Term); >+ bool isLastSuffixTokenEffectful = false; >+ while (true) { >+ PEEK(suffixToken); >+ if (suffixToken->type != Lexer::Token::Type::FullStop >+ && suffixToken->type != Lexer::Token::Type::Arrow >+ && suffixToken->type != Lexer::Token::Type::LeftSquareBracket >+ && suffixToken->type != Lexer::Token::Type::PlusPlus >+ && suffixToken->type != Lexer::Token::Type::MinusMinus) { >+ break; > } >- return expression; >- }); >- if (suffix) >- return suffix; >- >- return Unexpected<Error>(suffix.error()); >+ isLastSuffixTokenEffectful = suffixToken->type == Lexer::Token::Type::PlusPlus || suffixToken->type == Lexer::Token::Type::MinusMinus; >+ auto result = parseSuffixOperator(WTFMove(*expression)); >+ expression = WTFMove(result.result); >+ } >+ if (isLastSuffixTokenEffectful && isEffectful) >+ *isEffectful = true; >+ return expression; > } > > auto Parser::parseCallExpression() -> Expected<UniqueRef<AST::Expression>, Error> > { >- auto name = consumeType(Lexer::Token::Type::Identifier); >- if (!name) >- return Unexpected<Error>(name.error()); >+ CONSUME_TYPE(name, Identifier); > auto callName = name->stringView.toString(); > >- auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >- if (!leftParenthesis) >- return Unexpected<Error>(leftParenthesis.error()); >+ CONSUME_TYPE(leftParenthesis, LeftParenthesis); > > Vector<UniqueRef<AST::Expression>> arguments; > if (tryType(Lexer::Token::Type::RightParenthesis)) > return { makeUniqueRef<AST::CallExpression>(WTFMove(*name), WTFMove(callName), WTFMove(arguments)) }; > >- auto firstArgument = parsePossibleTernaryConditional(); >- if (!firstArgument) >- return Unexpected<Error>(firstArgument.error()); >+ PARSE(firstArgument, PossibleTernaryConditional); > arguments.append(WTFMove(*firstArgument)); > while (tryType(Lexer::Token::Type::Comma)) { >- auto argument = parsePossibleTernaryConditional(); >- if (!argument) >- return Unexpected<Error>(argument.error()); >+ PARSE(argument, PossibleTernaryConditional); > arguments.append(WTFMove(*argument)); > } > >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >+ CONSUME_TYPE(rightParenthesis, RightParenthesis); > > return { makeUniqueRef<AST::CallExpression>(WTFMove(*name), WTFMove(callName), WTFMove(arguments)) }; > } >@@ -2564,13 +1963,8 @@ auto Parser::parseTerm() -> Expected<UniqueRef<AST::Expression>, Error> > } > default: { > ASSERT(type->type == Lexer::Token::Type::LeftParenthesis); >- auto expression = parseExpression(); >- if (!expression) >- return Unexpected<Error>(expression.error()); >- >- auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >- if (!rightParenthesis) >- return Unexpected<Error>(rightParenthesis.error()); >+ PARSE(expression, Expression); >+ CONSUME_TYPE(rightParenthesis, RightParenthesis); > > return { WTFMove(*expression) }; > } >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h >index 11ef5cd302e..9f591a293d7 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h >@@ -96,6 +96,7 @@ > #include "WHLSLWhileLoop.h" > #include <wtf/Expected.h> > #include <wtf/Optional.h> >+#include <wtf/PrintStream.h> > > namespace WebCore { > >@@ -115,11 +116,18 @@ public: > } > > String error; >+ >+ void dump(PrintStream& out) const >+ { >+ out.print(error); >+ } > }; > > Optional<Error> parse(Program&, StringView, Mode); > > private: >+ // FIXME: We should not need this >+ // https://bugs.webkit.org/show_bug.cgi?id=198357 > template<typename T> T backtrackingScope(std::function<T()> callback) > { > auto state = m_lexer.state(); >@@ -136,10 +144,12 @@ private: > }; > Unexpected<Error> fail(const String& message, TryToPeek = TryToPeek::Yes); > Expected<Lexer::Token, Error> peek(); >+ Expected<Lexer::Token, Error> peekFurther(); >+ bool peekTypes(const Vector<Lexer::Token::Type>&); > Optional<Lexer::Token> tryType(Lexer::Token::Type); >- Optional<Lexer::Token> tryTypes(Vector<Lexer::Token::Type>); >+ Optional<Lexer::Token> tryTypes(const Vector<Lexer::Token::Type>&); > Expected<Lexer::Token, Error> consumeType(Lexer::Token::Type); >- Expected<Lexer::Token, Error> consumeTypes(Vector<Lexer::Token::Type>); >+ Expected<Lexer::Token, Error> consumeTypes(const Vector<Lexer::Token::Type>&); > > Expected<Variant<int, unsigned>, Error> consumeIntegralLiteral(); > Expected<unsigned, Error> consumeNonNegativeIntegralLiteral(); >@@ -165,7 +175,7 @@ private: > Expected<AST::ResourceSemantic, Error> parseResourceSemantic(); > Expected<AST::SpecializationConstantSemantic, Error> parseSpecializationConstantSemantic(); > Expected<AST::StageInOutSemantic, Error> parseStageInOutSemantic(); >- Expected<AST::Semantic, Error> parseSemantic(); >+ Expected<Optional<AST::Semantic>, Error> parseSemantic(); > AST::Qualifiers parseQualifiers(); > Expected<AST::StructureElement, Error> parseStructureElement(); > Expected<AST::StructureDefinition, Error> parseStructureDefinition(); >@@ -176,7 +186,8 @@ private: > Expected<AST::AttributeBlock, Error> parseAttributeBlock(); > Expected<AST::VariableDeclaration, Error> parseParameter(); > Expected<AST::VariableDeclarations, Error> parseParameters(); >- Expected<AST::FunctionDeclaration, Error> parseEntryPointFunctionDeclaration(); >+ Expected<AST::FunctionDeclaration, Error> parseComputeFunctionDeclaration(); >+ Expected<AST::FunctionDeclaration, Error> parseVertexOrFragmentFunctionDeclaration(); > Expected<AST::FunctionDeclaration, Error> parseRegularFunctionDeclaration(); > Expected<AST::FunctionDeclaration, Error> parseOperatorFunctionDeclaration(); > Expected<AST::FunctionDeclaration, Error> parseFunctionDeclaration(); >@@ -184,7 +195,7 @@ private: > Expected<AST::NativeFunctionDeclaration, Error> parseNativeFunctionDeclaration(); > > Expected<AST::Block, Error> parseBlock(); >- AST::Block parseBlockBody(Lexer::Token&& origin); >+ Expected<AST::Block, Error> parseBlockBody(Lexer::Token&& origin); > Expected<AST::IfStatement, Error> parseIfStatement(); > Expected<AST::SwitchStatement, Error> parseSwitchStatement(); > Expected<AST::SwitchCase, Error> parseSwitchCase(); >@@ -197,8 +208,6 @@ private: > > Expected<UniqueRef<AST::Expression>, Error> parseEffectfulExpression(); > Expected<UniqueRef<AST::Expression>, Error> parseEffectfulAssignment(); >- Expected<UniqueRef<AST::Expression>, Error> parseEffectfulPrefix(); >- Expected<UniqueRef<AST::Expression>, Error> parseEffectfulSuffix(); > struct SuffixExpression { > SuffixExpression(UniqueRef<AST::Expression>&& result, bool success) > : result(WTFMove(result)) >@@ -215,15 +224,22 @@ private: > > Expected<UniqueRef<AST::Expression>, Error> parseExpression(); > Expected<UniqueRef<AST::Expression>, Error> parseTernaryConditional(); >+ Expected<UniqueRef<AST::Expression>, Error> completeTernaryConditional(Lexer::Token&& origin, UniqueRef<AST::Expression>&& predicate); > Expected<UniqueRef<AST::Expression>, Error> parseAssignment(); >+ Expected<UniqueRef<AST::Expression>, Error> completeAssignment(Lexer::Token&& origin, UniqueRef<AST::Expression>&& left); > Expected<UniqueRef<AST::Expression>, Error> parsePossibleTernaryConditional(); > Expected<UniqueRef<AST::Expression>, Error> parsePossibleLogicalBinaryOperation(); >+ Expected<UniqueRef<AST::Expression>, Error> completePossibleLogicalBinaryOperation(UniqueRef<AST::Expression>&& previous); > Expected<UniqueRef<AST::Expression>, Error> parsePossibleRelationalBinaryOperation(); >+ Expected<UniqueRef<AST::Expression>, Error> completePossibleRelationalBinaryOperation(UniqueRef<AST::Expression>&& previous); > Expected<UniqueRef<AST::Expression>, Error> parsePossibleShift(); >+ Expected<UniqueRef<AST::Expression>, Error> completePossibleShift(UniqueRef<AST::Expression>&& previous); > Expected<UniqueRef<AST::Expression>, Error> parsePossibleAdd(); >+ Expected<UniqueRef<AST::Expression>, Error> completePossibleAdd(UniqueRef<AST::Expression>&& previous); > Expected<UniqueRef<AST::Expression>, Error> parsePossibleMultiply(); >- Expected<UniqueRef<AST::Expression>, Error> parsePossiblePrefix(); >- Expected<UniqueRef<AST::Expression>, Error> parsePossibleSuffix(); >+ Expected<UniqueRef<AST::Expression>, Error> completePossibleMultiply(UniqueRef<AST::Expression>&& previous); >+ Expected<UniqueRef<AST::Expression>, Error> parsePossiblePrefix(bool *isEffectful = nullptr); >+ Expected<UniqueRef<AST::Expression>, Error> parsePossibleSuffix(bool *isEffectful = nullptr); > Expected<UniqueRef<AST::Expression>, Error> parseCallExpression(); > Expected<UniqueRef<AST::Expression>, Error> parseTerm(); >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 192890
:
370292
|
370799
|
370805
|
370907
|
370913
|
370971
|
371228
|
371452