WebKit Bugzilla
Attachment 357975 Details for
Bug 192355
: [WHLSL] Add a handwritten parser
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
patch.txt (text/plain), 115.77 KB, created by
Myles C. Maxfield
on 2018-12-21 13:41:01 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Myles C. Maxfield
Created:
2018-12-21 13:41:01 PST
Size:
115.77 KB
patch
obsolete
>commit d4aeeec5a966741da03729fe962bef4e65606776 >Author: Myles C. Maxfield <mmaxfield@apple.com> >Date: Fri Dec 21 13:39:33 2018 -0800 > > Parser > >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 1ce1a8daf8e..63f9fd93546 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,102 @@ >+2018-12-21 Myles C. Maxfield <mmaxfield@apple.com> >+ >+ [WHLSL] Add a handwritten parser >+ https://bugs.webkit.org/show_bug.cgi?id=192355 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ The parser is a mechanical representation of WHLSL's ANTLR grammar at >+ https://github.com/gpuweb/WHLSL/blob/master/Spec/WHLSL.g4. The parser >+ uses Expected<> to return an appropriate Error string when parsing fails. >+ >+ This patch doesn't include the AST nodes themselves - those are in >+ https://bugs.webkit.org/show_bug.cgi?id=192991. I split up the patch to >+ aid easier reviewing. >+ >+ No new tests because the parser isn't hooked up yet. >+ >+ * Modules/webgpu/WHLSL/WHLSLParser.cpp: >+ (WebCore::WHLSL::Parser::Parser): >+ (WebCore::WHLSL::Parser::parse): >+ (WebCore::WHLSL::Parser::fail): >+ (WebCore::WHLSL::Parser::peek): >+ (WebCore::WHLSL::Parser::tryType): >+ (WebCore::WHLSL::Parser::tryTypes): >+ (WebCore::WHLSL::Parser::consumeType): >+ (WebCore::WHLSL::Parser::consumeTypes): >+ (WebCore::WHLSL::digitValue): >+ (WebCore::WHLSL::intLiteralToInt): >+ (WebCore::WHLSL::uintLiteralToUint): >+ (WebCore::WHLSL::floatLiteralToFloat): >+ (WebCore::WHLSL::Parser::consumeIntegralLiteral): >+ (WebCore::WHLSL::Parser::consumeNonNegativeIntegralLiteral): >+ (WebCore::WHLSL::recognizeSimpleUnsignedInteger): >+ (WebCore::WHLSL::Parser::parseConstantExpression): >+ (WebCore::WHLSL::Parser::parseTypeArgument): >+ (WebCore::WHLSL::Parser::parseTypeArguments): >+ (WebCore::WHLSL::Parser::parseTypeSuffixAbbreviated): >+ (WebCore::WHLSL::Parser::parseTypeSuffixNonAbbreviated): >+ (WebCore::WHLSL::Parser::parseAddressSpaceType): >+ (WebCore::WHLSL::Parser::parseNonAddressSpaceType): >+ (WebCore::WHLSL::Parser::parseType): >+ (WebCore::WHLSL::Parser::parseTypeDefinition): >+ (WebCore::WHLSL::Parser::parseBuiltInSemantic): >+ (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::parseEntryPointFunctionDeclaration): >+ (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::parseEffectfulPrefix): >+ (WebCore::WHLSL::Parser::parseEffectfulSuffix): >+ (WebCore::WHLSL::Parser::parseLimitedSuffixOperator): >+ (WebCore::WHLSL::Parser::parseSuffixOperator): >+ (WebCore::WHLSL::Parser::parseExpression): >+ (WebCore::WHLSL::Parser::parseTernaryConditional): >+ (WebCore::WHLSL::Parser::parseAssignment): >+ (WebCore::WHLSL::Parser::parsePossibleTernaryConditional): >+ (WebCore::WHLSL::Parser::parsePossibleLogicalBinaryOperation): >+ (WebCore::WHLSL::Parser::parsePossibleRelationalBinaryOperation): >+ (WebCore::WHLSL::Parser::parsePossibleShift): >+ (WebCore::WHLSL::Parser::parsePossibleAdd): >+ (WebCore::WHLSL::Parser::parsePossibleMultiply): >+ (WebCore::WHLSL::Parser::parsePossiblePrefix): >+ (WebCore::WHLSL::Parser::parsePossibleSuffix): >+ (WebCore::WHLSL::Parser::parseCallExpression): >+ (WebCore::WHLSL::Parser::parseTerm): >+ * Modules/webgpu/WHLSL/WHLSLParser.h: >+ (WebCore::WHLSL::Parser::Error::Error): >+ (WebCore::WHLSL::Parser::backtrackingScope): >+ (WebCore::WHLSL::Parser::SuffixExpression::SuffixExpression): >+ (WebCore::WHLSL::Parser::SuffixExpression::operator bool const): >+ > 2018-12-21 Myles C. Maxfield <mmaxfield@apple.com> > > [WHLSL] Implement parser AST nodes >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp >index 016c692e2d8..bbc9e160e48 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp >@@ -34,6 +34,2485 @@ namespace WebCore { > > namespace WHLSL { > >+Parser::Parser() >+{ >+} >+ >+auto Parser::parse(Program& result, StringView stringView, Mode mode) -> Optional<Error> >+{ >+ m_lexer = Lexer(stringView); >+ m_mode = mode; >+ >+ while (!m_lexer.isFullyConsumed()) { >+ if (tryType(Lexer::Token::Type::Semicolon)) { >+ m_lexer.consumeToken(); >+ continue; >+ } >+ >+ { >+ auto typeDefinition = backtrackingScope<Expected<AST::TypeDefinition, Error>>([&]() { >+ return parseTypeDefinition(); >+ }); >+ if (typeDefinition) { >+ result.append(WTFMove(*typeDefinition)); >+ continue; >+ } >+ } >+ >+ { >+ auto structureDefinition = backtrackingScope<Expected<AST::StructureDefinition, Error>>([&]() { >+ return parseStructureDefinition(); >+ }); >+ if (structureDefinition) { >+ result.append(WTFMove(*structureDefinition)); >+ continue; >+ } >+ } >+ >+ { >+ auto enumerationDefinition = backtrackingScope<Expected<AST::EnumerationDefinition, Error>>([&]() { >+ return parseEnumerationDefinition(); >+ }); >+ if (enumerationDefinition) { >+ result.append(WTFMove(*enumerationDefinition)); >+ continue; >+ } >+ } >+ >+ Optional<Error> error; >+ { >+ auto functionDefinition = backtrackingScope<Expected<AST::FunctionDefinition, Error>>([&]() { >+ return parseFunctionDefinition(); >+ }); >+ if (functionDefinition) { >+ result.append(WTFMove(*functionDefinition)); >+ continue; >+ } >+ error = functionDefinition.error(); >+ } >+ >+ if (m_mode == Mode::StandardLibrary) { >+ auto nativeFunctionDeclaration = backtrackingScope<Expected<AST::NativeFunctionDeclaration, Error>>([&]() { >+ return parseNativeFunctionDeclaration(); >+ }); >+ if (nativeFunctionDeclaration) { >+ result.append(WTFMove(*nativeFunctionDeclaration)); >+ continue; >+ } >+ } >+ >+ if (m_mode == Mode::StandardLibrary) { >+ auto nativeTypeDeclaration = backtrackingScope<Expected<AST::NativeTypeDeclaration, Error>>([&]() { >+ return parseNativeTypeDeclaration(); >+ }); >+ if (nativeTypeDeclaration) { >+ result.append(WTFMove(*nativeTypeDeclaration)); >+ continue; >+ } >+ } >+ >+ WTFLogAlways("%s", error->error.utf8().data()); >+ return WTFMove(*error); >+ } >+ return WTF::nullopt; >+} >+ >+auto Parser::fail(const String& message) -> Unexpected<Error> { >+ if (auto nextToken = peek()) >+ return Unexpected<Error>(Error(m_lexer.errorString(*nextToken, message))); >+ return Unexpected<Error>(Error(String::format("Cannot lex: %s", message.utf8().data()))); >+} >+ >+auto Parser::peek() -> Expected<Lexer::Token, Error> { >+ if (auto token = m_lexer.consumeToken()) { >+ m_lexer.unconsumeToken(Lexer::Token(*token)); >+ return *token; >+ } >+ return fail(String("Cannot consume token", String::ConstructFromLiteral)); >+} >+ >+Optional<Lexer::Token> Parser::tryType(Lexer::Token::Type type) >+{ >+ if (auto token = m_lexer.consumeToken()) { >+ if (token->type == type) >+ return token; >+ m_lexer.unconsumeToken(Lexer::Token(*token)); >+ } >+ return WTF::nullopt; >+} >+ >+Optional<Lexer::Token> Parser::tryTypes(Vector<Lexer::Token::Type> types) >+{ >+ if (auto token = m_lexer.consumeToken()) { >+ if (std::find(types.begin(), types.end(), token->type) != types.end()) >+ return token; >+ m_lexer.unconsumeToken(Lexer::Token(*token)); >+ } >+ return WTF::nullopt; >+} >+ >+auto Parser::consumeType(Lexer::Token::Type type) -> Expected<Lexer::Token, Error> { >+ if (auto token = m_lexer.consumeToken()) { >+ if (token->type == type) >+ return *token; >+ return fail(String::format("Unexpected token (expected %s got %s)", Lexer::Token::typeName(type), Lexer::Token::typeName(token->type))); >+ } >+ return fail(String::format("Cannot consume token (expected %s)", Lexer::Token::typeName(type))); >+} >+ >+auto Parser::consumeTypes(Vector<Lexer::Token::Type> types) -> Expected<Lexer::Token, Error> { >+ auto buildExpectedString = [&]() -> String { >+ StringBuilder builder; >+ builder.append("["); >+ for (unsigned i = 0; i < types.size(); ++i) { >+ if (i > 0) >+ builder.append(", "); >+ builder.append(Lexer::Token::typeName(types[i])); >+ } >+ builder.append("]"); >+ return builder.toString(); >+ }; >+ >+ if (auto token = m_lexer.consumeToken()) { >+ if (std::find(types.begin(), types.end(), token->type) != types.end()) >+ return *token; >+ return fail(String::format("Unexpected token (expected one of %s got %s)", buildExpectedString().utf8().data(), Lexer::Token::typeName(token->type))); >+ } >+ return fail(String::format("Cannot consume token (expected %s)", buildExpectedString().utf8().data())); >+} >+ >+static int digitValue(UChar character) >+{ >+ if (character >= '0' && character <= '9') >+ return character - '0'; >+ if (character >= 'a' && character <= 'f') >+ return character - 'a' + 10; >+ return character - 'A' + 10; >+} >+ >+static Expected<int, Parser::Error> intLiteralToInt(StringView text) >+{ >+ bool negate = false; >+ if (text.startsWith(String("-", String::ConstructFromLiteral))) { >+ negate = true; >+ text = text.substring(1); >+ } >+ int base = 10; >+ if (text.startsWith(String("0x", String::ConstructFromLiteral))) { >+ text = text.substring(2); >+ base = 16; >+ } >+ >+ int result = 0; >+ for (unsigned i = 0; i < text.length(); ++i) { >+ int digit = digitValue(text[i]); >+ auto previous = result; >+ result = result * base + digit; >+ if (result < previous) // FIXME: overflow on signed integers is undefined >+ return Unexpected<Parser::Error>(Parser::Error(String::format("int literal %s is out of bounds", text.utf8().data()))); >+ } >+ if (negate) >+ result *= -1; >+ // FIXME: This algorithm makes it impossible to represent 0x800000 (the most negative representable value) >+ return { result }; >+} >+ >+static Expected<unsigned, Parser::Error> uintLiteralToUint(StringView text) >+{ >+ unsigned base = 10; >+ if (text.startsWith(String("0x", String::ConstructFromLiteral))) { >+ text = text.substring(2); >+ base = 16; >+ } >+ ASSERT(text.substring(text.length() - 1) == "u"); >+ text = text.substring(0, text.length() - 1); >+ unsigned result = 0; >+ for (unsigned i = 0; i < text.length(); ++i) { >+ unsigned digit = digitValue(text[i]); >+ auto previous = result; >+ result = result * base + digit; >+ if (result < previous) >+ return Unexpected<Parser::Error>(Parser::Error(String::format("uint literal %s is out of bounds", text.utf8().data()))); >+ } >+ return { result }; >+} >+ >+static Expected<float, Parser::Error> floatLiteralToFloat(StringView text) >+{ >+ bool negate = false; >+ if (text.length() > 0 && text[0] == '-') { >+ negate = true; >+ text = text.substring(1); >+ } >+ if (text.length() > 0 && text[text.length() - 1] == 'f') >+ text = text.substring(0, text.length() - 1); >+ float result; >+ unsigned index = 0; >+ for (index = 0; index < text.length() && text[index] != '.'; ++index) { >+ ASSERT(text[index] >= '0' && text[index] <= '9'); >+ result = result * 10 + (text[index] - '0'); >+ } >+ ASSERT(index < text.length()); >+ ASSERT(text[index] == '.'); >+ float decimal = 1.0f / 10.0f; >+ for (++index; index < text.length(); ++index) { >+ ASSERT(text[index] >= '0' && text[index] <= '9'); >+ result += decimal * (text[index] - '0'); >+ decimal /= 10.0f; >+ } >+ if (negate) >+ result *= -1; >+ return result; >+} >+ >+auto Parser::consumeIntegralLiteral() -> Expected<Variant<int, unsigned>, Error> { >+ auto integralLiteralToken = consumeTypes({ Lexer::Token::Type::IntLiteral, Lexer::Token::Type::UintLiteral }); >+ if (!integralLiteralToken) >+ return Unexpected<Error>(integralLiteralToken.error()); >+ >+ switch (integralLiteralToken->type) { >+ case Lexer::Token::Type::IntLiteral: { >+ auto result = intLiteralToInt(integralLiteralToken->stringView); >+ if (result) >+ return {{ *result }}; >+ return Unexpected<Error>(result.error()); >+ } >+ case Lexer::Token::Type::UintLiteral: { >+ auto result = uintLiteralToUint(integralLiteralToken->stringView); >+ if (result) >+ return {{ *result }}; >+ return Unexpected<Error>(result.error()); >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+} >+ >+auto Parser::consumeNonNegativeIntegralLiteral() -> Expected<unsigned, Error> { >+ auto integralLiteral = consumeIntegralLiteral(); >+ if (!integralLiteral) >+ return Unexpected<Error>(integralLiteral.error()); >+ auto result = WTF::visit(WTF::makeVisitor([](int x) -> Optional<unsigned> { >+ if (x < 0) >+ return WTF::nullopt; >+ return x; >+ }, [](unsigned x) -> Optional<unsigned> { >+ return x; >+ }), *integralLiteral); >+ if (result) >+ return *result; >+ return fail(String("int literal is negative", String::ConstructFromLiteral)); >+} >+ >+static Expected<unsigned, Parser::Error> recognizeSimpleUnsignedInteger(StringView stringView) >+{ >+ unsigned result = 0; >+ if (stringView.length() < 1) >+ return Unexpected<Parser::Error>(Parser::Error(String::format("Simple unsigned literal %s is too short", stringView.utf8().data()))); >+ for (unsigned i = 0; i < stringView.length(); ++i) { >+ if (stringView[i] < '0' || stringView[i] > '9') >+ return Unexpected<Parser::Error>(Parser::Error(String::format("Simple unsigned literal %s isn't of the form [0-9]+", stringView.utf8().data()))); >+ auto previous = result; >+ result = result * 10 + (stringView[i] - '0'); >+ if (result < previous) >+ return Unexpected<Parser::Error>(Parser::Error(String::format("Simple unsigned literal %s is out of bounds", stringView.utf8().data()))); >+ } >+ return result; >+} >+ >+auto Parser::parseConstantExpression() -> Expected<AST::ConstantExpression, Error> { >+ auto type = consumeTypes({ >+ Lexer::Token::Type::IntLiteral, >+ Lexer::Token::Type::UintLiteral, >+ Lexer::Token::Type::FloatLiteral, >+ Lexer::Token::Type::Null, >+ Lexer::Token::Type::True, >+ Lexer::Token::Type::False, >+ Lexer::Token::Type::Identifier, >+ }); >+ if (!type) >+ return Unexpected<Error>(type.error()); >+ >+ switch (type->type) { >+ case Lexer::Token::Type::IntLiteral: { >+ auto value = intLiteralToInt(type->stringView); >+ if (!value) >+ return Unexpected<Error>(value.error()); >+ return {{ AST::IntegerLiteral(WTFMove(*type), *value) }}; >+ } >+ case Lexer::Token::Type::UintLiteral: { >+ auto value = uintLiteralToUint(type->stringView); >+ if (!value) >+ return Unexpected<Error>(value.error()); >+ return {{ AST::UnsignedIntegerLiteral(WTFMove(*type), *value) }}; >+ } >+ case Lexer::Token::Type::FloatLiteral: { >+ auto value = floatLiteralToFloat(type->stringView); >+ if (!value) >+ return Unexpected<Error>(value.error()); >+ return {{ AST::FloatLiteral(WTFMove(*type), *value) }}; >+ } >+ case Lexer::Token::Type::Null: >+ return { AST::NullLiteral(WTFMove(*type)) }; >+ case Lexer::Token::Type::True: >+ return { AST::BooleanLiteral(WTFMove(*type), true) }; >+ case Lexer::Token::Type::False: >+ return { AST::BooleanLiteral(WTFMove(*type), false) }; >+ case 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()); >+ return { AST::ConstantExpressionEnumerationMemberReference(WTFMove(*origin), type->stringView.toString(), next->stringView.toString()) }; >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+} >+ >+auto Parser::parseTypeArgument() -> Expected<AST::TypeArgument, Error> { >+ auto constantExpression = backtrackingScope<Expected<AST::ConstantExpression, Error>>([&]() { >+ return parseConstantExpression(); >+ }); >+ if (constantExpression) >+ return AST::TypeArgument(WTFMove(*constantExpression)); >+ auto result = consumeType(Lexer::Token::Type::Identifier); >+ if (!result) >+ return Unexpected<Error>(result.error()); >+ return AST::TypeArgument(result->stringView.toString()); >+} >+ >+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; >+ 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); >+ >+ return AST::TypeArguments(); >+} >+ >+auto Parser::parseTypeSuffixAbbreviated() -> Expected<TypeSuffixAbbreviated, Error> { >+ auto token = consumeTypes({ Lexer::Token::Type::Star, Lexer::Token::Type::SquareBracketPair, Lexer::Token::Type::LeftSquareBracket }); >+ if (!token) >+ return Unexpected<Error>(token.error()); >+ if (token->type == Lexer::Token::Type::LeftSquareBracket) { >+ auto numElements = consumeNonNegativeIntegralLiteral(); >+ if (!numElements) >+ return Unexpected<Error>(numElements.error()); >+ auto rightSquareBracket = consumeType(Lexer::Token::Type::RightSquareBracket); >+ if (!rightSquareBracket) >+ return Unexpected<Error>(rightSquareBracket.error()); >+ return {{ *token, *numElements }}; >+ } >+ return {{ *token, WTF::nullopt }}; >+} >+ >+auto Parser::parseTypeSuffixNonAbbreviated() -> Expected<TypeSuffixNonAbbreviated, Error> { >+ auto token = consumeTypes({ Lexer::Token::Type::Star, Lexer::Token::Type::SquareBracketPair, Lexer::Token::Type::LeftSquareBracket }); >+ if (!token) >+ return Unexpected<Error>(token.error()); >+ if (token->type == Lexer::Token::Type::LeftSquareBracket) { >+ auto numElements = consumeNonNegativeIntegralLiteral(); >+ if (!numElements) >+ return Unexpected<Error>(numElements.error()); >+ auto rightSquareBracket = consumeType(Lexer::Token::Type::RightSquareBracket); >+ if (!rightSquareBracket) >+ return Unexpected<Error>(rightSquareBracket.error()); >+ return {{ *token, WTF::nullopt, *numElements }}; >+ } >+ auto addressSpace = consumeTypes({ Lexer::Token::Type::Constant, Lexer::Token::Type::Device, Lexer::Token::Type::Threadgroup, Lexer::Token::Type::Thread}); >+ if (!addressSpace) >+ return Unexpected<Error>(addressSpace.error()); >+ return {{ *token, { *addressSpace }, WTF::nullopt }}; >+} >+ >+auto Parser::parseAddressSpaceType() -> Expected<std::unique_ptr<AST::Type>, Error> { >+ auto addressSpace = consumeTypes({ Lexer::Token::Type::Constant, Lexer::Token::Type::Device, Lexer::Token::Type::Threadgroup, Lexer::Token::Type::Thread}); >+ if (!addressSpace) >+ return Unexpected<Error>(addressSpace.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 constructTypeFromSuffixAbbreviated = [&](const TypeSuffixAbbreviated& typeSuffixAbbreviated, std::unique_ptr<AST::Type>&& previous) -> std::unique_ptr<AST::Type> { >+ switch (typeSuffixAbbreviated.token.type) { >+ case Lexer::Token::Type::Star: >+ return std::make_unique<AST::PointerType>(Lexer::Token(typeSuffixAbbreviated.token), addressSpace->stringView.toString(), WTFMove(previous)); >+ case Lexer::Token::Type::SquareBracketPair: >+ return std::make_unique<AST::ArrayReferenceType>(Lexer::Token(typeSuffixAbbreviated.token), addressSpace->stringView.toString(), WTFMove(previous)); >+ case Lexer::Token::Type::LeftSquareBracket: >+ return std::make_unique<AST::ArrayType>(Lexer::Token(typeSuffixAbbreviated.token), WTFMove(previous), *typeSuffixAbbreviated.numElements); >+ default: >+ ASSERT_NOT_REACHED(); >+ return nullptr; >+ } >+ }; >+ >+ auto firstTypeSuffixAbbreviated = parseTypeSuffixAbbreviated(); >+ if (!firstTypeSuffixAbbreviated) >+ return Unexpected<Error>(firstTypeSuffixAbbreviated.error()); >+ std::unique_ptr<AST::Type> result = std::make_unique<AST::TypeReference>(Lexer::Token(*addressSpace), name->stringView.toString(), WTFMove(*typeArguments)); >+ result = constructTypeFromSuffixAbbreviated(*firstTypeSuffixAbbreviated, WTFMove(result)); >+ while (true) { >+ auto typeSuffixAbbreviated = backtrackingScope<Expected<TypeSuffixAbbreviated, Error>>([&]() { >+ return parseTypeSuffixAbbreviated(); >+ }); >+ if (!typeSuffixAbbreviated) >+ break; >+ // FIXME: The nesting here might be in the wrong order. >+ result = constructTypeFromSuffixAbbreviated(*typeSuffixAbbreviated, WTFMove(result)); >+ } >+ >+ return WTFMove(result); >+} >+ >+auto Parser::parseNonAddressSpaceType() -> Expected<std::unique_ptr<AST::Type>, 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, std::unique_ptr<AST::Type>&& previous) -> std::unique_ptr<AST::Type> { >+ switch (typeSuffixNonAbbreviated.token.type) { >+ case Lexer::Token::Type::Star: >+ return std::make_unique<AST::PointerType>(Lexer::Token(typeSuffixNonAbbreviated.token), typeSuffixNonAbbreviated.addressSpace->stringView.toString(), WTFMove(previous)); >+ case Lexer::Token::Type::SquareBracketPair: >+ return std::make_unique<AST::ArrayReferenceType>(Lexer::Token(typeSuffixNonAbbreviated.token), typeSuffixNonAbbreviated.addressSpace->stringView.toString(), WTFMove(previous)); >+ case Lexer::Token::Type::LeftSquareBracket: >+ return std::make_unique<AST::ArrayType>(Lexer::Token(typeSuffixNonAbbreviated.token), WTFMove(previous), *typeSuffixNonAbbreviated.numElements); >+ default: >+ ASSERT_NOT_REACHED(); >+ return nullptr; >+ } >+ }; >+ >+ std::unique_ptr<AST::Type> result = std::make_unique<AST::TypeReference>(WTFMove(*origin), name->stringView.toString(), WTFMove(*typeArguments)); >+ while (true) { >+ auto typeSuffixNonAbbreviated = backtrackingScope<Expected<TypeSuffixNonAbbreviated, Error>>([&]() { >+ return parseTypeSuffixNonAbbreviated(); >+ }); >+ if (!typeSuffixNonAbbreviated) >+ break; >+ // FIXME: The nesting here might be in the wrong order. >+ result = constructTypeFromSuffixNonAbbreviated(*typeSuffixNonAbbreviated, WTFMove(result)); >+ } >+ >+ return WTFMove(result); >+} >+ >+auto Parser::parseType() -> Expected<std::unique_ptr<AST::Type>, Error> { >+ auto type = backtrackingScope<Expected<std::unique_ptr<AST::Type>, Error>>([&]() { >+ return parseAddressSpaceType(); >+ }); >+ if (type) >+ return type; >+ >+ type = backtrackingScope<Expected<std::unique_ptr<AST::Type>, 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()); >+ return AST::TypeDefinition(WTFMove(*origin), name->stringView.toString(), WTFMove(*type)); >+} >+ >+auto Parser::parseBuiltInSemantic() -> Expected<AST::BuiltInSemantic, Error> { >+ auto origin = consumeTypes({ >+ Lexer::Token::Type::SVInstanceID, >+ Lexer::Token::Type::SVVertexID, >+ Lexer::Token::Type::PSize, >+ Lexer::Token::Type::SVPosition, >+ Lexer::Token::Type::SVIsFrontFace, >+ Lexer::Token::Type::SVSampleIndex, >+ Lexer::Token::Type::SVInnerCoverage, >+ Lexer::Token::Type::SVTarget, >+ Lexer::Token::Type::SVDepth, >+ Lexer::Token::Type::SVCoverage, >+ Lexer::Token::Type::SVDispatchThreadID, >+ Lexer::Token::Type::SVGroupID, >+ Lexer::Token::Type::SVGroupIndex, >+ Lexer::Token::Type::SVGroupThreadID}); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ switch (origin->type) { >+ case Lexer::Token::Type::SVInstanceID: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVInstanceID); >+ case Lexer::Token::Type::SVVertexID: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVVertexID); >+ case Lexer::Token::Type::PSize: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::PSize); >+ case Lexer::Token::Type::SVPosition: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVPosition); >+ case Lexer::Token::Type::SVIsFrontFace: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVIsFrontFace); >+ case Lexer::Token::Type::SVSampleIndex: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVSampleIndex); >+ case Lexer::Token::Type::SVInnerCoverage: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVInnerCoverage); >+ case Lexer::Token::Type::SVTarget: { >+ auto target = consumeNonNegativeIntegralLiteral(); >+ if (!target) >+ return Unexpected<Error>(target.error()); >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVTarget, *target); >+ } >+ case Lexer::Token::Type::SVDepth: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVDepth); >+ case Lexer::Token::Type::SVCoverage: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVCoverage); >+ case Lexer::Token::Type::SVDispatchThreadID: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVDispatchThreadID); >+ case Lexer::Token::Type::SVGroupID: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVGroupID); >+ case Lexer::Token::Type::SVGroupIndex: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVGroupIndex); >+ case Lexer::Token::Type::SVGroupThreadID: >+ return AST::BuiltInSemantic(WTFMove(*origin), AST::BuiltInSemantic::Variable::SVGroupThreadID); >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+} >+ >+auto Parser::parseResourceSemantic() -> Expected<AST::ResourceSemantic, Error> { >+ auto origin = consumeType(Lexer::Token::Type::Register); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ 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()); >+ if (info->stringView.length() < 2 || (info->stringView[0] != 'u' >+ && info->stringView[0] != 't' >+ && info->stringView[0] != 'b' >+ && info->stringView[0] != 's')) >+ return Unexpected<Error>(Error(String::format("%c is not a known resource type ('u', 't', 'b', or 's')", info->stringView[0]))); >+ >+ AST::ResourceSemantic::Mode mode; >+ switch (info->stringView[0]) { >+ case 'u': >+ mode = AST::ResourceSemantic::Mode::UnorderedAccessView; >+ break; >+ case 't': >+ mode = AST::ResourceSemantic::Mode::Texture; >+ break; >+ case 'b': >+ mode = AST::ResourceSemantic::Mode::Buffer; >+ break; >+ case 's': >+ mode = AST::ResourceSemantic::Mode::Sampler; >+ break; >+ } >+ >+ auto index = recognizeSimpleUnsignedInteger(info->stringView.substring(1)); >+ if (!index) >+ return Unexpected<Error>(index.error()); >+ >+ unsigned space = 0; >+ if (tryType(Lexer::Token::Type::Comma)) { >+ auto spaceToken = consumeType(Lexer::Token::Type::Identifier); >+ if (!spaceToken) >+ return Unexpected<Error>(spaceToken.error()); >+ auto prefix = String("space", String::ConstructFromLiteral); >+ if (!spaceToken->stringView.startsWith(StringView(prefix))) >+ return Unexpected<Error>(Error(String::format("Second argument to resource semantic %s needs be of the form 'space0'", spaceToken->stringView.utf8().data()))); >+ if (spaceToken->stringView.length() <= prefix.length()) >+ return Unexpected<Error>(Error(String::format("Second argument to resource semantic %s needs be of the form 'space0'", spaceToken->stringView.utf8().data()))); >+ auto spaceValue = recognizeSimpleUnsignedInteger(spaceToken->stringView.substring(prefix.length())); >+ if (!spaceValue) >+ return Unexpected<Error>(spaceValue.error()); >+ space = *spaceValue; >+ } >+ >+ auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >+ if (!rightParenthesis) >+ return Unexpected<Error>(rightParenthesis.error()); >+ >+ 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()); >+ 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()); >+ >+ auto index = consumeNonNegativeIntegralLiteral(); >+ if (!index) >+ return Unexpected<Error>(index.error()); >+ >+ auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >+ if (!rightParenthesis) >+ return Unexpected<Error>(rightParenthesis.error()); >+ >+ return AST::StageInOutSemantic(WTFMove(*origin), *index); >+} >+ >+auto Parser::parseSemantic() -> Expected<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)); >+ >+ return Unexpected<Error>(stageInOutSemantic.error()); >+} >+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 if ("sample" == next->stringView) >+ qualifiers.append(AST::Qualifier::Sample); >+ else >+ ASSERT_NOT_REACHED(); >+ } else >+ break; >+ } >+ return qualifiers; >+} >+ >+auto Parser::parseStructureElement() -> Expected<AST::StructureElement, Error> { >+ auto origin = peek(); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ 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()); >+ >+ 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); >+} >+ >+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()); >+ >+ AST::StructureElements structureElements; >+ while (true) { >+ auto structureElement = backtrackingScope<Expected<AST::StructureElement, Error>>([&]() { >+ return parseStructureElement(); >+ }); >+ if (structureElement) >+ structureElements.append(WTFMove(*structureElement)); >+ else >+ break; >+ } >+ >+ 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()); >+ >+ std::unique_ptr<AST::Type> type; >+ if (tryType(Lexer::Token::Type::Colon)) { >+ auto parsedType = parseType(); >+ if (!parsedType) >+ return Unexpected<Error>(parsedType.error()); >+ type = WTFMove(*parsedType); >+ } >+ >+ auto leftCurlyBracket = consumeType(Lexer::Token::Type::LeftCurlyBracket); >+ if (!leftCurlyBracket) >+ return Unexpected<Error>(leftCurlyBracket.error()); >+ >+ auto firstEnumerationMember = parseEnumerationMember(); >+ if (!firstEnumerationMember) >+ return Unexpected<Error>(firstEnumerationMember.error()); >+ >+ Vector<AST::EnumerationMember> members; >+ members.append(WTFMove(*firstEnumerationMember)); >+ >+ while (tryType(Lexer::Token::Type::Comma)) { >+ auto member = parseEnumerationMember(); >+ if (!member) >+ return Unexpected<Error>(member.error()); >+ members.append(WTFMove(*member)); >+ } >+ >+ auto rightCurlyBracket = consumeType(Lexer::Token::Type::RightCurlyBracket); >+ if (!rightCurlyBracket) >+ return Unexpected<Error>(rightCurlyBracket.error()); >+ >+ return AST::EnumerationDefinition(WTFMove(*origin), name->stringView.toString(), WTFMove(type), WTFMove(members)); >+} >+ >+auto Parser::parseEnumerationMember() -> Expected<AST::EnumerationMember, Error> { >+ auto identifier = consumeType(Lexer::Token::Type::Identifier); >+ if (!identifier) >+ return Unexpected<Error>(identifier.error()); >+ auto name = identifier->stringView.toString(); >+ >+ if (tryType(Lexer::Token::Type::EqualsSign)) { >+ auto constantExpression = parseConstantExpression(); >+ if (!constantExpression) >+ return Unexpected<Error>(constantExpression.error()); >+ return AST::EnumerationMember(Lexer::Token(*identifier), WTFMove(name), WTFMove(*constantExpression)); >+ } >+ return AST::EnumerationMember(Lexer::Token(*identifier), WTFMove(name)); >+} >+ >+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()); >+ >+ 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()); >+ >+ auto width = consumeNonNegativeIntegralLiteral(); >+ if (!width) >+ return Unexpected<Error>(width.error()); >+ >+ auto comma = consumeType(Lexer::Token::Type::Comma); >+ if (!comma) >+ return Unexpected<Error>(comma.error()); >+ >+ auto height = consumeNonNegativeIntegralLiteral(); >+ if (!height) >+ return Unexpected<Error>(height.error()); >+ >+ comma = consumeType(Lexer::Token::Type::Comma); >+ if (!comma) >+ return Unexpected<Error>(comma.error()); >+ >+ auto depth = consumeNonNegativeIntegralLiteral(); >+ if (!depth) >+ return Unexpected<Error>(depth.error()); >+ >+ auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >+ if (!rightParenthesis) >+ return Unexpected<Error>(rightParenthesis.error()); >+ >+ 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()); >+ >+ AST::AttributeBlock result; >+ >+ while (true) { >+ auto numThreadsFunctionAttribute = backtrackingScope<Expected<AST::NumThreadsFunctionAttribute, Error>>([&]() { >+ return parseNumThreadsFunctionAttribute(); >+ }); >+ if (numThreadsFunctionAttribute) { >+ result.append(WTFMove(*numThreadsFunctionAttribute)); >+ continue; >+ } >+ >+ break; >+ } >+ >+ auto rightSquareBracket = consumeType(Lexer::Token::Type::RightSquareBracket); >+ if (!rightSquareBracket) >+ return Unexpected<Error>(rightSquareBracket.error()); >+ >+ return WTFMove(result); >+} >+ >+auto Parser::parseParameter() -> Expected<AST::Parameter, Error> { >+ auto origin = peek(); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ AST::Qualifiers qualifiers = parseQualifiers(); >+ >+ auto type = parseType(); >+ if (!type) >+ return Unexpected<Error>(type.error()); >+ >+ Optional<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::Parameter(WTFMove(*origin), WTFMove(qualifiers), WTFMove(*type), WTFMove(name), WTFMove(*semantic)); >+ } >+ >+ return AST::Parameter(WTFMove(*origin), WTFMove(qualifiers), WTFMove(*type), WTFMove(name), WTF::nullopt); >+} >+ >+auto Parser::parseParameters() -> Expected<AST::Parameters, Error> { >+ auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >+ if (!leftParenthesis) >+ return Unexpected<Error>(leftParenthesis.error()); >+ >+ AST::Parameters parameters; >+ if (tryType(Lexer::Token::Type::RightParenthesis)) >+ return WTFMove(parameters); >+ >+ auto firstParameter = parseParameter(); >+ if (!firstParameter) >+ return Unexpected<Error>(firstParameter.error()); >+ parameters.append(WTFMove(*firstParameter)); >+ >+ while (tryType(Lexer::Token::Type::Comma)) { >+ auto parameter = parseParameter(); >+ if (!parameter) >+ return Unexpected<Error>(parameter.error()); >+ parameters.append(WTFMove(*parameter)); >+ } >+ >+ auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >+ if (!rightParenthesis) >+ return Unexpected<Error>(rightParenthesis.error()); >+ >+ return WTFMove(parameters); >+} >+ >+auto Parser::parseFunctionDefinition() -> Expected<AST::FunctionDefinition, Error> { >+ bool restricted = static_cast<bool>(tryType(Lexer::Token::Type::Restricted)); >+ >+ auto functionDeclaration = parseFunctionDeclaration(); >+ if (!functionDeclaration) >+ return Unexpected<Error>(functionDeclaration.error()); >+ >+ auto block = parseBlock(); >+ if (!block) >+ return Unexpected<Error>(block.error()); >+ >+ return AST::FunctionDefinition(WTFMove(*functionDeclaration), WTFMove(*block), restricted); >+} >+ >+auto Parser::parseEntryPointFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error> { >+ auto origin = peek(); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ AST::AttributeBlock attributeBlock; >+ AST::FunctionDeclaration::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::FunctionDeclaration::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::FunctionDeclaration::EntryPointType::Vertex; >+ break; >+ case Lexer::Token::Type::Fragment: >+ entryPointType = AST::FunctionDeclaration::EntryPointType::Fragment; >+ break; >+ default: >+ ASSERT_NOT_REACHED(); >+ entryPointType = AST::FunctionDeclaration::EntryPointType::Vertex; >+ } >+ } >+ >+ auto type = parseType(); >+ if (!type) >+ return Unexpected<Error>(type.error()); >+ >+ auto name = consumeType(Lexer::Token::Type::Identifier); >+ if (!name) >+ return Unexpected<Error>(name.error()); >+ >+ auto parameters = parseParameters(); >+ if (!parameters) >+ return Unexpected<Error>(parameters.error()); >+ >+ 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)); >+ } >+ >+ return AST::FunctionDeclaration(WTFMove(*origin), WTFMove(attributeBlock), entryPointType, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTF::nullopt); >+} >+ >+auto Parser::parseRegularFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error> { >+ auto origin = peek(); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ auto type = parseType(); >+ if (!type) >+ return Unexpected<Error>(type.error()); >+ >+ auto name = consumeTypes({ Lexer::Token::Type::Identifier, Lexer::Token::Type::OperatorName }); >+ if (!name) >+ return Unexpected<Error>(name.error()); >+ >+ auto parameters = parseParameters(); >+ if (!parameters) >+ return Unexpected<Error>(parameters.error()); >+ >+ 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)); >+ } >+ >+ return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTF::nullopt); >+} >+ >+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()); >+ >+ 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), String("Operator Cast", String::ConstructFromLiteral), WTFMove(*parameters), WTFMove(*semantic)); >+ } >+ >+ return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), String("Operator Cast", String::ConstructFromLiteral), WTFMove(*parameters), WTF::nullopt); >+} >+ >+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>>([&]() { >+ return parseOperatorFunctionDeclaration(); >+ }); >+ if (operatorFunctionDeclaration) >+ return WTFMove(*operatorFunctionDeclaration); >+ >+ return Unexpected<Error>(operatorFunctionDeclaration.error()); >+} >+ >+auto Parser::parseNativeFunctionDeclaration() -> Expected<AST::NativeFunctionDeclaration, Error> { >+ Optional<Lexer::Token> origin; >+ >+ bool restricted = false; >+ if (auto restrictedValue = tryType(Lexer::Token::Type::Restricted)) { >+ origin = *restrictedValue; >+ restricted = true; >+ } >+ >+ 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(functionDeclaration->takeOrigin(), functionDeclaration->takeAttributeBlock(), functionDeclaration->takeEntryPointType(), functionDeclaration->takeType(), functionDeclaration->takeName(), functionDeclaration->takeParameters(), functionDeclaration->takeSemantic(), restricted); >+} >+ >+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); >+} >+ >+AST::Block Parser::parseBlockBody(Lexer::Token&& origin) >+{ >+ Vector<std::unique_ptr<AST::Statement>> statements; >+ while (true) { >+ auto statement = backtrackingScope<Expected<std::unique_ptr<AST::Statement>, Error>>([&]() { >+ return parseStatement(); >+ }); >+ if (statement) >+ statements.append(WTFMove(*statement)); >+ else >+ break; >+ } >+ 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()); >+ >+ std::unique_ptr<AST::Statement> elseBody; >+ if (tryType(Lexer::Token::Type::Else)) { >+ auto parsedElseBody = parseStatement(); >+ if (!parsedElseBody) >+ return Unexpected<Error>(parsedElseBody.error()); >+ elseBody = WTFMove(*parsedElseBody); >+ } >+ >+ return AST::IfStatement(WTFMove(*origin), WTFMove(*conditional), WTFMove(*body), WTFMove(elseBody)); >+} >+ >+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()); >+ >+ Vector<AST::SwitchCase> switchCases; >+ while (true) { >+ auto switchCase = backtrackingScope<Expected<AST::SwitchCase, Error>>([&]() { >+ return parseSwitchCase(); >+ }); >+ if (switchCase) >+ switchCases.append(WTFMove(*switchCase)); >+ else >+ break; >+ } >+ >+ auto rightCurlyBracket = consumeType(Lexer::Token::Type::RightCurlyBracket); >+ if (!rightCurlyBracket) >+ return Unexpected<Error>(rightCurlyBracket.error()); >+ >+ return AST::SwitchStatement(WTFMove(*origin), WTFMove(*value), WTFMove(switchCases)); >+} >+ >+auto Parser::parseSwitchCase() -> Expected<AST::SwitchCase, Error> { >+ auto origin = consumeTypes({ Lexer::Token::Type::Case, Lexer::Token::Type::Default }); >+ if (!origin) >+ return Unexpected<Error>(origin.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()); >+ >+ auto block = parseBlockBody(Lexer::Token(*origin)); >+ >+ return AST::SwitchCase(WTFMove(*origin), WTFMove(*value), WTFMove(block)); >+ } >+ case Lexer::Token::Type::Default: { >+ auto origin = consumeType(Lexer::Token::Type::Colon); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ auto block = parseBlockBody(Lexer::Token(*origin)); >+ >+ return AST::SwitchCase(WTFMove(*origin), WTF::nullopt, WTFMove(block)); >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+} >+ >+auto Parser::parseForLoop() -> Expected<AST::ForLoop, Error> { >+ auto origin = consumeType(Lexer::Token::Type::For); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ auto parseRemainder = [&](Variant<AST::VariableDeclarationsStatement, std::unique_ptr<AST::Expression>>&& initialization) -> Expected<AST::ForLoop, Error> { >+ auto semicolon = consumeType(Lexer::Token::Type::Semicolon); >+ if (!semicolon) >+ return Unexpected<Error>(semicolon.error()); >+ >+ auto condition = backtrackingScope<std::unique_ptr<AST::Expression>>([&]() -> std::unique_ptr<AST::Expression> { >+ if (auto expression = parseExpression()) >+ return WTFMove(*expression); >+ return nullptr; >+ }); >+ >+ semicolon = consumeType(Lexer::Token::Type::Semicolon); >+ if (!semicolon) >+ return Unexpected<Error>(semicolon.error()); >+ >+ auto increment = backtrackingScope<std::unique_ptr<AST::Expression>>([&]() -> std::unique_ptr<AST::Expression> { >+ if (auto expression = parseExpression()) >+ return WTFMove(*expression); >+ return nullptr; >+ }); >+ >+ auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >+ if (!rightParenthesis) >+ return Unexpected<Error>(rightParenthesis.error()); >+ >+ auto body = parseStatement(); >+ if (!body) >+ return Unexpected<Error>(body.error()); >+ >+ 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()); >+ >+ 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()); >+ >+ 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()); >+ >+ return AST::DoWhileLoop(WTFMove(*origin), WTFMove(*body), WTFMove(*conditional)); >+} >+ >+auto Parser::parseVariableDeclaration(std::unique_ptr<AST::Type>&& type) -> Expected<AST::VariableDeclaration, Error> { >+ auto origin = peek(); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ 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), nullptr); >+ } >+ >+ 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)); >+ } >+ >+ return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), WTFMove(type), name->stringView.toString(), WTF::nullopt, nullptr); >+} >+ >+auto Parser::parseVariableDeclarations() -> Expected<AST::VariableDeclarationsStatement, Error> { >+ auto origin = peek(); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ auto type = parseType(); >+ if (!type) >+ return Unexpected<Error>(type.error()); >+ >+ auto firstVariableDeclaration = parseVariableDeclaration(std::unique_ptr<AST::Type>((*type)->clone())); >+ if (!firstVariableDeclaration) >+ return Unexpected<Error>(firstVariableDeclaration.error()); >+ >+ Vector<AST::VariableDeclaration> result; >+ result.append(WTFMove(*firstVariableDeclaration)); >+ >+ while (tryType(Lexer::Token::Type::Comma)) { >+ auto variableDeclaration = parseVariableDeclaration(std::unique_ptr<AST::Type>((*type)->clone())); >+ if (!variableDeclaration) >+ return Unexpected<Error>(variableDeclaration.error()); >+ result.append(WTFMove(*variableDeclaration)); >+ } >+ >+ return AST::VariableDeclarationsStatement(WTFMove(*origin), WTFMove(result)); >+} >+ >+auto Parser::parseStatement() -> Expected<std::unique_ptr<AST::Statement>, Error> { >+ { >+ auto block = backtrackingScope<Expected<AST::Block, Error>>([&]() { >+ return parseBlock(); >+ }); >+ if (block) >+ return std::unique_ptr<AST::Statement>(std::make_unique<AST::Block>(WTFMove(*block))); >+ } >+ >+ { >+ auto ifStatement = backtrackingScope<Expected<AST::IfStatement, Error>>([&]() { >+ return parseIfStatement(); >+ }); >+ if (ifStatement) >+ return std::unique_ptr<AST::Statement>(std::make_unique<AST::IfStatement>(WTFMove(*ifStatement))); >+ } >+ >+ { >+ auto switchStatement = backtrackingScope<Expected<AST::SwitchStatement, Error>>([&]() { >+ return parseSwitchStatement(); >+ }); >+ if (switchStatement) >+ return std::unique_ptr<AST::Statement>(std::make_unique<AST::SwitchStatement>(WTFMove(*switchStatement))); >+ } >+ >+ { >+ auto forLoop = backtrackingScope<Expected<AST::ForLoop, Error>>([&]() { >+ return parseForLoop(); >+ }); >+ if (forLoop) >+ return std::unique_ptr<AST::Statement>(std::make_unique<AST::ForLoop>(WTFMove(*forLoop))); >+ } >+ >+ { >+ auto whileLoop = backtrackingScope<Expected<AST::WhileLoop, Error>>([&]() { >+ return parseWhileLoop(); >+ }); >+ if (whileLoop) >+ return std::unique_ptr<AST::Statement>(std::make_unique<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 std::unique_ptr<AST::Statement>(std::make_unique<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 std::unique_ptr<AST::Statement>(std::make_unique<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 std::unique_ptr<AST::Statement>(std::make_unique<AST::Continue>(WTFMove(*continueObject))); >+ } >+ >+ { >+ 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 std::unique_ptr<AST::Statement>(std::make_unique<AST::Fallthrough>(WTFMove(*fallthroughObject))); >+ } >+ >+ { >+ 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 std::unique_ptr<AST::Statement>(std::make_unique<AST::Trap>(WTFMove(*trapObject))); >+ } >+ >+ { >+ 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), nullptr); >+ >+ 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 std::unique_ptr<AST::Statement>(std::make_unique<AST::Return>(WTFMove(*returnObject))); >+ } >+ >+ { >+ 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()); >+ >+ return result; >+ }); >+ if (variableDeclarations) >+ return std::unique_ptr<AST::Statement>(std::make_unique<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations))); >+ } >+ >+ auto effectfulExpression = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() -> Expected<std::unique_ptr<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 std::unique_ptr<AST::Statement>(std::make_unique<AST::EffectfulExpressionStatement>(WTFMove(*effectfulExpression))); >+ >+ return Unexpected<Error>(effectfulExpression.error()); >+} >+ >+auto Parser::parseEffectfulExpression() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto origin = peek(); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ Vector<std::unique_ptr<AST::Expression>> expressions; >+ >+ auto first = backtrackingScope<std::unique_ptr<AST::Expression>>([&]() -> std::unique_ptr<AST::Expression> { >+ auto effectfulExpression = parseEffectfulAssignment(); >+ if (!effectfulExpression) >+ return nullptr; >+ return WTFMove(*effectfulExpression); >+ }); >+ if (!first) >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::CommaExpression>(WTFMove(*origin), WTFMove(expressions))); >+ >+ expressions.append(WTFMove(first)); >+ >+ while (tryType(Lexer::Token::Type::Comma)) { >+ auto expression = parseEffectfulAssignment(); >+ if (!expression) >+ return Unexpected<Error>(expression.error()); >+ expressions.append(WTFMove(*expression)); >+ } >+ >+ if (expressions.size() == 1) >+ return WTFMove(expressions[0]); >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::CommaExpression>(WTFMove(*origin), WTFMove(expressions))); >+} >+ >+auto Parser::parseEffectfulAssignment() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto assignment = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() { >+ return parseAssignment(); >+ }); >+ if (assignment) >+ return assignment; >+ >+ assignment = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() { >+ return parseEffectfulPrefix(); >+ }); >+ if (assignment) >+ return assignment; >+ >+ assignment = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() { >+ return parseCallExpression(); >+ }); >+ if (assignment) >+ return assignment; >+ >+ return Unexpected<Error>(assignment.error()); >+} >+ >+auto Parser::parseEffectfulPrefix() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto prefix = consumeTypes({ Lexer::Token::Type::PlusPlus, Lexer::Token::Type::MinusMinus }); >+ if (!prefix) >+ return Unexpected<Error>(prefix.error()); >+ >+ auto previous = parsePossiblePrefix(); >+ if (!previous) >+ return Unexpected<Error>(previous.error()); >+ >+ switch (prefix->type) { >+ case Lexer::Token::Type::PlusPlus: { >+ auto result = std::make_unique<AST::ReadModifyWriteExpression>(Lexer::Token(*prefix), WTFMove(*previous)); >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(result->oldVariableReference()); >+ result->setNewValueExpression(std::make_unique<AST::CallExpression>(WTFMove(*prefix), String("operator++", String::ConstructFromLiteral), WTFMove(callArguments))); >+ result->setResultExpression(result->newVariableReference()); >+ return std::unique_ptr<AST::Expression>(WTFMove(result)); >+ } >+ case Lexer::Token::Type::MinusMinus: { >+ auto result = std::make_unique<AST::ReadModifyWriteExpression>(Lexer::Token(*prefix), WTFMove(*previous)); >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(result->oldVariableReference()); >+ result->setNewValueExpression(std::make_unique<AST::CallExpression>(WTFMove(*prefix), String("operator--", String::ConstructFromLiteral), WTFMove(callArguments))); >+ result->setResultExpression(result->newVariableReference()); >+ return std::unique_ptr<AST::Expression>(WTFMove(result)); >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+} >+ >+auto Parser::parseEffectfulSuffix() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto effectfulSuffix = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() -> Expected<std::unique_ptr<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 = std::make_unique<AST::ReadModifyWriteExpression>(Lexer::Token(*suffix), WTFMove(*previous)); >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(result->oldVariableReference()); >+ result->setNewValueExpression(std::make_unique<AST::CallExpression>(WTFMove(*suffix), String("operator++", String::ConstructFromLiteral), WTFMove(callArguments))); >+ result->setResultExpression(result->oldVariableReference()); >+ return std::unique_ptr<AST::Expression>(WTFMove(result)); >+ } >+ case Lexer::Token::Type::MinusMinus: { >+ auto result = std::make_unique<AST::ReadModifyWriteExpression>(Lexer::Token(*suffix), WTFMove(*previous)); >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(result->oldVariableReference()); >+ result->setNewValueExpression(std::make_unique<AST::CallExpression>(WTFMove(*suffix), String("operator--", String::ConstructFromLiteral), WTFMove(callArguments))); >+ result->setResultExpression(result->oldVariableReference()); >+ return std::unique_ptr<AST::Expression>(WTFMove(result)); >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+ }); >+ if (effectfulSuffix) >+ return effectfulSuffix; >+ >+ effectfulSuffix = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() { >+ return parseCallExpression(); >+ }); >+ if (effectfulSuffix) >+ return effectfulSuffix; >+ >+ effectfulSuffix = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() -> Expected<std::unique_ptr<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 std::unique_ptr<AST::Expression>(WTFMove(*expression)); >+ }); >+ if (effectfulSuffix) >+ return effectfulSuffix; >+ >+ return Unexpected<Error>(effectfulSuffix.error()); >+} >+ >+auto Parser::parseLimitedSuffixOperator(std::unique_ptr<AST::Expression>&& previous) -> SuffixExpression >+{ >+ auto type = consumeTypes({ Lexer::Token::Type::FullStop, Lexer::Token::Type::Arrow, Lexer::Token::Type::LeftSquareBracket }); >+ if (!type) >+ return SuffixExpression(WTFMove(previous), false); >+ >+ switch (type->type) { >+ case Lexer::Token::Type::FullStop: { >+ auto identifier = consumeType(Lexer::Token::Type::Identifier); >+ if (!identifier) >+ return SuffixExpression(WTFMove(previous), false); >+ return SuffixExpression(std::make_unique<AST::DotExpression>(WTFMove(*type), WTFMove(previous), identifier->stringView.toString()), true); >+ } >+ case Lexer::Token::Type::Arrow: { >+ auto identifier = consumeType(Lexer::Token::Type::Identifier); >+ if (!identifier) >+ return SuffixExpression(WTFMove(previous), false); >+ return SuffixExpression(std::make_unique<AST::DotExpression>(Lexer::Token(*type), std::make_unique<AST::DereferenceExpression>(WTFMove(*type), WTFMove(previous)), identifier->stringView.toString()), true); >+ } >+ case Lexer::Token::Type::LeftSquareBracket: { >+ auto expression = parseExpression(); >+ if (!expression) >+ return SuffixExpression(WTFMove(previous), false); >+ if (!consumeType(Lexer::Token::Type::RightSquareBracket)) >+ return SuffixExpression(WTFMove(previous), false); >+ return SuffixExpression(std::make_unique<AST::IndexExpression>(WTFMove(*type), WTFMove(previous), WTFMove(*expression)), true); >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return SuffixExpression(WTFMove(previous), false); >+ } >+} >+ >+auto Parser::parseSuffixOperator(std::unique_ptr<AST::Expression>&& previous) -> SuffixExpression >+{ >+ auto suffix = consumeTypes({ Lexer::Token::Type::FullStop, Lexer::Token::Type::Arrow, Lexer::Token::Type::LeftSquareBracket, Lexer::Token::Type::PlusPlus, Lexer::Token::Type::MinusMinus }); >+ if (!suffix) >+ return SuffixExpression(WTFMove(previous), false); >+ >+ switch (suffix->type) { >+ case Lexer::Token::Type::FullStop: { >+ auto identifier = consumeType(Lexer::Token::Type::Identifier); >+ if (!identifier) >+ return SuffixExpression(WTFMove(previous), false); >+ return SuffixExpression(std::make_unique<AST::DotExpression>(WTFMove(*suffix), WTFMove(previous), identifier->stringView.toString()), true); >+ } >+ case Lexer::Token::Type::Arrow: { >+ auto identifier = consumeType(Lexer::Token::Type::Identifier); >+ if (!identifier) >+ return SuffixExpression(WTFMove(previous), false); >+ return SuffixExpression(std::make_unique<AST::DotExpression>(Lexer::Token(*suffix), std::make_unique<AST::DereferenceExpression>(WTFMove(*suffix), WTFMove(previous)), identifier->stringView.toString()), true); >+ } >+ case Lexer::Token::Type::LeftSquareBracket: { >+ auto expression = parseExpression(); >+ if (!expression) >+ return SuffixExpression(WTFMove(previous), false); >+ if (!consumeType(Lexer::Token::Type::RightSquareBracket)) >+ return SuffixExpression(WTFMove(previous), false); >+ return SuffixExpression(std::make_unique<AST::IndexExpression>(WTFMove(*suffix), WTFMove(previous), WTFMove(*expression)), true); >+ } >+ case Lexer::Token::Type::PlusPlus: { >+ auto result = std::make_unique<AST::ReadModifyWriteExpression>(Lexer::Token(*suffix), WTFMove(previous)); >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(result->oldVariableReference()); >+ result->setNewValueExpression(std::make_unique<AST::CallExpression>(WTFMove(*suffix), String("operator++", String::ConstructFromLiteral), WTFMove(callArguments))); >+ result->setResultExpression(result->oldVariableReference()); >+ return SuffixExpression(WTFMove(result), true); >+ } >+ case Lexer::Token::Type::MinusMinus: { >+ auto result = std::make_unique<AST::ReadModifyWriteExpression>(Lexer::Token(*suffix), WTFMove(previous)); >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(result->oldVariableReference()); >+ result->setNewValueExpression(std::make_unique<AST::CallExpression>(WTFMove(*suffix), String("operator--", String::ConstructFromLiteral), WTFMove(callArguments))); >+ result->setResultExpression(result->oldVariableReference()); >+ return SuffixExpression(WTFMove(result), true); >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return SuffixExpression(WTFMove(previous), false); >+ } >+} >+ >+auto Parser::parseExpression() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto origin = peek(); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ auto first = parsePossibleTernaryConditional(); >+ if (!first) >+ return Unexpected<Error>(first.error()); >+ >+ Vector<std::unique_ptr<AST::Expression>> expressions; >+ expressions.append(WTFMove(*first)); >+ >+ while (tryType(Lexer::Token::Type::Comma)) { >+ auto expression = parsePossibleTernaryConditional(); >+ if (!expression) >+ return Unexpected<Error>(expression.error()); >+ expressions.append(WTFMove(*expression)); >+ } >+ >+ if (expressions.size() == 1) >+ return WTFMove(expressions[0]); >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::CommaExpression>(WTFMove(*origin), WTFMove(expressions))); >+} >+ >+auto Parser::parseTernaryConditional() -> Expected<std::unique_ptr<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()); >+ >+ auto bodyExpression = parseExpression(); >+ if (!bodyExpression) >+ return Unexpected<Error>(bodyExpression.error()); >+ >+ auto colon = consumeType(Lexer::Token::Type::Colon); >+ if (!colon) >+ return Unexpected<Error>(colon.error()); >+ >+ auto elseExpression = parsePossibleTernaryConditional(); >+ if (!elseExpression) >+ return Unexpected<Error>(elseExpression.error()); >+ >+ // FIXME: Cast the predicate to a bool. >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::TernaryExpression>(WTFMove(*origin), WTFMove(*predicate), WTFMove(*bodyExpression), WTFMove(*elseExpression))); >+} >+ >+auto Parser::parseAssignment() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto origin = peek(); >+ if (!origin) >+ return Unexpected<Error>(origin.error()); >+ >+ auto left = parsePossiblePrefix(); >+ if (!left) >+ return Unexpected<Error>(left.error()); >+ >+ auto assignmentOperator = consumeTypes({ >+ 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 >+ }); >+ if (!assignmentOperator) >+ return Unexpected<Error>(assignmentOperator.error()); >+ >+ auto right = parsePossibleTernaryConditional(); >+ if (!right) >+ return Unexpected<Error>(right.error()); >+ >+ if (assignmentOperator->type == Lexer::Token::Type::EqualsSign) >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::AssignmentExpression>(WTFMove(*origin), WTFMove(*left), WTFMove(*right))); >+ >+ String name; >+ switch (assignmentOperator->type) { >+ case Lexer::Token::Type::PlusEquals: >+ name = String("operator+", String::ConstructFromLiteral); >+ break; >+ case Lexer::Token::Type::MinusEquals: >+ name = String("operator-", String::ConstructFromLiteral); >+ break; >+ case Lexer::Token::Type::TimesEquals: >+ name = String("operator*", String::ConstructFromLiteral); >+ break; >+ case Lexer::Token::Type::DivideEquals: >+ name = String("operator/", String::ConstructFromLiteral); >+ break; >+ case Lexer::Token::Type::ModEquals: >+ name = String("operator%", String::ConstructFromLiteral); >+ break; >+ case Lexer::Token::Type::XorEquals: >+ name = String("operator^", String::ConstructFromLiteral); >+ break; >+ case Lexer::Token::Type::AndEquals: >+ name = String("operator&", String::ConstructFromLiteral); >+ break; >+ case Lexer::Token::Type::OrEquals: >+ name = String("operator|", String::ConstructFromLiteral); >+ break; >+ case Lexer::Token::Type::RightShiftEquals: >+ name = String("operator>>", String::ConstructFromLiteral); >+ break; >+ case Lexer::Token::Type::LeftShiftEquals: >+ name = String("operator<<", String::ConstructFromLiteral); >+ break; >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+ >+ auto result = std::make_unique<AST::ReadModifyWriteExpression>(Lexer::Token(*origin), WTFMove(*left)); >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(result->oldVariableReference()); >+ callArguments.append(WTFMove(*right)); >+ result->setNewValueExpression(std::make_unique<AST::CallExpression>(WTFMove(*origin), WTFMove(name), WTFMove(callArguments))); >+ result->setResultExpression(result->newVariableReference()); >+ return std::unique_ptr<AST::Expression>(WTFMove(result)); >+} >+ >+auto Parser::parsePossibleTernaryConditional() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto ternaryExpression = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() { >+ return parseTernaryConditional(); >+ }); >+ if (ternaryExpression) >+ return ternaryExpression; >+ >+ auto assignmentExpression = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() { >+ return parseAssignment(); >+ }); >+ if (assignmentExpression) >+ return assignmentExpression; >+ >+ auto binaryOperation = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() { >+ return parsePossibleLogicalBinaryOperation(); >+ }); >+ if (binaryOperation) >+ return binaryOperation; >+ >+ return Unexpected<Error>(binaryOperation.error()); >+} >+ >+auto Parser::parsePossibleLogicalBinaryOperation() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ std::unique_ptr<AST::Expression> previous; >+ auto parsedPrevious = parsePossibleRelationalBinaryOperation(); >+ if (!parsedPrevious) >+ return Unexpected<Error>(parsedPrevious.error()); >+ previous = WTFMove(*parsedPrevious); >+ >+ while (auto logicalBinaryOperation = tryTypes({ >+ Lexer::Token::Type::OrOr, >+ Lexer::Token::Type::AndAnd, >+ Lexer::Token::Type::Or, >+ Lexer::Token::Type::Xor, >+ Lexer::Token::Type::And >+ })) { >+ auto next = parsePossibleRelationalBinaryOperation(); >+ if (!next) >+ return Unexpected<Error>(next.error()); >+ >+ switch (logicalBinaryOperation->type) { >+ case Lexer::Token::Type::OrOr: >+ previous = std::make_unique<AST::LogicalExpression>(WTFMove(*logicalBinaryOperation), AST::LogicalExpression::Type::Or, WTFMove(previous), WTFMove(*next)); >+ break; >+ case Lexer::Token::Type::AndAnd: >+ previous = std::make_unique<AST::LogicalExpression>(WTFMove(*logicalBinaryOperation), AST::LogicalExpression::Type::And, WTFMove(previous), WTFMove(*next)); >+ break; >+ case Lexer::Token::Type::Or: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*logicalBinaryOperation), String("operator|", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ case Lexer::Token::Type::Xor: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*logicalBinaryOperation), String("operator^", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ case Lexer::Token::Type::And: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*logicalBinaryOperation), String("operator&", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+ } >+ >+ return WTFMove(previous); >+} >+ >+auto Parser::parsePossibleRelationalBinaryOperation() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ std::unique_ptr<AST::Expression> previous; >+ auto parsedPrevious = parsePossibleShift(); >+ if (!parsedPrevious) >+ return Unexpected<Error>(parsedPrevious.error()); >+ previous = WTFMove(*parsedPrevious); >+ >+ while (auto relationalBinaryOperation = tryTypes({ >+ Lexer::Token::Type::LessThanSign, >+ Lexer::Token::Type::GreaterThanSign, >+ Lexer::Token::Type::LessThanOrEqualTo, >+ Lexer::Token::Type::GreaterThanOrEqualTo, >+ Lexer::Token::Type::EqualComparison, >+ Lexer::Token::Type::NotEqual >+ })) { >+ auto next = parsePossibleShift(); >+ if (!next) >+ return Unexpected<Error>(next.error()); >+ >+ switch (relationalBinaryOperation->type) { >+ case Lexer::Token::Type::LessThanSign: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*relationalBinaryOperation), String("operator<", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ case Lexer::Token::Type::GreaterThanSign: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*relationalBinaryOperation), String("operator>", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ case Lexer::Token::Type::LessThanOrEqualTo: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*relationalBinaryOperation), String("operator<=", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ case Lexer::Token::Type::GreaterThanOrEqualTo: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*relationalBinaryOperation), String("operator>=", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ case Lexer::Token::Type::EqualComparison: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*relationalBinaryOperation), String("operator==", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ case Lexer::Token::Type::NotEqual: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(Lexer::Token(*relationalBinaryOperation), String("operator==", String::ConstructFromLiteral), WTFMove(callArguments)); >+ // FIXME: Cast the argument to a bool >+ previous = std::make_unique<AST::LogicalNotExpression>(WTFMove(*relationalBinaryOperation), WTFMove(previous)); >+ break; >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+ } >+ >+ return WTFMove(previous); >+} >+ >+auto Parser::parsePossibleShift() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ std::unique_ptr<AST::Expression> previous; >+ auto parsedPrevious = parsePossibleAdd(); >+ if (!parsedPrevious) >+ return Unexpected<Error>(parsedPrevious.error()); >+ previous = WTFMove(*parsedPrevious); >+ >+ while (auto shift = tryTypes({ >+ Lexer::Token::Type::LeftShift, >+ Lexer::Token::Type::RightShift >+ })) { >+ auto next = parsePossibleAdd(); >+ if (!next) >+ return Unexpected<Error>(next.error()); >+ >+ switch (shift->type) { >+ case Lexer::Token::Type::LeftShift: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*shift), String("operator<<", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ case Lexer::Token::Type::RightShift: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*shift), String("operator>>", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+ } >+ >+ return WTFMove(previous); >+} >+ >+auto Parser::parsePossibleAdd() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ std::unique_ptr<AST::Expression> previous; >+ auto parsedPrevious = parsePossibleMultiply(); >+ if (!parsedPrevious) >+ return Unexpected<Error>(parsedPrevious.error()); >+ previous = WTFMove(*parsedPrevious); >+ >+ while (auto add = tryTypes({ >+ Lexer::Token::Type::Plus, >+ Lexer::Token::Type::Minus >+ })) { >+ auto next = parsePossibleMultiply(); >+ if (!next) >+ return Unexpected<Error>(next.error()); >+ >+ switch (add->type) { >+ case Lexer::Token::Type::Plus: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*add), String("operator+", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ case Lexer::Token::Type::Minus: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*add), String("operator-", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+ } >+ >+ return WTFMove(previous); >+} >+ >+auto Parser::parsePossibleMultiply() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ std::unique_ptr<AST::Expression> previous; >+ auto parsedPrevious = parsePossiblePrefix(); >+ if (!parsedPrevious) >+ return Unexpected<Error>(parsedPrevious.error()); >+ previous = WTFMove(*parsedPrevious); >+ >+ 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()); >+ >+ switch (multiply->type) { >+ case Lexer::Token::Type::Star: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*multiply), String("operator*", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ case Lexer::Token::Type::Divide: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*multiply), String("operator/", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ case Lexer::Token::Type::Mod: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(previous)); >+ callArguments.append(WTFMove(*next)); >+ previous = std::make_unique<AST::CallExpression>(WTFMove(*multiply), String("operator%", String::ConstructFromLiteral), WTFMove(callArguments)); >+ break; >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+ } >+ >+ return WTFMove(previous); >+} >+ >+auto Parser::parsePossiblePrefix() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ if (auto prefix = tryTypes({ >+ Lexer::Token::Type::PlusPlus, >+ Lexer::Token::Type::MinusMinus, >+ Lexer::Token::Type::Plus, >+ Lexer::Token::Type::Minus, >+ Lexer::Token::Type::Tilde, >+ Lexer::Token::Type::ExclamationPoint, >+ Lexer::Token::Type::And, >+ Lexer::Token::Type::At, >+ Lexer::Token::Type::Star >+ })) { >+ auto next = parsePossiblePrefix(); >+ if (!next) >+ return Unexpected<Error>(next.error()); >+ >+ switch (prefix->type) { >+ case Lexer::Token::Type::PlusPlus: { >+ auto result = std::make_unique<AST::ReadModifyWriteExpression>(Lexer::Token(*prefix), WTFMove(*next)); >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(result->oldVariableReference()); >+ result->setNewValueExpression(std::make_unique<AST::CallExpression>(Lexer::Token(*prefix), String("operator++", String::ConstructFromLiteral), WTFMove(callArguments))); >+ result->setResultExpression(result->newVariableReference()); >+ return std::unique_ptr<AST::Expression>(WTFMove(result)); >+ } >+ case Lexer::Token::Type::MinusMinus: { >+ auto result = std::make_unique<AST::ReadModifyWriteExpression>(Lexer::Token(*prefix), WTFMove(*next)); >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(result->oldVariableReference()); >+ result->setNewValueExpression(std::make_unique<AST::CallExpression>(Lexer::Token(*prefix), String("operator--", String::ConstructFromLiteral), WTFMove(callArguments))); >+ result->setResultExpression(result->newVariableReference()); >+ return std::unique_ptr<AST::Expression>(WTFMove(result)); >+ } >+ case Lexer::Token::Type::Plus: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(*next)); >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::CallExpression>(Lexer::Token(*prefix), String("operator+", String::ConstructFromLiteral), WTFMove(callArguments))); >+ } >+ case Lexer::Token::Type::Minus: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(*next)); >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::CallExpression>(Lexer::Token(*prefix), String("operator-", String::ConstructFromLiteral), WTFMove(callArguments))); >+ } >+ case Lexer::Token::Type::Tilde: { >+ Vector<std::unique_ptr<AST::Expression>> callArguments; >+ callArguments.append(WTFMove(*next)); >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::CallExpression>(Lexer::Token(*prefix), String("operator~", String::ConstructFromLiteral), WTFMove(callArguments))); >+ } >+ case Lexer::Token::Type::ExclamationPoint: >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::LogicalNotExpression>(Lexer::Token(*prefix), WTFMove(*next))); >+ case Lexer::Token::Type::And: >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::MakePointerExpression>(Lexer::Token(*prefix), WTFMove(*next))); >+ case Lexer::Token::Type::At: >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::MakeArrayReferenceExpression>(Lexer::Token(*prefix), WTFMove(*next))); >+ case Lexer::Token::Type::Star: >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::DereferenceExpression>(Lexer::Token(*prefix), WTFMove(*next))); >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+ } >+ >+ return parsePossibleSuffix(); >+} >+ >+auto Parser::parsePossibleSuffix() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto suffix = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto expression = parseCallExpression(); >+ if (!expression) >+ return Unexpected<Error>(expression.error()); >+ >+ while (true) { >+ auto result = backtrackingScope<SuffixExpression>([&]() -> SuffixExpression { >+ return parseLimitedSuffixOperator(WTFMove(*expression)); >+ }); >+ expression = WTFMove(result.result); >+ if (!result) >+ break; >+ } >+ return expression; >+ }); >+ if (suffix) >+ return suffix; >+ >+ suffix = backtrackingScope<Expected<std::unique_ptr<AST::Expression>, Error>>([&]() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto expression = parseTerm(); >+ if (!expression) >+ return Unexpected<Error>(expression.error()); >+ >+ while (true) { >+ auto result = backtrackingScope<SuffixExpression>([&]() -> SuffixExpression { >+ return parseSuffixOperator(WTFMove(*expression)); >+ }); >+ expression = WTFMove(result.result); >+ if (!result) >+ break; >+ } >+ return expression; >+ }); >+ if (suffix) >+ return suffix; >+ >+ return Unexpected<Error>(suffix.error()); >+} >+ >+auto Parser::parseCallExpression() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto name = consumeType(Lexer::Token::Type::Identifier); >+ if (!name) >+ return Unexpected<Error>(name.error()); >+ auto callName = name->stringView.toString(); >+ >+ auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis); >+ if (!leftParenthesis) >+ return Unexpected<Error>(leftParenthesis.error()); >+ >+ Vector<std::unique_ptr<AST::Expression>> arguments; >+ if (tryType(Lexer::Token::Type::RightParenthesis)) >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::CallExpression>(WTFMove(*name), WTFMove(callName), WTFMove(arguments))); >+ >+ auto firstArgument = parsePossibleTernaryConditional(); >+ if (!firstArgument) >+ return Unexpected<Error>(firstArgument.error()); >+ arguments.append(WTFMove(*firstArgument)); >+ while (tryType(Lexer::Token::Type::Comma)) { >+ auto argument = parsePossibleTernaryConditional(); >+ if (!argument) >+ return Unexpected<Error>(argument.error()); >+ arguments.append(WTFMove(*argument)); >+ } >+ >+ auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis); >+ if (!rightParenthesis) >+ return Unexpected<Error>(rightParenthesis.error()); >+ >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::CallExpression>(WTFMove(*name), WTFMove(callName), WTFMove(arguments))); >+} >+ >+auto Parser::parseTerm() -> Expected<std::unique_ptr<AST::Expression>, Error> { >+ auto type = consumeTypes({ >+ Lexer::Token::Type::IntLiteral, >+ Lexer::Token::Type::UintLiteral, >+ Lexer::Token::Type::FloatLiteral, >+ Lexer::Token::Type::Null, >+ Lexer::Token::Type::True, >+ Lexer::Token::Type::False, >+ Lexer::Token::Type::Identifier, >+ Lexer::Token::Type::LeftParenthesis >+ }); >+ if (!type) >+ return Unexpected<Error>(type.error()); >+ >+ switch (type->type) { >+ case Lexer::Token::Type::IntLiteral: { >+ auto value = intLiteralToInt(type->stringView); >+ if (!value) >+ return Unexpected<Error>(value.error()); >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::IntegerLiteral>(WTFMove(*type), *value)); >+ } >+ case Lexer::Token::Type::UintLiteral: { >+ auto value = uintLiteralToUint(type->stringView); >+ if (!value) >+ return Unexpected<Error>(value.error()); >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::UnsignedIntegerLiteral>(WTFMove(*type), *value)); >+ } >+ case Lexer::Token::Type::FloatLiteral: { >+ auto value = floatLiteralToFloat(type->stringView); >+ if (!value) >+ return Unexpected<Error>(value.error()); >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::FloatLiteral>(WTFMove(*type), *value)); >+ } >+ case Lexer::Token::Type::Null: >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::NullLiteral>(WTFMove(*type))); >+ case Lexer::Token::Type::True: >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::BooleanLiteral>(WTFMove(*type), true)); >+ case Lexer::Token::Type::False: >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::BooleanLiteral>(WTFMove(*type), false)); >+ case Lexer::Token::Type::Identifier: { >+ auto name = type->stringView.toString(); >+ return std::unique_ptr<AST::Expression>(std::make_unique<AST::VariableReference>(WTFMove(*type), WTFMove(name))); >+ } >+ case 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()); >+ >+ return std::unique_ptr<AST::Expression>(WTFMove(*expression)); >+ } >+ default: >+ ASSERT_NOT_REACHED(); >+ return Unexpected<Error>(Error(String("Something really bad happened", String::ConstructFromLiteral))); >+ } >+} >+ > } > > } >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h >index 5c57a99a9f6..da3e06b01e4 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h >@@ -105,7 +105,131 @@ namespace WebCore { > namespace WHLSL { > > class Parser { >+public: >+ enum class Mode { >+ StandardLibrary, >+ User >+ }; > >+ struct Error { >+ Error(String&& error) >+ : error(WTFMove(error)) >+ { >+ } >+ >+ String error; >+ }; >+ >+ Parser(); >+ >+ Optional<Error> parse(Program&, StringView, Mode); >+ >+private: >+ template<typename T> T backtrackingScope(std::function<T()> callback) >+ { >+ auto state = m_lexer.state(); >+ auto result = callback(); >+ if (result) >+ return result; >+ m_lexer.setState(WTFMove(state)); >+ return result; >+ } >+ >+ Unexpected<Error> fail(const String& message); >+ Expected<Lexer::Token, Error> peek(); >+ Optional<Lexer::Token> tryType(Lexer::Token::Type); >+ Optional<Lexer::Token> tryTypes(Vector<Lexer::Token::Type>); >+ Expected<Lexer::Token, Error> consumeType(Lexer::Token::Type); >+ Expected<Lexer::Token, Error> consumeTypes(Vector<Lexer::Token::Type>); >+ >+ Expected<Variant<int, unsigned>, Error> consumeIntegralLiteral(); >+ Expected<unsigned, Error> consumeNonNegativeIntegralLiteral(); >+ Expected<AST::ConstantExpression, Error> parseConstantExpression(); >+ Expected<AST::TypeArgument, Error> parseTypeArgument(); >+ Expected<AST::TypeArguments, Error> parseTypeArguments(); >+ struct TypeSuffixAbbreviated { >+ Lexer::Token token; >+ Optional<unsigned> numElements; >+ }; >+ Expected<TypeSuffixAbbreviated, Error> parseTypeSuffixAbbreviated(); >+ struct TypeSuffixNonAbbreviated { >+ Lexer::Token token; >+ Optional<Lexer::Token> addressSpace; >+ Optional<unsigned> numElements; >+ }; >+ Expected<TypeSuffixNonAbbreviated, Error> parseTypeSuffixNonAbbreviated(); >+ Expected<std::unique_ptr<AST::Type>, Error> parseAddressSpaceType(); >+ Expected<std::unique_ptr<AST::Type>, Error> parseNonAddressSpaceType(); >+ Expected<std::unique_ptr<AST::Type>, Error> parseType(); >+ Expected<AST::TypeDefinition, Error> parseTypeDefinition(); >+ Expected<AST::BuiltInSemantic, Error> parseBuiltInSemantic(); >+ Expected<AST::ResourceSemantic, Error> parseResourceSemantic(); >+ Expected<AST::SpecializationConstantSemantic, Error> parseSpecializationConstantSemantic(); >+ Expected<AST::StageInOutSemantic, Error> parseStageInOutSemantic(); >+ Expected<AST::Semantic, Error> parseSemantic(); >+ AST::Qualifiers parseQualifiers(); >+ Expected<AST::StructureElement, Error> parseStructureElement(); >+ Expected<AST::StructureDefinition, Error> parseStructureDefinition(); >+ Expected<AST::EnumerationDefinition, Error> parseEnumerationDefinition(); >+ Expected<AST::EnumerationMember, Error> parseEnumerationMember(); >+ Expected<AST::NativeTypeDeclaration, Error> parseNativeTypeDeclaration(); >+ Expected<AST::NumThreadsFunctionAttribute, Error> parseNumThreadsFunctionAttribute(); >+ Expected<AST::AttributeBlock, Error> parseAttributeBlock(); >+ Expected<AST::Parameter, Error> parseParameter(); >+ Expected<AST::Parameters, Error> parseParameters(); >+ Expected<AST::FunctionDeclaration, Error> parseEntryPointFunctionDeclaration(); >+ Expected<AST::FunctionDeclaration, Error> parseRegularFunctionDeclaration(); >+ Expected<AST::FunctionDeclaration, Error> parseOperatorFunctionDeclaration(); >+ Expected<AST::FunctionDeclaration, Error> parseFunctionDeclaration(); >+ Expected<AST::FunctionDefinition, Error> parseFunctionDefinition(); >+ Expected<AST::NativeFunctionDeclaration, Error> parseNativeFunctionDeclaration(); >+ >+ Expected<AST::Block, Error> parseBlock(); >+ AST::Block parseBlockBody(Lexer::Token&& origin); >+ Expected<AST::IfStatement, Error> parseIfStatement(); >+ Expected<AST::SwitchStatement, Error> parseSwitchStatement(); >+ Expected<AST::SwitchCase, Error> parseSwitchCase(); >+ Expected<AST::ForLoop, Error> parseForLoop(); >+ Expected<AST::WhileLoop, Error> parseWhileLoop(); >+ Expected<AST::DoWhileLoop, Error> parseDoWhileLoop(); >+ Expected<AST::VariableDeclaration, Error> parseVariableDeclaration(std::unique_ptr<AST::Type>&&); >+ Expected<AST::VariableDeclarationsStatement, Error> parseVariableDeclarations(); >+ Expected<std::unique_ptr<AST::Statement>, Error> parseStatement(); >+ >+ Expected<std::unique_ptr<AST::Expression>, Error> parseEffectfulExpression(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parseEffectfulAssignment(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parseEffectfulPrefix(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parseEffectfulSuffix(); >+ struct SuffixExpression { >+ SuffixExpression(std::unique_ptr<AST::Expression>&& result, bool success) >+ : result(WTFMove(result)) >+ , success(success) >+ { >+ } >+ >+ std::unique_ptr<AST::Expression> result; >+ bool success; >+ operator bool() const { return success; } >+ }; >+ SuffixExpression parseLimitedSuffixOperator(std::unique_ptr<AST::Expression>&&); >+ SuffixExpression parseSuffixOperator(std::unique_ptr<AST::Expression>&&); >+ >+ Expected<std::unique_ptr<AST::Expression>, Error> parseExpression(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parseTernaryConditional(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parseAssignment(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parsePossibleTernaryConditional(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parsePossibleLogicalBinaryOperation(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parsePossibleRelationalBinaryOperation(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parsePossibleShift(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parsePossibleAdd(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parsePossibleMultiply(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parsePossiblePrefix(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parsePossibleSuffix(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parseCallExpression(); >+ Expected<std::unique_ptr<AST::Expression>, Error> parseTerm(); >+ >+ Lexer m_lexer; >+ Mode m_mode; > }; > > }
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 192355
:
356468
|
356569
|
356570
|
356585
|
356695
|
356778
|
356863
|
356947
|
357031
|
357035
|
357038
|
357081
|
357103
|
357199
|
357207
|
357225
|
357245
|
357268
|
357277
|
357303
|
357304
|
357361
|
357410
|
357430
|
357458
|
357520
|
357602
|
357749
|
357754
|
357765
|
357869
|
357889
|
357929
|
357932
|
357975
|
358866
|
358880
|
358902
|
359250