Changeset 246135 in webkit


Ignore:
Timestamp:
Jun 5, 2019 5:46:25 PM (5 years ago)
Author:
rmorisset@apple.com
Message:

[WHLSL] Parsing and lexing the standard library is slow
https://bugs.webkit.org/show_bug.cgi?id=192890
<rdar://problem/50746335>

Reviewed by Myles Maxfield.

The main idea is to avoid backtracking by instead peeking at the next token (and occasionally at the one after that).
This implies a few things:

  • We can replace the stack of tokens by a trivial ring buffer of size 2 (holding the next token and the one after, or WTF::nullopt if we are at the end of the file).
  • We now have "completeFooExpression" functions, to avoid having to reparse the prefix of some expression, if we find half-way through what it is.

I also fixed the following parser bug:

which was due to a mistake I made in the grammar

Finally I added two new macros: CONSUME_TYPE and PARSE to eliminate about 500 lines of error propagation boilerplate.

There are still lots of ways of improving the parser and lexer, such as:

  • finishing the conversion of tokens in the lexer, not bothering with allocating string views
  • make two special tokens Invalid and EOF, to remove the overhead of Optional
  • make peekTypes and consumeTypes use templates to avoid constructing a Vector and calling find on it.
  • Turn the entire lexer into a proper automata, not going through the same characters again and again (this is certainly the largest win by far)
  • Remove the last few pieces of backtracking from the parser.

The current patch is already enough to make parsing the full standard library (something like 85k lines) approximately 260ms.
This is still longer than I would like, but nowhere near the bottleneck any longer because of some other parts of the compiler.

  • Modules/webgpu/WHLSL/WHLSLLexer.h:

(WebCore::WHLSL::Lexer::Lexer):
(WebCore::WHLSL::Lexer::consumeToken):
(WebCore::WHLSL::Lexer::peek):
(WebCore::WHLSL::Lexer::peekFurther):
(WebCore::WHLSL::Lexer::state const):
(WebCore::WHLSL::Lexer::setState):
(WebCore::WHLSL::Lexer::unconsumeToken): Deleted.

  • Modules/webgpu/WHLSL/WHLSLParser.cpp:

(WebCore::WHLSL::Parser::parse):
(WebCore::WHLSL::Parser::peek):
(WebCore::WHLSL::Parser::peekTypes):
(WebCore::WHLSL::Parser::tryType):
(WebCore::WHLSL::Parser::tryTypes):
(WebCore::WHLSL::Parser::consumeTypes):
(WebCore::WHLSL::Parser::parseConstantExpression):
(WebCore::WHLSL::Parser::parseTypeArgument):
(WebCore::WHLSL::Parser::parseTypeArguments):
(WebCore::WHLSL::Parser::parseTypeSuffixAbbreviated):
(WebCore::WHLSL::Parser::parseTypeSuffixNonAbbreviated):
(WebCore::WHLSL::Parser::parseType):
(WebCore::WHLSL::Parser::parseTypeDefinition):
(WebCore::WHLSL::Parser::parseResourceSemantic):
(WebCore::WHLSL::Parser::parseSpecializationConstantSemantic):
(WebCore::WHLSL::Parser::parseStageInOutSemantic):
(WebCore::WHLSL::Parser::parseSemantic):
(WebCore::WHLSL::Parser::parseQualifiers):
(WebCore::WHLSL::Parser::parseStructureElement):
(WebCore::WHLSL::Parser::parseStructureDefinition):
(WebCore::WHLSL::Parser::parseEnumerationDefinition):
(WebCore::WHLSL::Parser::parseEnumerationMember):
(WebCore::WHLSL::Parser::parseNativeTypeDeclaration):
(WebCore::WHLSL::Parser::parseNumThreadsFunctionAttribute):
(WebCore::WHLSL::Parser::parseAttributeBlock):
(WebCore::WHLSL::Parser::parseParameter):
(WebCore::WHLSL::Parser::parseParameters):
(WebCore::WHLSL::Parser::parseFunctionDefinition):
(WebCore::WHLSL::Parser::parseComputeFunctionDeclaration):
(WebCore::WHLSL::Parser::parseVertexFragmentFunctionDeclaration):
(WebCore::WHLSL::Parser::parseRegularFunctionDeclaration):
(WebCore::WHLSL::Parser::parseOperatorFunctionDeclaration):
(WebCore::WHLSL::Parser::parseFunctionDeclaration):
(WebCore::WHLSL::Parser::parseNativeFunctionDeclaration):
(WebCore::WHLSL::Parser::parseBlock):
(WebCore::WHLSL::Parser::parseBlockBody):
(WebCore::WHLSL::Parser::parseIfStatement):
(WebCore::WHLSL::Parser::parseSwitchStatement):
(WebCore::WHLSL::Parser::parseSwitchCase):
(WebCore::WHLSL::Parser::parseForLoop):
(WebCore::WHLSL::Parser::parseWhileLoop):
(WebCore::WHLSL::Parser::parseDoWhileLoop):
(WebCore::WHLSL::Parser::parseVariableDeclaration):
(WebCore::WHLSL::Parser::parseVariableDeclarations):
(WebCore::WHLSL::Parser::parseStatement):
(WebCore::WHLSL::Parser::parseEffectfulExpression):
(WebCore::WHLSL::Parser::parseEffectfulAssignment):
(WebCore::WHLSL::Parser::parseExpression):
(WebCore::WHLSL::Parser::parseTernaryConditional): Deleted.
(WebCore::WHLSL::Parser::completeTernaryConditional):
(WebCore::WHLSL::Parser::parseAssignment): Deleted.
(WebCore::WHLSL::Parser::completeAssignment):
(WebCore::WHLSL::Parser::parsePossibleTernaryConditional):
(WebCore::WHLSL::Parser::parsePossibleLogicalBinaryOperation):
(WebCore::WHLSL::Parser::completePossibleLogicalBinaryOperation):
(WebCore::WHLSL::Parser::parsePossibleRelationalBinaryOperation):
(WebCore::WHLSL::Parser::completePossibleRelationalBinaryOperation):
(WebCore::WHLSL::Parser::parsePossibleShift):
(WebCore::WHLSL::Parser::completePossibleShift):
(WebCore::WHLSL::Parser::parsePossibleAdd):
(WebCore::WHLSL::Parser::completePossibleAdd):
(WebCore::WHLSL::Parser::parsePossibleMultiply):
(WebCore::WHLSL::Parser::completePossibleMultiply):
(WebCore::WHLSL::Parser::parsePossiblePrefix):
(WebCore::WHLSL::Parser::parsePossibleSuffix):
(WebCore::WHLSL::Parser::parseCallExpression):
(WebCore::WHLSL::Parser::parseTerm):
(WebCore::WHLSL::Parser::parseAddressSpaceType): Deleted.
(WebCore::WHLSL::Parser::parseNonAddressSpaceType): Deleted.
(WebCore::WHLSL::Parser::parseEntryPointFunctionDeclaration): Deleted.
(WebCore::WHLSL::Parser::parseEffectfulPrefix): Deleted.
(WebCore::WHLSL::Parser::parseEffectfulSuffix): Deleted.

  • Modules/webgpu/WHLSL/WHLSLParser.h:

(WebCore::WHLSL::Parser::Error::dump const):

Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r246131 r246135  
     12019-06-05  Robin Morisset  <rmorisset@apple.com>
     2
     3        [WHLSL] Parsing and lexing the standard library is slow
     4        https://bugs.webkit.org/show_bug.cgi?id=192890
     5        <rdar://problem/50746335>
     6
     7        Reviewed by Myles Maxfield.
     8
     9        The main idea is to avoid backtracking by instead peeking at the next token (and occasionally at the one after that).
     10        This implies a few things:
     11        - We can replace the stack of tokens by a trivial ring buffer of size 2 (holding the next token and the one after, or WTF::nullopt if we are at the end of the file).
     12        - We now have "completeFooExpression" functions, to avoid having to reparse the prefix of some expression, if we find half-way through what it is.
     13
     14        I also fixed the following parser bug:
     15        - https://bugs.webkit.org/show_bug.cgi?id=198305 [WHLSL] Multiple variables with initializers in a declaration statement crashes the compiler
     16            which was due to a mistake I made in the grammar
     17
     18        Finally I added two new macros: CONSUME_TYPE and PARSE to eliminate about 500 lines of error propagation boilerplate.
     19
     20        There are still lots of ways of improving the parser and lexer, such as:
     21        - finishing the conversion of tokens in the lexer, not bothering with allocating string views
     22        - make two special tokens Invalid and EOF, to remove the overhead of Optional
     23        - make peekTypes and consumeTypes use templates to avoid constructing a Vector and calling find on it.
     24        - Turn the entire lexer into a proper automata, not going through the same characters again and again (this is certainly the largest win by far)
     25        - Remove the last few pieces of backtracking from the parser.
     26
     27        The current patch is already enough to make parsing the full standard library (something like 85k lines) approximately 260ms.
     28        This is still longer than I would like, but nowhere near the bottleneck any longer because of some other parts of the compiler.
     29
     30        * Modules/webgpu/WHLSL/WHLSLLexer.h:
     31        (WebCore::WHLSL::Lexer::Lexer):
     32        (WebCore::WHLSL::Lexer::consumeToken):
     33        (WebCore::WHLSL::Lexer::peek):
     34        (WebCore::WHLSL::Lexer::peekFurther):
     35        (WebCore::WHLSL::Lexer::state const):
     36        (WebCore::WHLSL::Lexer::setState):
     37        (WebCore::WHLSL::Lexer::unconsumeToken): Deleted.
     38        * Modules/webgpu/WHLSL/WHLSLParser.cpp:
     39        (WebCore::WHLSL::Parser::parse):
     40        (WebCore::WHLSL::Parser::peek):
     41        (WebCore::WHLSL::Parser::peekTypes):
     42        (WebCore::WHLSL::Parser::tryType):
     43        (WebCore::WHLSL::Parser::tryTypes):
     44        (WebCore::WHLSL::Parser::consumeTypes):
     45        (WebCore::WHLSL::Parser::parseConstantExpression):
     46        (WebCore::WHLSL::Parser::parseTypeArgument):
     47        (WebCore::WHLSL::Parser::parseTypeArguments):
     48        (WebCore::WHLSL::Parser::parseTypeSuffixAbbreviated):
     49        (WebCore::WHLSL::Parser::parseTypeSuffixNonAbbreviated):
     50        (WebCore::WHLSL::Parser::parseType):
     51        (WebCore::WHLSL::Parser::parseTypeDefinition):
     52        (WebCore::WHLSL::Parser::parseResourceSemantic):
     53        (WebCore::WHLSL::Parser::parseSpecializationConstantSemantic):
     54        (WebCore::WHLSL::Parser::parseStageInOutSemantic):
     55        (WebCore::WHLSL::Parser::parseSemantic):
     56        (WebCore::WHLSL::Parser::parseQualifiers):
     57        (WebCore::WHLSL::Parser::parseStructureElement):
     58        (WebCore::WHLSL::Parser::parseStructureDefinition):
     59        (WebCore::WHLSL::Parser::parseEnumerationDefinition):
     60        (WebCore::WHLSL::Parser::parseEnumerationMember):
     61        (WebCore::WHLSL::Parser::parseNativeTypeDeclaration):
     62        (WebCore::WHLSL::Parser::parseNumThreadsFunctionAttribute):
     63        (WebCore::WHLSL::Parser::parseAttributeBlock):
     64        (WebCore::WHLSL::Parser::parseParameter):
     65        (WebCore::WHLSL::Parser::parseParameters):
     66        (WebCore::WHLSL::Parser::parseFunctionDefinition):
     67        (WebCore::WHLSL::Parser::parseComputeFunctionDeclaration):
     68        (WebCore::WHLSL::Parser::parseVertexFragmentFunctionDeclaration):
     69        (WebCore::WHLSL::Parser::parseRegularFunctionDeclaration):
     70        (WebCore::WHLSL::Parser::parseOperatorFunctionDeclaration):
     71        (WebCore::WHLSL::Parser::parseFunctionDeclaration):
     72        (WebCore::WHLSL::Parser::parseNativeFunctionDeclaration):
     73        (WebCore::WHLSL::Parser::parseBlock):
     74        (WebCore::WHLSL::Parser::parseBlockBody):
     75        (WebCore::WHLSL::Parser::parseIfStatement):
     76        (WebCore::WHLSL::Parser::parseSwitchStatement):
     77        (WebCore::WHLSL::Parser::parseSwitchCase):
     78        (WebCore::WHLSL::Parser::parseForLoop):
     79        (WebCore::WHLSL::Parser::parseWhileLoop):
     80        (WebCore::WHLSL::Parser::parseDoWhileLoop):
     81        (WebCore::WHLSL::Parser::parseVariableDeclaration):
     82        (WebCore::WHLSL::Parser::parseVariableDeclarations):
     83        (WebCore::WHLSL::Parser::parseStatement):
     84        (WebCore::WHLSL::Parser::parseEffectfulExpression):
     85        (WebCore::WHLSL::Parser::parseEffectfulAssignment):
     86        (WebCore::WHLSL::Parser::parseExpression):
     87        (WebCore::WHLSL::Parser::parseTernaryConditional): Deleted.
     88        (WebCore::WHLSL::Parser::completeTernaryConditional):
     89        (WebCore::WHLSL::Parser::parseAssignment): Deleted.
     90        (WebCore::WHLSL::Parser::completeAssignment):
     91        (WebCore::WHLSL::Parser::parsePossibleTernaryConditional):
     92        (WebCore::WHLSL::Parser::parsePossibleLogicalBinaryOperation):
     93        (WebCore::WHLSL::Parser::completePossibleLogicalBinaryOperation):
     94        (WebCore::WHLSL::Parser::parsePossibleRelationalBinaryOperation):
     95        (WebCore::WHLSL::Parser::completePossibleRelationalBinaryOperation):
     96        (WebCore::WHLSL::Parser::parsePossibleShift):
     97        (WebCore::WHLSL::Parser::completePossibleShift):
     98        (WebCore::WHLSL::Parser::parsePossibleAdd):
     99        (WebCore::WHLSL::Parser::completePossibleAdd):
     100        (WebCore::WHLSL::Parser::parsePossibleMultiply):
     101        (WebCore::WHLSL::Parser::completePossibleMultiply):
     102        (WebCore::WHLSL::Parser::parsePossiblePrefix):
     103        (WebCore::WHLSL::Parser::parsePossibleSuffix):
     104        (WebCore::WHLSL::Parser::parseCallExpression):
     105        (WebCore::WHLSL::Parser::parseTerm):
     106        (WebCore::WHLSL::Parser::parseAddressSpaceType): Deleted.
     107        (WebCore::WHLSL::Parser::parseNonAddressSpaceType): Deleted.
     108        (WebCore::WHLSL::Parser::parseEntryPointFunctionDeclaration): Deleted.
     109        (WebCore::WHLSL::Parser::parseEffectfulPrefix): Deleted.
     110        (WebCore::WHLSL::Parser::parseEffectfulSuffix): Deleted.
     111        * Modules/webgpu/WHLSL/WHLSLParser.h:
     112        (WebCore::WHLSL::Parser::Error::dump const):
     113
    11142019-06-05  Alex Christensen  <achristensen@webkit.org>
    2115
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLLexer.h

    r246108 r246135  
    4747    {
    4848        skipWhitespaceAndComments();
     49        m_ringBuffer[0] = consumeTokenFromStream();
     50        m_ringBuffer[1] = consumeTokenFromStream();
    4951    }
    5052
     
    178180    Optional<Token> consumeToken()
    179181    {
    180         if (!m_stack.isEmpty())
    181             return m_stack.takeLast();
    182         return consumeTokenFromStream();
    183     }
    184 
    185     void unconsumeToken(Token&& token)
    186     {
    187         m_stack.append(WTFMove(token));
    188     }
    189 
     182        auto result = m_ringBuffer[m_ringBufferIndex];
     183        m_ringBuffer[m_ringBufferIndex] = consumeTokenFromStream();
     184        m_ringBufferIndex = (m_ringBufferIndex + 1) % 2;
     185        return result;
     186    }
     187
     188    Optional<Token> peek()
     189    {
     190        return m_ringBuffer[m_ringBufferIndex];
     191    }
     192
     193    Optional<Token> peekFurther()
     194    {
     195        return m_ringBuffer[(m_ringBufferIndex + 1) % 2];
     196    }
     197
     198    // FIXME: We should not need this
     199    // https://bugs.webkit.org/show_bug.cgi?id=198357
    190200    struct State {
    191         Vector<Token> stack;
     201        Optional<Token> ringBuffer[2];
     202        unsigned ringBufferIndex;
    192203        unsigned offset;
    193204        unsigned lineNumber;
     
    196207    State state() const
    197208    {
    198         return { m_stack, m_offset, m_lineNumber };
     209        State state;
     210        state.ringBuffer[0] = m_ringBuffer[0];
     211        state.ringBuffer[1] = m_ringBuffer[1];
     212        state.ringBufferIndex = m_ringBufferIndex;
     213        state.offset = m_offset;
     214        state.lineNumber = m_lineNumber;
     215        return state;
    199216    }
    200217
    201218    void setState(const State& state)
    202219    {
    203         m_stack = state.stack;
     220        m_ringBuffer[0] = state.ringBuffer[0];
     221        m_ringBuffer[1] = state.ringBuffer[1];
     222        m_ringBufferIndex = state.ringBufferIndex;
    204223        m_offset = state.offset;
    205224        m_lineNumber = state.lineNumber;
     225
    206226    }
    207227
    208228    void setState(State&& state)
    209229    {
    210         m_stack = WTFMove(state.stack);
     230        m_ringBuffer[0] = WTFMove(state.ringBuffer[0]);
     231        m_ringBuffer[1] = WTFMove(state.ringBuffer[1]);
     232        m_ringBufferIndex = WTFMove(state.ringBufferIndex);
    211233        m_offset = WTFMove(state.offset);
    212234        m_lineNumber = WTFMove(state.lineNumber);
     
    254276
    255277    StringView m_stringView;
    256     Vector<Token> m_stack;
     278    Optional<Token> m_ringBuffer[2];
     279    unsigned m_ringBufferIndex { 0 };
    257280    unsigned m_offset { 0 };
    258281    unsigned m_lineNumber { 0 };
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp

    r246121 r246135  
    3939namespace WHLSL {
    4040
     41#define PARSE(name, element, ...) \
     42    auto name = parse##element(__VA_ARGS__); \
     43    if (!name) \
     44        return Unexpected<Error>(name.error());
     45
     46#define CONSUME_TYPE(name, type) \
     47    auto name = consumeType(Lexer::Token::Type::type); \
     48    if (!name) \
     49        return Unexpected<Error>(name.error());
     50
     51#define PEEK(name) \
     52    auto name = peek(); \
     53    if (!name) \
     54        return Unexpected<Error>(name.error());
     55
     56#define PEEK_FURTHER(name) \
     57    auto name = peekFurther(); \
     58    if (!name) \
     59        return Unexpected<Error>(name.error());
     60
    4161// FIXME: https://bugs.webkit.org/show_bug.cgi?id=195682 Return a better error code from this, and report it to JavaScript.
    4262auto Parser::parse(Program& program, StringView stringView, Mode mode) -> Optional<Error>
     
    4666
    4767    while (!m_lexer.isFullyConsumed()) {
    48         if (tryType(Lexer::Token::Type::Semicolon)) {
     68        auto token = m_lexer.peek();
     69        if (!token)
     70            break;
     71        switch (token->type) {
     72        case Lexer::Token::Type::Semicolon:
    4973            m_lexer.consumeToken();
    5074            continue;
    51         }
    52 
    53         {
    54             auto typeDefinition = backtrackingScope<Expected<AST::TypeDefinition, Error>>([&]() {
    55                 return parseTypeDefinition();
    56             });
    57             if (typeDefinition) {
    58                 auto success = program.append(WTFMove(*typeDefinition));
    59                 if (!success)
    60                     return WTF::nullopt;
     75        case Lexer::Token::Type::Typedef: {
     76            auto typeDefinition = parseTypeDefinition();
     77            if (!typeDefinition)
     78                return typeDefinition.error();
     79            program.append(WTFMove(*typeDefinition));
     80            continue;
     81        }
     82        case Lexer::Token::Type::Struct: {
     83            auto structureDefinition = parseStructureDefinition();
     84            if (!structureDefinition)
     85                return structureDefinition.error();
     86            program.append(WTFMove(*structureDefinition));
     87            continue;
     88        }
     89        case Lexer::Token::Type::Enum: {
     90            auto enumerationDefinition = parseEnumerationDefinition();
     91            if (!enumerationDefinition)
     92                return enumerationDefinition.error();
     93            program.append(WTFMove(*enumerationDefinition));
     94            continue;
     95        }
     96        case Lexer::Token::Type::Native: {
     97            ASSERT(m_mode == Mode::StandardLibrary);
     98            auto furtherToken = peekFurther();
     99            if (!furtherToken)
     100                return WTF::nullopt;
     101            if (furtherToken->type == Lexer::Token::Type::Typedef) {
     102                auto nativeTypeDeclaration = parseNativeTypeDeclaration();
     103                if (!nativeTypeDeclaration)
     104                    return nativeTypeDeclaration.error();
     105                program.append(WTFMove(*nativeTypeDeclaration));
    61106                continue;
    62107            }
    63         }
    64 
    65         {
    66             auto structureDefinition = backtrackingScope<Expected<AST::StructureDefinition, Error>>([&]() {
    67                 return parseStructureDefinition();
    68             });
    69             if (structureDefinition) {
    70                 auto success = program.append(WTFMove(*structureDefinition));
    71                 if (!success)
    72                     return WTF::nullopt;
    73                 continue;
    74             }
    75         }
    76 
    77         {
    78             auto enumerationDefinition = backtrackingScope<Expected<AST::EnumerationDefinition, Error>>([&]() {
    79                 return parseEnumerationDefinition();
    80             });
    81             if (enumerationDefinition) {
    82                 auto success = program.append(WTFMove(*enumerationDefinition));
    83                 if (!success)
    84                     return WTF::nullopt;
    85                 continue;
    86             }
    87         }
    88 
    89         Optional<Error> error;
    90         {
    91             auto functionDefinition = backtrackingScope<Expected<AST::FunctionDefinition, Error>>([&]() {
    92                 return parseFunctionDefinition();
    93             });
    94             if (functionDefinition) {
    95                 auto success = program.append(WTFMove(*functionDefinition));
    96                 if (!success)
    97                     return WTF::nullopt;
    98                 continue;
    99             }
    100             error = functionDefinition.error();
    101         }
    102 
    103         if (m_mode == Mode::StandardLibrary) {
    104             auto nativeFunctionDeclaration = backtrackingScope<Expected<AST::NativeFunctionDeclaration, Error>>([&]() {
    105                 return parseNativeFunctionDeclaration();
    106             });
    107             if (nativeFunctionDeclaration) {
    108                 auto success = program.append(WTFMove(*nativeFunctionDeclaration));
    109                 if (!success)
    110                     return WTF::nullopt;
    111                 continue;
    112             }
    113         }
    114 
    115         if (m_mode == Mode::StandardLibrary) {
    116             auto nativeTypeDeclaration = backtrackingScope<Expected<AST::NativeTypeDeclaration, Error>>([&]() {
    117                 return parseNativeTypeDeclaration();
    118             });
    119             if (nativeTypeDeclaration) {
    120                 auto success = program.append(WTFMove(*nativeTypeDeclaration));
    121                 if (!success)
    122                     return WTF::nullopt;
    123                 continue;
    124             }
    125         }
    126 
    127         return WTFMove(*error);
    128     }
     108            auto nativeFunctionDeclaration = parseNativeFunctionDeclaration();
     109            if (!nativeFunctionDeclaration)
     110                return nativeFunctionDeclaration.error();
     111            program.append(WTFMove(*nativeFunctionDeclaration));
     112            continue;
     113        }
     114        default: {
     115            auto functionDefinition = parseFunctionDefinition();
     116            if (!functionDefinition)
     117                return functionDefinition.error();
     118            program.append(WTFMove(*functionDefinition));
     119            continue;
     120        }
     121        }
     122    }
     123
    129124    return WTF::nullopt;
    130125}
     
    141136auto Parser::peek() -> Expected<Lexer::Token, Error>
    142137{
    143     if (auto token = m_lexer.consumeToken()) {
    144         m_lexer.unconsumeToken(Lexer::Token(*token));
     138    if (auto token = m_lexer.peek()) {
    145139        return *token;
    146140    }
     
    148142}
    149143
     144auto Parser::peekFurther() -> Expected<Lexer::Token, Error>
     145{
     146    if (auto token = m_lexer.peekFurther()) {
     147        return *token;
     148    }
     149    return fail("Cannot consume two tokens"_str, TryToPeek::No);
     150}
     151
     152bool Parser::peekTypes(const Vector<Lexer::Token::Type>& types)
     153{
     154    if (auto token = m_lexer.peek())
     155        return std::find(types.begin(), types.end(), token->type) != types.end();
     156    return false;
     157}
     158
    150159Optional<Lexer::Token> Parser::tryType(Lexer::Token::Type type)
    151160{
    152     if (auto token = m_lexer.consumeToken()) {
     161    if (auto token = m_lexer.peek()) {
    153162        if (token->type == type)
    154             return token;
    155         m_lexer.unconsumeToken(Lexer::Token(*token));
     163            return m_lexer.consumeToken();
    156164    }
    157165    return WTF::nullopt;
    158166}
    159167
    160 Optional<Lexer::Token> Parser::tryTypes(Vector<Lexer::Token::Type> types)
    161 {
    162     if (auto token = m_lexer.consumeToken()) {
     168Optional<Lexer::Token> Parser::tryTypes(const Vector<Lexer::Token::Type>& types)
     169{
     170    if (auto token = m_lexer.peek()) {
    163171        if (std::find(types.begin(), types.end(), token->type) != types.end())
    164             return token;
    165         m_lexer.unconsumeToken(Lexer::Token(*token));
     172            return m_lexer.consumeToken();
    166173    }
    167174    return WTF::nullopt;
     
    178185}
    179186
    180 auto Parser::consumeTypes(Vector<Lexer::Token::Type> types) -> Expected<Lexer::Token, Error>
     187auto Parser::consumeTypes(const Vector<Lexer::Token::Type>& types) -> Expected<Lexer::Token, Error>
    181188{
    182189    auto buildExpectedString = [&]() -> String {
     
    368375    default: {
    369376        ASSERT(type->type == Lexer::Token::Type::Identifier);
    370         auto origin = consumeType(Lexer::Token::Type::FullStop);
    371         if (!origin)
    372             return Unexpected<Error>(origin.error());
    373         auto next = consumeType(Lexer::Token::Type::Identifier);
    374         if (!next)
    375             return Unexpected<Error>(next.error());
     377        CONSUME_TYPE(origin, FullStop);
     378        CONSUME_TYPE(next, Identifier);
    376379        return { AST::EnumerationMemberLiteral(WTFMove(*origin), type->stringView.toString(), next->stringView.toString()) };
    377380    }
     
    381384auto Parser::parseTypeArgument() -> Expected<AST::TypeArgument, Error>
    382385{
    383     auto constantExpression = backtrackingScope<Expected<AST::ConstantExpression, Error>>([&]() {
    384         return parseConstantExpression();
    385     });
    386     if (constantExpression)
     386    PEEK(nextToken);
     387    PEEK_FURTHER(furtherToken);
     388    if (nextToken->type != Lexer::Token::Type::Identifier || furtherToken->type == Lexer::Token::Type::FullStop) {
     389        PARSE(constantExpression, ConstantExpression);
    387390        return AST::TypeArgument(WTFMove(*constantExpression));
    388     auto result = consumeType(Lexer::Token::Type::Identifier);
    389     if (!result)
    390         return Unexpected<Error>(result.error());
     391    }
     392    CONSUME_TYPE(result, Identifier);
    391393    return AST::TypeArgument(makeUniqueRef<AST::TypeReference>(Lexer::Token(*result), result->stringView.toString(), AST::TypeArguments()));
    392394}
     
    394396auto Parser::parseTypeArguments() -> Expected<AST::TypeArguments, Error>
    395397{
    396     auto typeArguments = backtrackingScope<Optional<AST::TypeArguments>>([&]() -> Optional<AST::TypeArguments> {
    397         auto lessThanSign = consumeType(Lexer::Token::Type::LessThanSign);
    398         if (!lessThanSign)
    399             return WTF::nullopt;
    400         AST::TypeArguments typeArguments;
    401         auto typeArgument = parseTypeArgument();
    402         if (!typeArgument)
    403             return WTF::nullopt;
     398    AST::TypeArguments typeArguments;
     399    auto lessThanSign = tryType(Lexer::Token::Type::LessThanSign);
     400    if (!lessThanSign)
     401        return typeArguments;
     402
     403    auto greaterThanSign = tryType(Lexer::Token::Type::GreaterThanSign);
     404    if (greaterThanSign)
     405        return typeArguments;
     406
     407    PARSE(typeArgument, TypeArgument);
     408    typeArguments.append(WTFMove(*typeArgument));
     409
     410    while (true) {
     411        auto greaterThanSign = tryType(Lexer::Token::Type::GreaterThanSign);
     412        if (greaterThanSign)
     413            break;
     414
     415        CONSUME_TYPE(comma, Comma);
     416        PARSE(typeArgument, TypeArgument);
    404417        typeArguments.append(WTFMove(*typeArgument));
    405         while (tryType(Lexer::Token::Type::Comma)) {
    406             auto typeArgument = parseTypeArgument();
    407             if (!typeArgument)
    408                 return WTF::nullopt;
    409             typeArguments.append(WTFMove(*typeArgument));
    410         }
    411         auto greaterThanSign = consumeType(Lexer::Token::Type::GreaterThanSign);
    412         if (!greaterThanSign)
    413             return WTF::nullopt;
    414         return typeArguments;
    415     });
    416     if (typeArguments)
    417         return WTFMove(*typeArguments);
    418 
    419     typeArguments = backtrackingScope<Optional<AST::TypeArguments>>([&]() -> Optional<AST::TypeArguments> {
    420         auto lessThanSign = consumeType(Lexer::Token::Type::LessThanSign);
    421         if (!lessThanSign)
    422             return WTF::nullopt;
    423         auto greaterThanSign = consumeType(Lexer::Token::Type::GreaterThanSign);
    424         if (!greaterThanSign)
    425             return WTF::nullopt;
    426         return {{ }};
    427     });
    428     if (typeArguments)
    429         return WTFMove(*typeArguments);
    430 
    431     return AST::TypeArguments();
     418    }
     419
     420    return typeArguments;
    432421}
    433422
     
    441430        if (!numElements)
    442431            return Unexpected<Error>(numElements.error());
    443         auto rightSquareBracket = consumeType(Lexer::Token::Type::RightSquareBracket);
    444         if (!rightSquareBracket)
    445             return Unexpected<Error>(rightSquareBracket.error());
     432        CONSUME_TYPE(rightSquareBracket, RightSquareBracket);
    446433        return {{ *token, *numElements }};
    447434    }
     
    458445        if (!numElements)
    459446            return Unexpected<Error>(numElements.error());
    460         auto rightSquareBracket = consumeType(Lexer::Token::Type::RightSquareBracket);
    461         if (!rightSquareBracket)
    462             return Unexpected<Error>(rightSquareBracket.error());
     447        CONSUME_TYPE(rightSquareBracket, RightSquareBracket);
    463448        return {{ *token, WTF::nullopt, *numElements }};
    464449    }
     
    485470}
    486471
    487 auto Parser::parseAddressSpaceType() -> Expected<UniqueRef<AST::UnnamedType>, Error>
    488 {
    489     auto addressSpaceToken = consumeTypes({ Lexer::Token::Type::Constant, Lexer::Token::Type::Device, Lexer::Token::Type::Threadgroup, Lexer::Token::Type::Thread});
    490     if (!addressSpaceToken)
    491         return Unexpected<Error>(addressSpaceToken.error());
    492     AST::AddressSpace addressSpace;
    493     switch (addressSpaceToken->type) {
    494     case Lexer::Token::Type::Constant:
    495         addressSpace = AST::AddressSpace::Constant;
    496         break;
    497     case Lexer::Token::Type::Device:
    498         addressSpace = AST::AddressSpace::Device;
    499         break;
    500     case Lexer::Token::Type::Threadgroup:
    501         addressSpace = AST::AddressSpace::Threadgroup;
    502         break;
    503     default:
    504         ASSERT(addressSpaceToken->type == Lexer::Token::Type::Thread);
    505         addressSpace = AST::AddressSpace::Thread;
    506         break;
    507     }
    508     auto name = consumeType(Lexer::Token::Type::Identifier);
    509     if (!name)
    510         return Unexpected<Error>(name.error());
    511     auto typeArguments = parseTypeArguments();
    512     if (!typeArguments)
    513         return Unexpected<Error>(typeArguments.error());
    514 
    515     auto constructTypeFromSuffixAbbreviated = [&](const TypeSuffixAbbreviated& typeSuffixAbbreviated, UniqueRef<AST::UnnamedType>&& previous) -> UniqueRef<AST::UnnamedType> {
    516         switch (typeSuffixAbbreviated.token.type) {
    517         case Lexer::Token::Type::Star:
    518             return { makeUniqueRef<AST::PointerType>(Lexer::Token(typeSuffixAbbreviated.token), addressSpace, WTFMove(previous)) };
    519         case Lexer::Token::Type::SquareBracketPair:
    520             return { makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(typeSuffixAbbreviated.token), addressSpace, WTFMove(previous)) };
     472auto Parser::parseType() -> Expected<UniqueRef<AST::UnnamedType>, Error>
     473{
     474    auto addressSpaceToken = tryTypes({ Lexer::Token::Type::Constant, Lexer::Token::Type::Device, Lexer::Token::Type::Threadgroup, Lexer::Token::Type::Thread});
     475
     476    CONSUME_TYPE(name, Identifier);
     477    PARSE(typeArguments, TypeArguments);
     478
     479    if (addressSpaceToken) {
     480        AST::AddressSpace addressSpace;
     481        switch (addressSpaceToken->type) {
     482        case Lexer::Token::Type::Constant:
     483            addressSpace = AST::AddressSpace::Constant;
     484            break;
     485        case Lexer::Token::Type::Device:
     486            addressSpace = AST::AddressSpace::Device;
     487            break;
     488        case Lexer::Token::Type::Threadgroup:
     489            addressSpace = AST::AddressSpace::Threadgroup;
     490            break;
    521491        default:
    522             ASSERT(typeSuffixAbbreviated.token.type == Lexer::Token::Type::LeftSquareBracket);
    523             return { makeUniqueRef<AST::ArrayType>(Lexer::Token(typeSuffixAbbreviated.token), WTFMove(previous), *typeSuffixAbbreviated.numElements) };
    524         }
    525     };
    526 
    527     auto firstTypeSuffixAbbreviated = parseTypeSuffixAbbreviated();
    528     if (!firstTypeSuffixAbbreviated)
    529         return Unexpected<Error>(firstTypeSuffixAbbreviated.error());
    530     UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*addressSpaceToken), name->stringView.toString(), WTFMove(*typeArguments));
    531     auto next = constructTypeFromSuffixAbbreviated(*firstTypeSuffixAbbreviated, WTFMove(result));
    532     result = WTFMove(next);
    533     while (true) {
    534         auto typeSuffixAbbreviated = backtrackingScope<Expected<TypeSuffixAbbreviated, Error>>([&]() {
    535             return parseTypeSuffixAbbreviated();
    536         });
    537         if (!typeSuffixAbbreviated)
    538             break;
    539         // FIXME: The nesting here might be in the wrong order.
    540         next = constructTypeFromSuffixAbbreviated(*typeSuffixAbbreviated, WTFMove(result));
     492            ASSERT(addressSpaceToken->type == Lexer::Token::Type::Thread);
     493            addressSpace = AST::AddressSpace::Thread;
     494            break;
     495        }
     496        auto constructTypeFromSuffixAbbreviated = [&](const TypeSuffixAbbreviated& typeSuffixAbbreviated, UniqueRef<AST::UnnamedType>&& previous) -> UniqueRef<AST::UnnamedType> {
     497            switch (typeSuffixAbbreviated.token.type) {
     498            case Lexer::Token::Type::Star:
     499                return { makeUniqueRef<AST::PointerType>(Lexer::Token(typeSuffixAbbreviated.token), addressSpace, WTFMove(previous)) };
     500            case Lexer::Token::Type::SquareBracketPair:
     501                return { makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(typeSuffixAbbreviated.token), addressSpace, WTFMove(previous)) };
     502            default:
     503                ASSERT(typeSuffixAbbreviated.token.type == Lexer::Token::Type::LeftSquareBracket);
     504                return { makeUniqueRef<AST::ArrayType>(Lexer::Token(typeSuffixAbbreviated.token), WTFMove(previous), *typeSuffixAbbreviated.numElements) };
     505            }
     506        };
     507        PARSE(firstTypeSuffixAbbreviated, TypeSuffixAbbreviated);
     508        UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*addressSpaceToken), name->stringView.toString(), WTFMove(*typeArguments));
     509        auto next = constructTypeFromSuffixAbbreviated(*firstTypeSuffixAbbreviated, WTFMove(result));
    541510        result = WTFMove(next);
    542     }
    543 
    544     return WTFMove(result);
    545 }
    546 
    547 auto Parser::parseNonAddressSpaceType() -> Expected<UniqueRef<AST::UnnamedType>, Error>
    548 {
    549     auto origin = peek();
    550     if (!origin)
    551         return Unexpected<Error>(origin.error());
    552     auto name = consumeType(Lexer::Token::Type::Identifier);
    553     if (!name)
    554         return Unexpected<Error>(name.error());
    555     auto typeArguments = parseTypeArguments();
    556     if (!typeArguments)
    557         return Unexpected<Error>(typeArguments.error());
     511        while (true) {
     512            PEEK(nextToken);
     513            if (nextToken->type != Lexer::Token::Type::Star
     514                && nextToken->type != Lexer::Token::Type::SquareBracketPair
     515                && nextToken->type != Lexer::Token::Type::LeftSquareBracket) {
     516                break;
     517            }
     518            PARSE(typeSuffixAbbreviated, TypeSuffixAbbreviated);
     519            // FIXME: The nesting here might be in the wrong order.
     520            next = constructTypeFromSuffixAbbreviated(*typeSuffixAbbreviated, WTFMove(result));
     521            result = WTFMove(next);
     522        }
     523        return WTFMove(result);
     524    }
    558525
    559526    auto constructTypeFromSuffixNonAbbreviated = [&](const TypeSuffixNonAbbreviated& typeSuffixNonAbbreviated, UniqueRef<AST::UnnamedType>&& previous) -> UniqueRef<AST::UnnamedType> {
     
    568535        }
    569536    };
    570 
    571     UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*origin), name->stringView.toString(), WTFMove(*typeArguments));
     537    UniqueRef<AST::UnnamedType> result = makeUniqueRef<AST::TypeReference>(WTFMove(*name), name->stringView.toString(), WTFMove(*typeArguments));
    572538    while (true) {
    573         auto typeSuffixNonAbbreviated = backtrackingScope<Expected<TypeSuffixNonAbbreviated, Error>>([&]() {
    574             return parseTypeSuffixNonAbbreviated();
    575         });
    576         if (!typeSuffixNonAbbreviated)
    577             break;
     539        PEEK(nextToken);
     540        if (nextToken->type != Lexer::Token::Type::Star
     541            && nextToken->type != Lexer::Token::Type::SquareBracketPair
     542            && nextToken->type != Lexer::Token::Type::LeftSquareBracket) {
     543            break;
     544        }
     545        PARSE(typeSuffixNonAbbreviated, TypeSuffixNonAbbreviated);
    578546        // FIXME: The nesting here might be in the wrong order.
    579547        auto next = constructTypeFromSuffixNonAbbreviated(*typeSuffixNonAbbreviated, WTFMove(result));
    580548        result = WTFMove(next);
    581549    }
    582 
    583550    return WTFMove(result);
    584551}
    585552
    586 auto Parser::parseType() -> Expected<UniqueRef<AST::UnnamedType>, Error>
    587 {
    588     {
    589         auto type = backtrackingScope<Expected<UniqueRef<AST::UnnamedType>, Error>>([&]() {
    590             return parseAddressSpaceType();
    591         });
    592         if (type)
    593             return type;
    594     }
    595 
    596     auto type = backtrackingScope<Expected<UniqueRef<AST::UnnamedType>, Error>>([&]() {
    597         return parseNonAddressSpaceType();
    598     });
    599     if (type)
    600         return type;
    601 
    602     return Unexpected<Error>(type.error());
    603 }
    604 
    605553auto Parser::parseTypeDefinition() -> Expected<AST::TypeDefinition, Error>
    606554{
    607     auto origin = consumeType(Lexer::Token::Type::Typedef);
    608     if (!origin)
    609         return Unexpected<Error>(origin.error());
    610     auto name = consumeType(Lexer::Token::Type::Identifier);
    611     if (!name)
    612         return Unexpected<Error>(name.error());
    613     auto equals = consumeType(Lexer::Token::Type::EqualsSign);
    614     if (!equals)
    615         return Unexpected<Error>(equals.error());
    616     auto type = parseType();
    617     if (!type)
    618         return Unexpected<Error>(type.error());
    619     auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    620     if (!semicolon)
    621         return Unexpected<Error>(semicolon.error());
     555    CONSUME_TYPE(origin, Typedef);
     556    CONSUME_TYPE(name, Identifier);
     557    CONSUME_TYPE(equals, EqualsSign);
     558    PARSE(type, Type);
     559    CONSUME_TYPE(semicolon, Semicolon);
    622560    return AST::TypeDefinition(WTFMove(*origin), name->stringView.toString(), WTFMove(*type));
    623561}
     
    682620auto Parser::parseResourceSemantic() -> Expected<AST::ResourceSemantic, Error>
    683621{
    684     auto origin = consumeType(Lexer::Token::Type::Register);
    685     if (!origin)
    686         return Unexpected<Error>(origin.error());
    687 
    688     auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis);
    689     if (!leftParenthesis)
    690         return Unexpected<Error>(leftParenthesis.error());
    691 
    692     auto info = consumeType(Lexer::Token::Type::Identifier);
    693     if (!info)
    694         return Unexpected<Error>(info.error());
     622    CONSUME_TYPE(origin, Register);
     623    CONSUME_TYPE(leftParenthesis, LeftParenthesis);
     624
     625    CONSUME_TYPE(info, Identifier);
    695626    if (info->stringView.length() < 2 || (info->stringView[0] != 'u'
    696627        && info->stringView[0] != 't'
     
    721652    unsigned space = 0;
    722653    if (tryType(Lexer::Token::Type::Comma)) {
    723         auto spaceToken = consumeType(Lexer::Token::Type::Identifier);
    724         if (!spaceToken)
    725             return Unexpected<Error>(spaceToken.error());
     654        CONSUME_TYPE(spaceToken, Identifier);
    726655        auto prefix = "space"_str;
    727656        if (!spaceToken->stringView.startsWith(StringView(prefix)))
     
    735664    }
    736665
    737     auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    738     if (!rightParenthesis)
    739         return Unexpected<Error>(rightParenthesis.error());
     666    CONSUME_TYPE(rightParenthesis, RightParenthesis);
    740667
    741668    return AST::ResourceSemantic(WTFMove(*origin), mode, *index, space);
     
    744671auto Parser::parseSpecializationConstantSemantic() -> Expected<AST::SpecializationConstantSemantic, Error>
    745672{
    746     auto origin = consumeType(Lexer::Token::Type::Specialized);
    747     if (!origin)
    748         return Unexpected<Error>(origin.error());
     673    CONSUME_TYPE(origin, Specialized);
    749674    return AST::SpecializationConstantSemantic(WTFMove(*origin));
    750675}
     
    752677auto Parser::parseStageInOutSemantic() -> Expected<AST::StageInOutSemantic, Error>
    753678{
    754     auto origin = consumeType(Lexer::Token::Type::Attribute);
    755     if (!origin)
    756         return Unexpected<Error>(origin.error());
    757 
    758     auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis);
    759     if (!leftParenthesis)
    760         return Unexpected<Error>(leftParenthesis.error());
     679    CONSUME_TYPE(origin, Attribute);
     680    CONSUME_TYPE(leftParenthesis, LeftParenthesis);
    761681
    762682    auto index = consumeNonNegativeIntegralLiteral();
     
    764684        return Unexpected<Error>(index.error());
    765685
    766     auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    767     if (!rightParenthesis)
    768         return Unexpected<Error>(rightParenthesis.error());
     686    CONSUME_TYPE(rightParenthesis, RightParenthesis);
    769687
    770688    return AST::StageInOutSemantic(WTFMove(*origin), *index);
    771689}
    772690
    773 auto Parser::parseSemantic() -> Expected<AST::Semantic, Error>
    774 {
    775     auto builtInSemantic = backtrackingScope<Expected<AST::BuiltInSemantic, Error>>([&]() {
    776         return parseBuiltInSemantic();
    777     });
    778     if (builtInSemantic)
    779         return AST::Semantic(WTFMove(*builtInSemantic));
    780 
    781     auto resourceSemantic = backtrackingScope<Expected<AST::ResourceSemantic, Error>>([&]() {
    782         return parseResourceSemantic();
    783     });
    784     if (resourceSemantic)
    785         return AST::Semantic(WTFMove(*resourceSemantic));
    786 
    787     auto specializationConstantSemantic = backtrackingScope<Expected<AST::SpecializationConstantSemantic, Error>>([&]() {
    788         return parseSpecializationConstantSemantic();
    789     });
    790     if (specializationConstantSemantic)
    791         return AST::Semantic(WTFMove(*specializationConstantSemantic));
    792 
    793     auto stageInOutSemantic = backtrackingScope<Expected<AST::StageInOutSemantic, Error>>([&]() {
    794         return parseStageInOutSemantic();
    795     });
    796     if (stageInOutSemantic)
    797         return AST::Semantic(WTFMove(*stageInOutSemantic));
    798 
    799     return Unexpected<Error>(stageInOutSemantic.error());
     691auto Parser::parseSemantic() -> Expected<Optional<AST::Semantic>, Error>
     692{
     693    if (!tryType(Lexer::Token::Type::Colon))
     694        return { WTF::nullopt };
     695
     696    PEEK(token);
     697    switch (token->type) {
     698    case Lexer::Token::Type::Attribute: {
     699        PARSE(result, StageInOutSemantic);
     700        return { AST::Semantic(WTFMove(*result)) };
     701    }
     702    case Lexer::Token::Type::Specialized:  {
     703        PARSE(result, SpecializationConstantSemantic);
     704        return { AST::Semantic(WTFMove(*result)) };
     705    }
     706    case Lexer::Token::Type::Register:  {
     707        PARSE(result, ResourceSemantic);
     708        return { AST::Semantic(WTFMove(*result)) };
     709    }
     710    default:  {
     711        PARSE(result, BuiltInSemantic);
     712        return { AST::Semantic(WTFMove(*result)) };
     713    }
     714    }
    800715}
    801716AST::Qualifiers Parser::parseQualifiers()
    802717{
    803718    AST::Qualifiers qualifiers;
    804     while (true) {
    805         if (auto next = tryType(Lexer::Token::Type::Qualifier)) {
    806             if ("nointerpolation" == next->stringView)
    807                 qualifiers.append(AST::Qualifier::Nointerpolation);
    808             else if ("noperspective" == next->stringView)
    809                 qualifiers.append(AST::Qualifier::Noperspective);
    810             else if ("uniform" == next->stringView)
    811                 qualifiers.append(AST::Qualifier::Uniform);
    812             else if ("centroid" == next->stringView)
    813                 qualifiers.append(AST::Qualifier::Centroid);
    814             else {
    815                 ASSERT("sample" == next->stringView);
    816                 qualifiers.append(AST::Qualifier::Sample);
    817             }
    818         } else
    819             break;
     719    while (auto next = tryType(Lexer::Token::Type::Qualifier)) {
     720        if ("nointerpolation" == next->stringView)
     721            qualifiers.append(AST::Qualifier::Nointerpolation);
     722        else if ("noperspective" == next->stringView)
     723            qualifiers.append(AST::Qualifier::Noperspective);
     724        else if ("uniform" == next->stringView)
     725            qualifiers.append(AST::Qualifier::Uniform);
     726        else if ("centroid" == next->stringView)
     727            qualifiers.append(AST::Qualifier::Centroid);
     728        else {
     729            ASSERT("sample" == next->stringView);
     730            qualifiers.append(AST::Qualifier::Sample);
     731        }
    820732    }
    821733    return qualifiers;
     
    824736auto Parser::parseStructureElement() -> Expected<AST::StructureElement, Error>
    825737{
    826     auto origin = peek();
    827     if (!origin)
    828         return Unexpected<Error>(origin.error());
     738    PEEK(origin);
    829739
    830740    AST::Qualifiers qualifiers = parseQualifiers();
    831741
    832     auto type = parseType();
    833     if (!type)
    834         return Unexpected<Error>(type.error());
    835 
    836     auto name = consumeType(Lexer::Token::Type::Identifier);
    837     if (!name)
    838         return Unexpected<Error>(name.error());
    839 
    840     if (tryType(Lexer::Token::Type::Colon)) {
    841         auto semantic = parseSemantic();
    842         if (!semantic)
    843             return Unexpected<Error>(semantic.error());
    844 
    845         auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    846         if (!semicolon)
    847             return Unexpected<Error>(semicolon.error());
    848 
    849         return AST::StructureElement(WTFMove(*origin), WTFMove(qualifiers), WTFMove(*type), name->stringView.toString(), WTFMove(*semantic));
    850     }
    851 
    852     auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    853     if (!semicolon)
    854         return Unexpected<Error>(semicolon.error());
    855 
    856     return AST::StructureElement(WTFMove(*origin), WTFMove(qualifiers), WTFMove(*type), name->stringView.toString(), WTF::nullopt);
     742    PARSE(type, Type);
     743    CONSUME_TYPE(name, Identifier);
     744    PARSE(semantic, Semantic);
     745    CONSUME_TYPE(semicolon, Semicolon);
     746
     747    return AST::StructureElement(WTFMove(*origin), WTFMove(qualifiers), WTFMove(*type), name->stringView.toString(), WTFMove(*semantic));
    857748}
    858749
    859750auto Parser::parseStructureDefinition() -> Expected<AST::StructureDefinition, Error>
    860751{
    861     auto origin = consumeType(Lexer::Token::Type::Struct);
    862     if (!origin)
    863         return Unexpected<Error>(origin.error());
    864 
    865     auto name = consumeType(Lexer::Token::Type::Identifier);
    866     if (!name)
    867         return Unexpected<Error>(name.error());
    868 
    869     auto leftCurlyBracket = consumeType(Lexer::Token::Type::LeftCurlyBracket);
    870     if (!leftCurlyBracket)
    871         return Unexpected<Error>(leftCurlyBracket.error());
     752    CONSUME_TYPE(origin, Struct);
     753    CONSUME_TYPE(name, Identifier);
     754    CONSUME_TYPE(leftCurlyBracket, LeftCurlyBracket);
    872755
    873756    AST::StructureElements structureElements;
    874     while (true) {
    875         auto structureElement = backtrackingScope<Expected<AST::StructureElement, Error>>([&]() {
    876             return parseStructureElement();
    877         });
    878         if (structureElement)
    879             structureElements.append(WTFMove(*structureElement));
    880         else
    881             break;
    882     }
    883 
    884     auto rightCurlyBracket = consumeType(Lexer::Token::Type::RightCurlyBracket);
    885     if (!rightCurlyBracket)
    886         return Unexpected<Error>(rightCurlyBracket.error());
     757    while (!tryType(Lexer::Token::Type::RightCurlyBracket)) {
     758        PARSE(structureElement, StructureElement);
     759        structureElements.append(WTFMove(*structureElement));
     760    }
    887761
    888762    return AST::StructureDefinition(WTFMove(*origin), name->stringView.toString(), WTFMove(structureElements));
     
    891765auto Parser::parseEnumerationDefinition() -> Expected<AST::EnumerationDefinition, Error>
    892766{
    893     auto origin = consumeType(Lexer::Token::Type::Enum);
    894     if (!origin)
    895         return Unexpected<Error>(origin.error());
    896 
    897     auto name = consumeType(Lexer::Token::Type::Identifier);
    898     if (!name)
    899         return Unexpected<Error>(name.error());
     767    CONSUME_TYPE(origin, Enum);
     768    CONSUME_TYPE(name, Identifier);
    900769
    901770    auto type = ([&]() -> Expected<UniqueRef<AST::UnnamedType>, Error> {
    902771        if (tryType(Lexer::Token::Type::Colon)) {
    903             auto parsedType = parseType();
    904             if (!parsedType)
    905                 return Unexpected<Error>(parsedType.error());
     772            PARSE(parsedType, Type);
    906773            return WTFMove(*parsedType);
    907774        }
     
    911778        return Unexpected<Error>(type.error());
    912779
    913     auto leftCurlyBracket = consumeType(Lexer::Token::Type::LeftCurlyBracket);
    914     if (!leftCurlyBracket)
    915         return Unexpected<Error>(leftCurlyBracket.error());
    916 
    917     auto firstEnumerationMember = parseEnumerationMember();
    918     if (!firstEnumerationMember)
    919         return Unexpected<Error>(firstEnumerationMember.error());
     780    CONSUME_TYPE(leftCurlyBracket, LeftCurlyBracket);
     781
     782    PARSE(firstEnumerationMember, EnumerationMember);
    920783
    921784    AST::EnumerationDefinition result(WTFMove(*origin), name->stringView.toString(), WTFMove(*type));
     
    925788
    926789    while (tryType(Lexer::Token::Type::Comma)) {
    927         auto member = parseEnumerationMember();
    928         if (!member)
    929             return Unexpected<Error>(member.error());
     790        PARSE(member, EnumerationMember);
    930791        success = result.add(WTFMove(*member));
    931792        if (!success)
     
    933794    }
    934795
    935     auto rightCurlyBracket = consumeType(Lexer::Token::Type::RightCurlyBracket);
    936     if (!rightCurlyBracket)
    937         return Unexpected<Error>(rightCurlyBracket.error());
     796    CONSUME_TYPE(rightCurlyBracket, RightCurlyBracket);
    938797
    939798    return WTFMove(result);
     
    942801auto Parser::parseEnumerationMember() -> Expected<AST::EnumerationMember, Error>
    943802{
    944     auto identifier = consumeType(Lexer::Token::Type::Identifier);
    945     if (!identifier)
    946         return Unexpected<Error>(identifier.error());
     803    CONSUME_TYPE(identifier, Identifier);
    947804    auto name = identifier->stringView.toString();
    948805
    949806    if (tryType(Lexer::Token::Type::EqualsSign)) {
    950         auto constantExpression = parseConstantExpression();
    951         if (!constantExpression)
    952             return Unexpected<Error>(constantExpression.error());
     807        PARSE(constantExpression, ConstantExpression);
    953808        return AST::EnumerationMember(Lexer::Token(*identifier), WTFMove(name), WTFMove(*constantExpression));
    954809    }
     
    958813auto Parser::parseNativeTypeDeclaration() -> Expected<AST::NativeTypeDeclaration, Error>
    959814{
    960     auto origin = consumeType(Lexer::Token::Type::Native);
    961     if (!origin)
    962         return Unexpected<Error>(origin.error());
    963 
    964     auto parsedTypedef = consumeType(Lexer::Token::Type::Typedef);
    965     if (!parsedTypedef)
    966         return Unexpected<Error>(parsedTypedef.error());
    967 
    968     auto name = consumeType(Lexer::Token::Type::Identifier);
    969     if (!name)
    970         return Unexpected<Error>(name.error());
    971 
    972     auto typeArguments = parseTypeArguments();
    973     if (!typeArguments)
    974         return Unexpected<Error>(typeArguments.error());
    975 
    976     auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    977     if (!semicolon)
    978         return Unexpected<Error>(semicolon.error());
     815    CONSUME_TYPE(origin, Native);
     816    CONSUME_TYPE(parsedTypedef, Typedef);
     817    CONSUME_TYPE(name, Identifier);
     818    PARSE(typeArguments, TypeArguments);
     819    CONSUME_TYPE(semicolon, Semicolon);
    979820
    980821    return AST::NativeTypeDeclaration(WTFMove(*origin), name->stringView.toString(), WTFMove(*typeArguments));
     
    983824auto Parser::parseNumThreadsFunctionAttribute() -> Expected<AST::NumThreadsFunctionAttribute, Error>
    984825{
    985     auto origin = consumeType(Lexer::Token::Type::NumThreads);
    986     if (!origin)
    987         return Unexpected<Error>(origin.error());
    988 
    989     auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis);
    990     if (!leftParenthesis)
    991         return Unexpected<Error>(leftParenthesis.error());
     826    CONSUME_TYPE(origin, NumThreads);
     827    CONSUME_TYPE(leftParenthesis, LeftParenthesis);
    992828
    993829    auto width = consumeNonNegativeIntegralLiteral();
     
    995831        return Unexpected<Error>(width.error());
    996832
    997     auto comma = consumeType(Lexer::Token::Type::Comma);
    998     if (!comma)
    999         return Unexpected<Error>(comma.error());
     833    CONSUME_TYPE(comma, Comma);
    1000834
    1001835    auto height = consumeNonNegativeIntegralLiteral();
     
    1003837        return Unexpected<Error>(height.error());
    1004838
    1005     comma = consumeType(Lexer::Token::Type::Comma);
    1006     if (!comma)
    1007         return Unexpected<Error>(comma.error());
     839    CONSUME_TYPE(secondComma, Comma);
    1008840
    1009841    auto depth = consumeNonNegativeIntegralLiteral();
     
    1011843        return Unexpected<Error>(depth.error());
    1012844
    1013     auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    1014     if (!rightParenthesis)
    1015         return Unexpected<Error>(rightParenthesis.error());
     845    CONSUME_TYPE(rightParenthesis, RightParenthesis);
    1016846
    1017847    return AST::NumThreadsFunctionAttribute(WTFMove(*origin), *width, *height, *depth);
     
    1020850auto Parser::parseAttributeBlock() -> Expected<AST::AttributeBlock, Error>
    1021851{
    1022     auto leftSquareBracket = consumeType(Lexer::Token::Type::LeftSquareBracket);
    1023     if (!leftSquareBracket)
    1024         return Unexpected<Error>(leftSquareBracket.error());
     852    CONSUME_TYPE(leftSquareBracket, LeftSquareBracket);
    1025853
    1026854    AST::AttributeBlock result;
     
    1038866    }
    1039867
    1040     auto rightSquareBracket = consumeType(Lexer::Token::Type::RightSquareBracket);
    1041     if (!rightSquareBracket)
    1042         return Unexpected<Error>(rightSquareBracket.error());
     868    CONSUME_TYPE(rightSquareBracket, RightSquareBracket);
    1043869
    1044870    return WTFMove(result);
     
    1047873auto Parser::parseParameter() -> Expected<AST::VariableDeclaration, Error>
    1048874{
    1049     auto origin = peek();
    1050     if (!origin)
    1051         return Unexpected<Error>(origin.error());
     875    PEEK(origin);
    1052876
    1053877    AST::Qualifiers qualifiers = parseQualifiers();
    1054878
    1055     auto type = parseType();
    1056     if (!type)
    1057         return Unexpected<Error>(type.error());
     879    PARSE(type, Type);
    1058880
    1059881    String name;
     
    1061883        name = token->stringView.toString();
    1062884
    1063     if (tryType(Lexer::Token::Type::Colon)) {
    1064         auto semantic = parseSemantic();
    1065         if (!semantic)
    1066             return Unexpected<Error>(semantic.error());
    1067         return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), Optional<UniqueRef<AST::UnnamedType>>(WTFMove(*type)), WTFMove(name), WTFMove(*semantic), WTF::nullopt);
    1068     }
    1069 
    1070     return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(*type) }, WTFMove(name), WTF::nullopt, WTF::nullopt);
     885    PARSE(semantic, Semantic);
     886
     887    return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(*type) }, WTFMove(name), WTFMove(*semantic), WTF::nullopt);
    1071888}
    1072889
    1073890auto Parser::parseParameters() -> Expected<AST::VariableDeclarations, Error>
    1074891{
    1075     auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis);
    1076     if (!leftParenthesis)
    1077         return Unexpected<Error>(leftParenthesis.error());
    1078 
    1079892    AST::VariableDeclarations parameters;
     893
     894    CONSUME_TYPE(leftParenthesis, LeftParenthesis);
     895
    1080896    if (tryType(Lexer::Token::Type::RightParenthesis))
    1081897        return WTFMove(parameters);
    1082898
    1083     auto firstParameter = parseParameter();
    1084     if (!firstParameter)
    1085         return Unexpected<Error>(firstParameter.error());
     899    PARSE(firstParameter, Parameter);
    1086900    parameters.append(makeUniqueRef<AST::VariableDeclaration>(WTFMove(*firstParameter)));
    1087901
    1088902    while (tryType(Lexer::Token::Type::Comma)) {
    1089         auto parameter = parseParameter();
    1090         if (!parameter)
    1091             return Unexpected<Error>(parameter.error());
     903        PARSE(parameter, Parameter);
    1092904        parameters.append(makeUniqueRef<AST::VariableDeclaration>(WTFMove(*parameter)));
    1093905    }
    1094906
    1095     auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    1096     if (!rightParenthesis)
    1097         return Unexpected<Error>(rightParenthesis.error());
     907    CONSUME_TYPE(rightParenthesis, RightParenthesis);
    1098908
    1099909    return WTFMove(parameters);
     
    1102912auto Parser::parseFunctionDefinition() -> Expected<AST::FunctionDefinition, Error>
    1103913{
    1104     auto functionDeclaration = parseFunctionDeclaration();
    1105     if (!functionDeclaration)
    1106         return Unexpected<Error>(functionDeclaration.error());
    1107 
    1108     auto block = parseBlock();
    1109     if (!block)
    1110         return Unexpected<Error>(block.error());
    1111 
     914    PARSE(functionDeclaration, FunctionDeclaration);
     915    PARSE(block, Block);
    1112916    return AST::FunctionDefinition(WTFMove(*functionDeclaration), WTFMove(*block));
    1113917}
    1114918
    1115 auto Parser::parseEntryPointFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error>
    1116 {
    1117     auto origin = peek();
    1118     if (!origin)
    1119         return Unexpected<Error>(origin.error());
    1120 
    1121     AST::AttributeBlock attributeBlock;
    1122     AST::EntryPointType entryPointType;
    1123 
    1124     auto parsedAttributeBlock = backtrackingScope<Expected<AST::AttributeBlock, Error>>([&]() {
    1125         return parseAttributeBlock();
    1126     });
    1127     if (parsedAttributeBlock) {
    1128         auto compute = consumeType(Lexer::Token::Type::Compute);
    1129         if (!compute)
    1130             return Unexpected<Error>(compute.error());
    1131         attributeBlock = WTFMove(*parsedAttributeBlock);
    1132         entryPointType = AST::EntryPointType::Compute;
    1133     } else {
    1134         auto type = consumeTypes({ Lexer::Token::Type::Vertex, Lexer::Token::Type::Fragment });
    1135         if (!type)
    1136             return Unexpected<Error>(type.error());
    1137 
    1138         switch (origin->type) {
    1139         case Lexer::Token::Type::Vertex:
    1140             entryPointType = AST::EntryPointType::Vertex;
    1141             break;
    1142         default:
    1143             ASSERT(origin->type == Lexer::Token::Type::Fragment);
    1144             entryPointType = AST::EntryPointType::Fragment;
    1145             break;
    1146         }
    1147     }
    1148 
    1149     auto type = parseType();
    1150     if (!type)
    1151         return Unexpected<Error>(type.error());
    1152 
    1153     auto name = consumeType(Lexer::Token::Type::Identifier);
    1154     if (!name)
    1155         return Unexpected<Error>(name.error());
    1156 
    1157     auto parameters = parseParameters();
    1158     if (!parameters)
    1159         return Unexpected<Error>(parameters.error());
    1160 
     919auto Parser::parseComputeFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error>
     920{
     921    PEEK(origin);
     922
     923    PARSE(attributeBlock, AttributeBlock);
     924    CONSUME_TYPE(compute, Compute);
     925    PARSE(type, Type);
     926    CONSUME_TYPE(name, Identifier);
     927    PARSE(parameters, Parameters);
     928    PARSE(semantic, Semantic);
    1161929    bool isOperator = false;
    1162 
    1163     if (tryType(Lexer::Token::Type::Colon)) {
    1164         auto semantic = parseSemantic();
    1165         if (!semantic)
    1166             return Unexpected<Error>(semantic.error());
    1167         return AST::FunctionDeclaration(WTFMove(*origin), WTFMove(attributeBlock), entryPointType, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator);
    1168     }
    1169 
    1170     return AST::FunctionDeclaration(WTFMove(*origin), WTFMove(attributeBlock), entryPointType, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTF::nullopt, isOperator);
     930    return AST::FunctionDeclaration(WTFMove(*origin), WTFMove(*attributeBlock), AST::EntryPointType::Compute, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator);
     931}
     932
     933auto Parser::parseVertexOrFragmentFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error>
     934{
     935    auto entryPoint = consumeTypes({ Lexer::Token::Type::Vertex, Lexer::Token::Type::Fragment });
     936    if (!entryPoint)
     937        return Unexpected<Error>(entryPoint.error());
     938    auto entryPointType = (entryPoint->type == Lexer::Token::Type::Vertex) ? AST::EntryPointType::Vertex : AST::EntryPointType::Fragment;
     939
     940    PARSE(type, Type);
     941    CONSUME_TYPE(name, Identifier);
     942    PARSE(parameters, Parameters);
     943    PARSE(semantic, Semantic);
     944
     945    bool isOperator = false;
     946    return AST::FunctionDeclaration(WTFMove(*entryPoint), { }, entryPointType, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator);
    1171947}
    1172948
    1173949auto Parser::parseRegularFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error>
    1174950{
    1175     auto origin = peek();
    1176     if (!origin)
    1177         return Unexpected<Error>(origin.error());
    1178 
    1179     auto type = parseType();
    1180     if (!type)
    1181         return Unexpected<Error>(type.error());
     951    PEEK(origin);
     952
     953    PARSE(type, Type);
    1182954
    1183955    auto name = consumeTypes({ Lexer::Token::Type::Identifier, Lexer::Token::Type::OperatorName });
     
    1186958    auto isOperator = name->type == Lexer::Token::Type::OperatorName;
    1187959
    1188     auto parameters = parseParameters();
    1189     if (!parameters)
    1190         return Unexpected<Error>(parameters.error());
    1191 
    1192     if (tryType(Lexer::Token::Type::Colon)) {
    1193         auto semantic = parseSemantic();
    1194         if (!semantic)
    1195             return Unexpected<Error>(semantic.error());
    1196         return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator);
    1197     }
    1198 
    1199     return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTF::nullopt, isOperator);
     960    PARSE(parameters, Parameters);
     961    PARSE(semantic, Semantic);
     962
     963    return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), name->stringView.toString(), WTFMove(*parameters), WTFMove(*semantic), isOperator);
    1200964}
    1201965
    1202966auto Parser::parseOperatorFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error>
    1203967{
    1204     auto origin = consumeType(Lexer::Token::Type::Operator);
    1205     if (!origin)
    1206         return Unexpected<Error>(origin.error());
    1207 
    1208     auto type = parseType();
    1209     if (!type)
    1210         return Unexpected<Error>(type.error());
    1211 
    1212     auto parameters = parseParameters();
    1213     if (!parameters)
    1214         return Unexpected<Error>(parameters.error());
     968    CONSUME_TYPE(origin, Operator);
     969    PARSE(type, Type);
     970    PARSE(parameters, Parameters);
     971    PARSE(semantic, Semantic);
    1215972
    1216973    bool isOperator = true;
    1217 
    1218     if (tryType(Lexer::Token::Type::Colon)) {
    1219         auto semantic = parseSemantic();
    1220         if (!semantic)
    1221             return Unexpected<Error>(semantic.error());
    1222         return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), "operator cast"_str, WTFMove(*parameters), WTFMove(*semantic), isOperator);
    1223     }
    1224 
    1225     return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), "operator cast"_str, WTFMove(*parameters), WTF::nullopt, isOperator);
     974    return AST::FunctionDeclaration(WTFMove(*origin), { }, WTF::nullopt, WTFMove(*type), "operator cast"_str, WTFMove(*parameters), WTFMove(*semantic), isOperator);
    1226975}
    1227976
    1228977auto Parser::parseFunctionDeclaration() -> Expected<AST::FunctionDeclaration, Error>
    1229978{
    1230     auto entryPointFunctionDeclaration = backtrackingScope<Expected<AST::FunctionDeclaration, Error>>([&]() {
    1231         return parseEntryPointFunctionDeclaration();
    1232     });
    1233     if (entryPointFunctionDeclaration)
    1234         return WTFMove(*entryPointFunctionDeclaration);
    1235 
    1236     auto regularFunctionDeclaration = backtrackingScope<Expected<AST::FunctionDeclaration, Error>>([&]() {
     979    PEEK(token);
     980    switch (token->type) {
     981    case Lexer::Token::Type::Operator:
     982        return parseOperatorFunctionDeclaration();
     983    case Lexer::Token::Type::Vertex:
     984    case Lexer::Token::Type::Fragment:
     985        return parseVertexOrFragmentFunctionDeclaration();
     986    case Lexer::Token::Type::LeftSquareBracket:
     987        return parseComputeFunctionDeclaration();
     988    default:
    1237989        return parseRegularFunctionDeclaration();
    1238     });
    1239     if (regularFunctionDeclaration)
    1240         return WTFMove(*regularFunctionDeclaration);
    1241 
    1242     auto operatorFunctionDeclaration = backtrackingScope<Expected<AST::FunctionDeclaration, Error>>([&]() {
    1243         return parseOperatorFunctionDeclaration();
    1244     });
    1245     if (operatorFunctionDeclaration)
    1246         return WTFMove(*operatorFunctionDeclaration);
    1247 
    1248     return Unexpected<Error>(operatorFunctionDeclaration.error());
     990    }
    1249991}
    1250992
    1251993auto Parser::parseNativeFunctionDeclaration() -> Expected<AST::NativeFunctionDeclaration, Error>
    1252994{
    1253     Optional<Lexer::Token> origin;
    1254 
    1255     auto native = consumeType(Lexer::Token::Type::Native);
    1256     if (!native)
    1257         return Unexpected<Error>(native.error());
    1258     if (!origin)
    1259         origin = *native;
    1260 
    1261     auto functionDeclaration = parseFunctionDeclaration();
    1262     if (!functionDeclaration)
    1263         return Unexpected<Error>(functionDeclaration.error());
    1264 
    1265     auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    1266     if (!semicolon)
    1267         return Unexpected<Error>(semicolon.error());
     995    CONSUME_TYPE(native, Native);
     996    PARSE(functionDeclaration, FunctionDeclaration);
     997    CONSUME_TYPE(semicolon, Semicolon);
    1268998
    1269999    return AST::NativeFunctionDeclaration(WTFMove(*functionDeclaration));
     
    12721002auto Parser::parseBlock() -> Expected<AST::Block, Error>
    12731003{
    1274     auto origin = consumeType(Lexer::Token::Type::LeftCurlyBracket);
    1275     if (!origin)
    1276         return Unexpected<Error>(origin.error());
    1277 
    1278     auto result = parseBlockBody(WTFMove(*origin));
    1279 
    1280     auto rightCurlyBracket = consumeType(Lexer::Token::Type::RightCurlyBracket);
    1281     if (!rightCurlyBracket)
    1282         return Unexpected<Error>(rightCurlyBracket.error());
    1283 
    1284     return WTFMove(result);
    1285 }
    1286 
    1287 AST::Block Parser::parseBlockBody(Lexer::Token&& origin)
     1004    CONSUME_TYPE(origin, LeftCurlyBracket);
     1005    PARSE(result, BlockBody, WTFMove(*origin));
     1006    CONSUME_TYPE(rightCurlyBracket, RightCurlyBracket);
     1007    return WTFMove(*result);
     1008}
     1009
     1010auto Parser::parseBlockBody(Lexer::Token&& origin) -> Expected<AST::Block, Error>
    12881011{
    12891012    AST::Statements statements;
    1290     while (true) {
    1291         auto statement = backtrackingScope<Expected<UniqueRef<AST::Statement>, Error>>([&]() {
    1292             return parseStatement();
    1293         });
    1294         if (statement)
    1295             statements.append(WTFMove(*statement));
    1296         else
    1297             break;
     1013    while (!peekTypes({Lexer::Token::Type::RightCurlyBracket, Lexer::Token::Type::Case, Lexer::Token::Type::Default})) {
     1014        PARSE(statement, Statement);
     1015        statements.append(WTFMove(*statement));
    12981016    }
    12991017    return AST::Block(WTFMove(origin), WTFMove(statements));
     
    13021020auto Parser::parseIfStatement() -> Expected<AST::IfStatement, Error>
    13031021{
    1304     auto origin = consumeType(Lexer::Token::Type::If);
    1305     if (!origin)
    1306         return Unexpected<Error>(origin.error());
    1307 
    1308     auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis);
    1309     if (!leftParenthesis)
    1310         return Unexpected<Error>(leftParenthesis.error());
    1311 
    1312     auto conditional = parseExpression();
    1313     if (!conditional)
    1314         return Unexpected<Error>(conditional.error());
    1315 
    1316     auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    1317     if (!rightParenthesis)
    1318         return Unexpected<Error>(rightParenthesis.error());
    1319 
    1320     auto body = parseStatement();
    1321     if (!body)
    1322         return Unexpected<Error>(body.error());
     1022    CONSUME_TYPE(origin, If);
     1023    CONSUME_TYPE(leftParenthesis, LeftParenthesis);
     1024    PARSE(conditional, Expression);
     1025    CONSUME_TYPE(rightParenthesis, RightParenthesis);
     1026    PARSE(body, Statement);
    13231027
    13241028    Optional<UniqueRef<AST::Statement>> elseBody;
    13251029    if (tryType(Lexer::Token::Type::Else)) {
    1326         auto parsedElseBody = parseStatement();
    1327         if (!parsedElseBody)
    1328             return Unexpected<Error>(parsedElseBody.error());
     1030        PARSE(parsedElseBody, Statement);
    13291031        elseBody = WTFMove(*parsedElseBody);
    13301032    }
     
    13381040auto Parser::parseSwitchStatement() -> Expected<AST::SwitchStatement, Error>
    13391041{
    1340     auto origin = consumeType(Lexer::Token::Type::Switch);
    1341     if (!origin)
    1342         return Unexpected<Error>(origin.error());
    1343 
    1344     auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis);
    1345     if (!leftParenthesis)
    1346         return Unexpected<Error>(leftParenthesis.error());
    1347 
    1348     auto value = parseExpression();
    1349     if (!value)
    1350         return Unexpected<Error>(value.error());
    1351 
    1352     auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    1353     if (!rightParenthesis)
    1354         return Unexpected<Error>(rightParenthesis.error());
    1355 
    1356     auto leftCurlyBracket = consumeType(Lexer::Token::Type::LeftCurlyBracket);
    1357     if (!leftCurlyBracket)
    1358         return Unexpected<Error>(leftCurlyBracket.error());
     1042    CONSUME_TYPE(origin, Switch);
     1043    CONSUME_TYPE(leftParenthesis, LeftParenthesis);
     1044    PARSE(value, Expression);
     1045    CONSUME_TYPE(rightParenthesis, RightParenthesis);
     1046    CONSUME_TYPE(leftCurlyBracket, LeftCurlyBracket);
    13591047
    13601048    Vector<AST::SwitchCase> switchCases;
    1361     while (true) {
    1362         auto switchCase = backtrackingScope<Expected<AST::SwitchCase, Error>>([&]() {
    1363             return parseSwitchCase();
    1364         });
    1365         if (switchCase)
    1366             switchCases.append(WTFMove(*switchCase));
    1367         else
    1368             break;
    1369     }
    1370 
    1371     auto rightCurlyBracket = consumeType(Lexer::Token::Type::RightCurlyBracket);
    1372     if (!rightCurlyBracket)
    1373         return Unexpected<Error>(rightCurlyBracket.error());
     1049    PEEK(nextToken);
     1050    while (nextToken->type != Lexer::Token::Type::RightCurlyBracket) {
     1051        PARSE(switchCase, SwitchCase);
     1052        switchCases.append(WTFMove(*switchCase));
     1053        PEEK(nextTokenInLoop);
     1054        nextToken = nextTokenInLoop;
     1055    }
     1056
     1057    m_lexer.consumeToken();
    13741058
    13751059    return AST::SwitchStatement(WTFMove(*origin), WTFMove(*value), WTFMove(switchCases));
     
    13841068    switch (origin->type) {
    13851069    case Lexer::Token::Type::Case: {
    1386         auto value = parseConstantExpression();
    1387         if (!value)
    1388             return Unexpected<Error>(value.error());
    1389 
    1390         auto origin = consumeType(Lexer::Token::Type::Colon);
    1391         if (!origin)
    1392             return Unexpected<Error>(origin.error());
    1393 
    1394         auto block = parseBlockBody(Lexer::Token(*origin));
    1395 
    1396         return AST::SwitchCase(WTFMove(*origin), WTFMove(*value), WTFMove(block));
     1070        PARSE(value, ConstantExpression);
     1071        CONSUME_TYPE(colon, Colon);
     1072
     1073        PARSE(block, BlockBody, Lexer::Token(*origin));
     1074
     1075        return AST::SwitchCase(WTFMove(*origin), WTFMove(*value), WTFMove(*block));
    13971076    }
    13981077    default: {
    13991078        ASSERT(origin->type == Lexer::Token::Type::Default);
    1400         auto origin = consumeType(Lexer::Token::Type::Colon);
    1401         if (!origin)
    1402             return Unexpected<Error>(origin.error());
    1403 
    1404         auto block = parseBlockBody(Lexer::Token(*origin));
    1405 
    1406         return AST::SwitchCase(WTFMove(*origin), WTF::nullopt, WTFMove(block));
     1079        CONSUME_TYPE(colon, Colon);
     1080
     1081        PARSE(block, BlockBody, Lexer::Token(*origin));
     1082
     1083        return AST::SwitchCase(WTFMove(*origin), WTF::nullopt, WTFMove(*block));
    14071084    }
    14081085    }
     
    14111088auto Parser::parseForLoop() -> Expected<AST::ForLoop, Error>
    14121089{
    1413     auto origin = consumeType(Lexer::Token::Type::For);
    1414     if (!origin)
    1415         return Unexpected<Error>(origin.error());
     1090    CONSUME_TYPE(origin, For);
     1091    CONSUME_TYPE(leftParenthesis, LeftParenthesis);
    14161092
    14171093    auto parseRemainder = [&](Variant<UniqueRef<AST::Statement>, UniqueRef<AST::Expression>>&& initialization) -> Expected<AST::ForLoop, Error> {
    1418         auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    1419         if (!semicolon)
    1420             return Unexpected<Error>(semicolon.error());
    1421 
    1422         auto condition = backtrackingScope<Optional<UniqueRef<AST::Expression>>>([&]() -> Optional<UniqueRef<AST::Expression>> {
     1094        CONSUME_TYPE(semicolon, Semicolon);
     1095
     1096        Optional<UniqueRef<AST::Expression>> condition = WTF::nullopt;
     1097        if (!tryType(Lexer::Token::Type::Semicolon)) {
    14231098            if (auto expression = parseExpression())
    1424                 return { WTFMove(*expression) };
    1425             return WTF::nullopt;
    1426         });
    1427 
    1428         semicolon = consumeType(Lexer::Token::Type::Semicolon);
    1429         if (!semicolon)
    1430             return Unexpected<Error>(semicolon.error());
    1431 
    1432         auto increment = backtrackingScope<Optional<UniqueRef<AST::Expression>>>([&]() -> Optional<UniqueRef<AST::Expression>> {
     1099                condition = { WTFMove(*expression) };
     1100            else
     1101                return Unexpected<Error>(expression.error());
     1102            CONSUME_TYPE(secondSemicolon, Semicolon);
     1103        }
     1104
     1105        Optional<UniqueRef<AST::Expression>> increment = WTF::nullopt;
     1106        if (!tryType(Lexer::Token::Type::RightParenthesis)) {
    14331107            if (auto expression = parseExpression())
    1434                 return { WTFMove(*expression) };
    1435             return WTF::nullopt;
    1436         });
    1437 
    1438         auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    1439         if (!rightParenthesis)
    1440             return Unexpected<Error>(rightParenthesis.error());
    1441 
    1442         auto body = parseStatement();
    1443         if (!body)
    1444             return Unexpected<Error>(body.error());
     1108                increment = { WTFMove(*expression) };
     1109            else
     1110                return Unexpected<Error>(expression.error());
     1111            CONSUME_TYPE(rightParenthesis, RightParenthesis);
     1112        }
     1113
     1114        PARSE(body, Statement);
    14451115
    14461116        return AST::ForLoop(WTFMove(*origin), WTFMove(initialization), WTFMove(condition), WTFMove(increment), WTFMove(*body));
    14471117    };
    1448 
    1449     auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis);
    1450     if (!leftParenthesis)
    1451         return Unexpected<Error>(leftParenthesis.error());
    14521118
    14531119    auto variableDeclarations = backtrackingScope<Expected<AST::VariableDeclarationsStatement, Error>>([&]() {
     
    14591125    }
    14601126
    1461     auto effectfulExpression = parseEffectfulExpression();
    1462     if (!effectfulExpression)
    1463         return Unexpected<Error>(effectfulExpression.error());
     1127    PARSE(effectfulExpression, EffectfulExpression);
    14641128
    14651129    return parseRemainder(WTFMove(*effectfulExpression));
     
    14681132auto Parser::parseWhileLoop() -> Expected<AST::WhileLoop, Error>
    14691133{
    1470     auto origin = consumeType(Lexer::Token::Type::While);
    1471     if (!origin)
    1472         return Unexpected<Error>(origin.error());
    1473 
    1474     auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis);
    1475     if (!leftParenthesis)
    1476         return Unexpected<Error>(leftParenthesis.error());
    1477 
    1478     auto conditional = parseExpression();
    1479     if (!conditional)
    1480         return Unexpected<Error>(conditional.error());
    1481 
    1482     auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    1483     if (!rightParenthesis)
    1484         return Unexpected<Error>(rightParenthesis.error());
    1485 
    1486     auto body = parseStatement();
    1487     if (!body)
    1488         return Unexpected<Error>(body.error());
     1134    CONSUME_TYPE(origin, While);
     1135    CONSUME_TYPE(leftParenthesis, LeftParenthesis);
     1136    PARSE(conditional, Expression);
     1137    CONSUME_TYPE(rightParenthesis, RightParenthesis);
     1138    PARSE(body, Statement);
    14891139
    14901140    return AST::WhileLoop(WTFMove(*origin), WTFMove(*conditional), WTFMove(*body));
     
    14931143auto Parser::parseDoWhileLoop() -> Expected<AST::DoWhileLoop, Error>
    14941144{
    1495     auto origin = consumeType(Lexer::Token::Type::Do);
    1496     if (!origin)
    1497         return Unexpected<Error>(origin.error());
    1498 
    1499     auto body = parseStatement();
    1500     if (!body)
    1501         return Unexpected<Error>(body.error());
    1502 
    1503     auto whileKeyword = consumeType(Lexer::Token::Type::While);
    1504     if (!whileKeyword)
    1505         return Unexpected<Error>(whileKeyword.error());
    1506 
    1507     auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis);
    1508     if (!leftParenthesis)
    1509         return Unexpected<Error>(leftParenthesis.error());
    1510 
    1511     auto conditional = parseExpression();
    1512     if (!conditional)
    1513         return Unexpected<Error>(conditional.error());
    1514 
    1515     auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    1516     if (!rightParenthesis)
    1517         return Unexpected<Error>(rightParenthesis.error());
     1145    CONSUME_TYPE(origin, Do);
     1146    PARSE(body, Statement);
     1147    CONSUME_TYPE(whileKeyword, While);
     1148    CONSUME_TYPE(leftParenthesis, LeftParenthesis);
     1149    PARSE(conditional, Expression);
     1150    CONSUME_TYPE(rightParenthesis, RightParenthesis);
     1151    CONSUME_TYPE(semicolon, Semicolon);
    15181152
    15191153    return AST::DoWhileLoop(WTFMove(*origin), WTFMove(*body), WTFMove(*conditional));
     
    15221156auto Parser::parseVariableDeclaration(UniqueRef<AST::UnnamedType>&& type) -> Expected<AST::VariableDeclaration, Error>
    15231157{
    1524     auto origin = peek();
    1525     if (!origin)
    1526         return Unexpected<Error>(origin.error());
     1158    PEEK(origin);
    15271159
    15281160    auto qualifiers = parseQualifiers();
    15291161
    1530     auto name = consumeType(Lexer::Token::Type::Identifier);
    1531     if (!name)
    1532         return Unexpected<Error>(name.error());
    1533 
    1534     if (tryType(Lexer::Token::Type::Colon)) {
    1535         auto semantic = parseSemantic();
    1536         if (!semantic)
    1537             return Unexpected<Error>(semantic.error());
    1538 
    1539         if (tryType(Lexer::Token::Type::EqualsSign)) {
    1540             auto initializer = parseExpression();
    1541             if (!initializer)
    1542                 return Unexpected<Error>(initializer.error());
    1543             return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTFMove(*semantic), WTFMove(*initializer));
    1544         }
    1545 
    1546         return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTFMove(*semantic), WTF::nullopt);
    1547     }
     1162    CONSUME_TYPE(name, Identifier);
     1163    PARSE(semantic, Semantic);
    15481164
    15491165    if (tryType(Lexer::Token::Type::EqualsSign)) {
    1550         auto initializer = parseExpression();
    1551         if (!initializer)
    1552             return Unexpected<Error>(initializer.error());
    1553         return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTF::nullopt, WTFMove(*initializer));
    1554     }
    1555 
    1556     return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTF::nullopt, WTF::nullopt);
     1166        PARSE(initializer, PossibleTernaryConditional);
     1167        return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTFMove(*semantic), WTFMove(*initializer));
     1168    }
     1169
     1170    return AST::VariableDeclaration(WTFMove(*origin), WTFMove(qualifiers), { WTFMove(type) }, name->stringView.toString(), WTFMove(*semantic), WTF::nullopt);
    15571171}
    15581172
    15591173auto Parser::parseVariableDeclarations() -> Expected<AST::VariableDeclarationsStatement, Error>
    15601174{
    1561     auto origin = peek();
    1562     if (!origin)
    1563         return Unexpected<Error>(origin.error());
    1564 
    1565     auto type = parseType();
    1566     if (!type)
    1567         return Unexpected<Error>(type.error());
     1175    PEEK(origin);
     1176
     1177    PARSE(type, Type);
    15681178
    15691179    auto firstVariableDeclaration = parseVariableDeclaration((*type)->clone());
     
    15861196auto Parser::parseStatement() -> Expected<UniqueRef<AST::Statement>, Error>
    15871197{
     1198    PEEK(token);
     1199    switch (token->type) {
     1200    case Lexer::Token::Type::LeftCurlyBracket: {
     1201        PARSE(block, Block);
     1202        return { makeUniqueRef<AST::Block>(WTFMove(*block)) };
     1203    }
     1204    case Lexer::Token::Type::If: {
     1205        PARSE(ifStatement, IfStatement);
     1206        return { makeUniqueRef<AST::IfStatement>(WTFMove(*ifStatement)) };
     1207    }
     1208    case Lexer::Token::Type::Switch: {
     1209        PARSE(switchStatement, SwitchStatement);
     1210        return { makeUniqueRef<AST::SwitchStatement>(WTFMove(*switchStatement)) };
     1211    }
     1212    case Lexer::Token::Type::For: {
     1213        PARSE(forLoop, ForLoop);
     1214        return { makeUniqueRef<AST::ForLoop>(WTFMove(*forLoop)) };
     1215    }
     1216    case Lexer::Token::Type::While: {
     1217        PARSE(whileLoop, WhileLoop);
     1218        return { makeUniqueRef<AST::WhileLoop>(WTFMove(*whileLoop)) };
     1219    }
     1220    case Lexer::Token::Type::Do: {
     1221        PARSE(doWhileLoop, DoWhileLoop);
     1222        return { makeUniqueRef<AST::DoWhileLoop>(WTFMove(*doWhileLoop)) };
     1223    }
     1224    case Lexer::Token::Type::Break: {
     1225        auto breakToken = m_lexer.consumeToken();
     1226        CONSUME_TYPE(semicolon, Semicolon);
     1227        auto breakObject = AST::Break(WTFMove(*breakToken));
     1228        return { makeUniqueRef<AST::Break>(WTFMove(breakObject)) };
     1229    }
     1230    case Lexer::Token::Type::Continue: {
     1231        auto continueToken = m_lexer.consumeToken();
     1232        CONSUME_TYPE(semicolon, Semicolon);
     1233        auto continueObject = AST::Continue(WTFMove(*continueToken));
     1234        return { makeUniqueRef<AST::Continue>(WTFMove(continueObject)) };
     1235    }
     1236    case Lexer::Token::Type::Fallthrough: {
     1237        auto fallthroughToken = m_lexer.consumeToken();
     1238        CONSUME_TYPE(semicolon, Semicolon);
     1239        auto fallthroughObject = AST::Fallthrough(WTFMove(*fallthroughToken));
     1240        return { makeUniqueRef<AST::Fallthrough>(WTFMove(fallthroughObject)) };
     1241    }
     1242    case Lexer::Token::Type::Trap: {
     1243        auto trapToken = m_lexer.consumeToken();
     1244        CONSUME_TYPE(semicolon, Semicolon);
     1245        auto trapObject = AST::Trap(WTFMove(*trapToken));
     1246        return { makeUniqueRef<AST::Trap>(WTFMove(trapObject)) };
     1247    }
     1248    case Lexer::Token::Type::Return: {
     1249        auto returnToken = m_lexer.consumeToken();
     1250        if (auto semicolon = tryType(Lexer::Token::Type::Semicolon)) {
     1251            auto returnObject = AST::Return(WTFMove(*returnToken), WTF::nullopt);
     1252            return { makeUniqueRef<AST::Return>(WTFMove(returnObject)) };
     1253        }
     1254        PARSE(expression, Expression);
     1255        CONSUME_TYPE(finalSemicolon, Semicolon);
     1256        auto returnObject = AST::Return(WTFMove(*returnToken), { WTFMove(*expression) });
     1257        return { makeUniqueRef<AST::Return>(WTFMove(returnObject)) };
     1258    }
     1259    case Lexer::Token::Type::Constant:
     1260    case Lexer::Token::Type::Device:
     1261    case Lexer::Token::Type::Threadgroup:
     1262    case Lexer::Token::Type::Thread: {
     1263        PARSE(variableDeclarations, VariableDeclarations);
     1264        CONSUME_TYPE(semicolon, Semicolon);
     1265        return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) };
     1266    }
     1267    case Lexer::Token::Type::Identifier: {
     1268        PEEK_FURTHER(nextToken);
     1269        switch (nextToken->type) {
     1270        case Lexer::Token::Type::Identifier:
     1271        case Lexer::Token::Type::LessThanSign:
     1272        case Lexer::Token::Type::Star:
     1273        case Lexer::Token::Type::Qualifier: {
     1274            PARSE(variableDeclarations, VariableDeclarations);
     1275            CONSUME_TYPE(semicolon, Semicolon);
     1276            return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) };
     1277        }
     1278        default:
     1279            break;
     1280        }
     1281        break;
     1282    }
     1283    default:
     1284        break;
     1285    }
     1286
    15881287    {
    1589         auto block = backtrackingScope<Expected<AST::Block, Error>>([&]() {
    1590             return parseBlock();
    1591         });
    1592         if (block)
    1593             return { makeUniqueRef<AST::Block>(WTFMove(*block)) };
    1594     }
    1595 
    1596     {
    1597         auto ifStatement = backtrackingScope<Expected<AST::IfStatement, Error>>([&]() {
    1598             return parseIfStatement();
    1599         });
    1600         if (ifStatement)
    1601             return { makeUniqueRef<AST::IfStatement>(WTFMove(*ifStatement)) };
    1602     }
    1603 
    1604     {
    1605         auto switchStatement = backtrackingScope<Expected<AST::SwitchStatement, Error>>([&]() {
    1606             return parseSwitchStatement();
    1607         });
    1608         if (switchStatement)
    1609             return { makeUniqueRef<AST::SwitchStatement>(WTFMove(*switchStatement)) };
    1610     }
    1611 
    1612     {
    1613         auto forLoop = backtrackingScope<Expected<AST::ForLoop, Error>>([&]() {
    1614             return parseForLoop();
    1615         });
    1616         if (forLoop)
    1617             return { makeUniqueRef<AST::ForLoop>(WTFMove(*forLoop)) };
    1618     }
    1619 
    1620     {
    1621         auto whileLoop = backtrackingScope<Expected<AST::WhileLoop, Error>>([&]() {
    1622             return parseWhileLoop();
    1623         });
    1624         if (whileLoop)
    1625             return { makeUniqueRef<AST::WhileLoop>(WTFMove(*whileLoop)) };
    1626     }
    1627 
    1628     {
    1629         auto doWhileLoop = backtrackingScope<Expected<AST::DoWhileLoop, Error>>([&]() -> Expected<AST::DoWhileLoop, Error> {
    1630             auto result = parseDoWhileLoop();
    1631             if (!result)
    1632                 return Unexpected<Error>(result.error());
    1633 
    1634             auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    1635             if (!semicolon)
    1636                 return Unexpected<Error>(semicolon.error());
    1637 
     1288        auto effectfulExpression = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> {
     1289            PARSE(result, EffectfulExpression);
     1290            CONSUME_TYPE(semicolon, Semicolon);
    16381291            return result;
    16391292        });
    1640         if (doWhileLoop)
    1641             return { makeUniqueRef<AST::DoWhileLoop>(WTFMove(*doWhileLoop)) };
    1642     }
    1643 
    1644     {
    1645         auto breakObject = backtrackingScope<Expected<AST::Break, Error>>([&]() -> Expected<AST::Break, Error> {
    1646             auto origin = consumeType(Lexer::Token::Type::Break);
    1647             if (!origin)
    1648                 return Unexpected<Error>(origin.error());
    1649 
    1650             auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    1651             if (!semicolon)
    1652                 return Unexpected<Error>(semicolon.error());
    1653 
    1654             return AST::Break(WTFMove(*origin));
    1655         });
    1656         if (breakObject)
    1657             return { makeUniqueRef<AST::Break>(WTFMove(*breakObject)) };
    1658     }
    1659 
    1660     {
    1661         auto continueObject = backtrackingScope<Expected<AST::Continue, Error>>([&]() -> Expected<AST::Continue, Error> {
    1662             auto origin = consumeType(Lexer::Token::Type::Continue);
    1663             if (!origin)
    1664                 return Unexpected<Error>(origin.error());
    1665 
    1666             auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    1667             if (!semicolon)
    1668                 return Unexpected<Error>(semicolon.error());
    1669 
    1670             return AST::Continue(WTFMove(*origin));
    1671         });
    1672         if (continueObject)
    1673             return { makeUniqueRef<AST::Continue>(WTFMove(*continueObject)) };
    1674     }
    1675 
    1676     {
    1677         auto fallthroughObject = backtrackingScope<Expected<AST::Fallthrough, Error>>([&]() -> Expected<AST::Fallthrough, Error> {
    1678             auto origin = consumeType(Lexer::Token::Type::Fallthrough);
    1679             if (!origin)
    1680                 return Unexpected<Error>(origin.error());
    1681 
    1682             auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    1683             if (!semicolon)
    1684                 return Unexpected<Error>(semicolon.error());
    1685 
    1686             return AST::Fallthrough(WTFMove(*origin));
    1687         });
    1688         if (fallthroughObject)
    1689             return { makeUniqueRef<AST::Fallthrough>(WTFMove(*fallthroughObject)) };
    1690     }
    1691 
    1692     {
    1693         auto trapObject = backtrackingScope<Expected<AST::Trap, Error>>([&]() -> Expected<AST::Trap, Error> {
    1694             auto origin = consumeType(Lexer::Token::Type::Trap);
    1695             if (!origin)
    1696                 return Unexpected<Error>(origin.error());
    1697 
    1698             auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    1699             if (!semicolon)
    1700                 return Unexpected<Error>(semicolon.error());
    1701 
    1702             return AST::Trap(WTFMove(*origin));
    1703         });
    1704         if (trapObject)
    1705             return { makeUniqueRef<AST::Trap>(WTFMove(*trapObject)) };
    1706     }
    1707 
    1708     {
    1709         auto returnObject = backtrackingScope<Expected<AST::Return, Error>>([&]() -> Expected<AST::Return, Error> {
    1710             auto origin = consumeType(Lexer::Token::Type::Return);
    1711             if (!origin)
    1712                 return Unexpected<Error>(origin.error());
    1713 
    1714             if (auto semicolon = tryType(Lexer::Token::Type::Semicolon))
    1715                 return AST::Return(WTFMove(*origin), WTF::nullopt);
    1716 
    1717             auto expression = parseExpression();
    1718             if (!expression)
    1719                 return Unexpected<Error>(expression.error());
    1720 
    1721             auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    1722             if (!semicolon)
    1723                 return Unexpected<Error>(semicolon.error());
    1724 
    1725             return AST::Return(WTFMove(*origin), { WTFMove(*expression) });
    1726         });
    1727         if (returnObject)
    1728             return { makeUniqueRef<AST::Return>(WTFMove(*returnObject)) };
    1729     }
    1730 
    1731     {
    1732         auto variableDeclarations = backtrackingScope<Expected<AST::VariableDeclarationsStatement, Error>>([&]() -> Expected<AST::VariableDeclarationsStatement, Error> {
    1733             auto result = parseVariableDeclarations();
    1734             if (!result)
    1735                 return Unexpected<Error>(result.error());
    1736 
    1737             auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    1738             if (!semicolon)
    1739                 return Unexpected<Error>(semicolon.error());
    1740 
    1741             return result;
    1742         });
    1743         if (variableDeclarations)
    1744             return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) };
    1745     }
    1746 
    1747     auto effectfulExpression = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> {
    1748         auto result = parseEffectfulExpression();
    1749         if (!result)
    1750             return Unexpected<Error>(result.error());
    1751 
    1752         auto semicolon = consumeType(Lexer::Token::Type::Semicolon);
    1753         if (!semicolon)
    1754             return Unexpected<Error>(semicolon.error());
    1755 
    1756         return result;
    1757     });
    1758     if (effectfulExpression)
    1759         return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(*effectfulExpression)) };
    1760 
    1761     return Unexpected<Error>(effectfulExpression.error());
     1293        if (effectfulExpression)
     1294            return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(*effectfulExpression)) };
     1295    }
     1296
     1297    PARSE(variableDeclarations, VariableDeclarations);
     1298    CONSUME_TYPE(semicolon, Semicolon);
     1299    return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) };
    17621300}
    17631301
    17641302auto Parser::parseEffectfulExpression() -> Expected<UniqueRef<AST::Expression>, Error>
    17651303{
    1766     auto origin = peek();
    1767     if (!origin)
    1768         return Unexpected<Error>(origin.error());
     1304    PEEK(origin);
    17691305
    17701306    Vector<UniqueRef<AST::Expression>> expressions;
    1771 
    1772     auto first = backtrackingScope<Optional<UniqueRef<AST::Expression>>>([&]() -> Optional<UniqueRef<AST::Expression>> {
    1773         auto effectfulExpression = parseEffectfulAssignment();
    1774         if (!effectfulExpression)
    1775             return WTF::nullopt;
    1776         return { WTFMove(*effectfulExpression) };
    1777     });
    1778     if (!first)
     1307    if (origin->type == Lexer::Token::Type::Semicolon)
    17791308        return { makeUniqueRef<AST::CommaExpression>(WTFMove(*origin), WTFMove(expressions)) };
    17801309
    1781     expressions.append(WTFMove(*first));
     1310    PARSE(effectfulExpression, EffectfulAssignment);
     1311    expressions.append(WTFMove(*effectfulExpression));
    17821312
    17831313    while (tryType(Lexer::Token::Type::Comma)) {
    1784         auto expression = parseEffectfulAssignment();
    1785         if (!expression)
    1786             return Unexpected<Error>(expression.error());
     1314        PARSE(expression, EffectfulAssignment);
    17871315        expressions.append(WTFMove(*expression));
    17881316    }
     
    17951323auto Parser::parseEffectfulAssignment() -> Expected<UniqueRef<AST::Expression>, Error>
    17961324{
    1797     auto assignment = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() {
    1798         return parseAssignment();
    1799     });
    1800     if (assignment)
    1801         return assignment;
    1802 
    1803     assignment = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() {
    1804         return parseEffectfulPrefix();
    1805     });
    1806     if (assignment)
    1807         return assignment;
    1808 
    1809     return Unexpected<Error>(assignment.error());
    1810 }
    1811 
    1812 auto Parser::parseEffectfulPrefix() -> Expected<UniqueRef<AST::Expression>, Error>
    1813 {
    1814     auto prefix = consumeTypes({ Lexer::Token::Type::PlusPlus, Lexer::Token::Type::MinusMinus });
    1815     if (!prefix)
    1816         return parseEffectfulSuffix();
    1817 
    1818     auto previous = parsePossiblePrefix();
    1819     if (!previous)
    1820         return Unexpected<Error>(previous.error());
    1821 
    1822     switch (prefix->type) {
    1823     case Lexer::Token::Type::PlusPlus: {
    1824         auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*prefix), WTFMove(*previous));
    1825         Vector<UniqueRef<AST::Expression>> callArguments;
    1826         callArguments.append(result->oldVariableReference());
    1827         result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(*prefix), "operator++"_str, WTFMove(callArguments)));
    1828         result->setResultExpression(result->newVariableReference());
    1829         return { WTFMove(result) };
    1830     }
    1831     default: {
    1832         ASSERT(prefix->type == Lexer::Token::Type::MinusMinus);
    1833         auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*prefix), WTFMove(*previous));
    1834         Vector<UniqueRef<AST::Expression>> callArguments;
    1835         callArguments.append(result->oldVariableReference());
    1836         result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(*prefix), "operator--"_str, WTFMove(callArguments)));
    1837         result->setResultExpression(result->newVariableReference());
    1838         return { WTFMove(result) };
    1839     }
    1840     }
    1841 }
    1842 
    1843 auto Parser::parseEffectfulSuffix() -> Expected<UniqueRef<AST::Expression>, Error>
    1844 {
    1845     auto effectfulSuffix = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> {
    1846         auto previous = parsePossibleSuffix();
    1847         if (!previous)
    1848             return Unexpected<Error>(previous.error());
    1849 
    1850         auto suffix = consumeTypes({ Lexer::Token::Type::PlusPlus, Lexer::Token::Type::MinusMinus });
    1851         if (!suffix)
    1852             return Unexpected<Error>(suffix.error());
    1853 
    1854         switch (suffix->type) {
    1855         case Lexer::Token::Type::PlusPlus: {
    1856             auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*suffix), WTFMove(*previous));
    1857             Vector<UniqueRef<AST::Expression>> callArguments;
    1858             callArguments.append(result->oldVariableReference());
    1859             result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(*suffix), "operator++"_str, WTFMove(callArguments)));
    1860             result->setResultExpression(result->oldVariableReference());
    1861             return { WTFMove(result) };
    1862         }
    1863         default: {
    1864             ASSERT(suffix->type == Lexer::Token::Type::MinusMinus);
    1865             auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*suffix), WTFMove(*previous));
    1866             Vector<UniqueRef<AST::Expression>> callArguments;
    1867             callArguments.append(result->oldVariableReference());
    1868             result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(*suffix), "operator--"_str, WTFMove(callArguments)));
    1869             result->setResultExpression(result->oldVariableReference());
    1870             return { WTFMove(result) };
    1871         }
    1872         }
    1873     });
    1874     if (effectfulSuffix)
    1875         return effectfulSuffix;
    1876 
    1877     effectfulSuffix = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() {
    1878         return parseCallExpression();
    1879     });
    1880     if (effectfulSuffix)
    1881         return effectfulSuffix;
    1882 
    1883     effectfulSuffix = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> {
    1884         auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis);
    1885         if (!leftParenthesis)
    1886             return Unexpected<Error>(leftParenthesis.error());
    1887 
    1888         auto expression = parseExpression();
    1889         if (!expression)
    1890             return Unexpected<Error>(expression.error());
    1891 
    1892         auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    1893         if (!rightParenthesis)
    1894             return Unexpected<Error>(rightParenthesis.error());
    1895 
    1896         return { WTFMove(*expression) };
    1897     });
    1898     if (effectfulSuffix)
    1899         return effectfulSuffix;
    1900 
    1901     return Unexpected<Error>(effectfulSuffix.error());
     1325    PEEK(origin);
     1326
     1327    bool isEffectful = false;
     1328    PARSE(expression, PossiblePrefix, &isEffectful);
     1329
     1330    if (!isEffectful || peekTypes({
     1331        Lexer::Token::Type::EqualsSign,
     1332        Lexer::Token::Type::PlusEquals,
     1333        Lexer::Token::Type::MinusEquals,
     1334        Lexer::Token::Type::TimesEquals,
     1335        Lexer::Token::Type::DivideEquals,
     1336        Lexer::Token::Type::ModEquals,
     1337        Lexer::Token::Type::XorEquals,
     1338        Lexer::Token::Type::AndEquals,
     1339        Lexer::Token::Type::OrEquals,
     1340        Lexer::Token::Type::RightShiftEquals,
     1341        Lexer::Token::Type::LeftShiftEquals
     1342    })) {
     1343        return completeAssignment(WTFMove(*origin), WTFMove(*expression));
     1344    }
     1345
     1346    return expression;
    19021347}
    19031348
     
    19821427auto Parser::parseExpression() -> Expected<UniqueRef<AST::Expression>, Error>
    19831428{
    1984     auto origin = peek();
    1985     if (!origin)
    1986         return Unexpected<Error>(origin.error());
    1987 
    1988     auto first = parsePossibleTernaryConditional();
    1989     if (!first)
    1990         return Unexpected<Error>(first.error());
    1991 
     1429    PEEK(origin);
     1430
     1431    PARSE(first, PossibleTernaryConditional);
    19921432    Vector<UniqueRef<AST::Expression>> expressions;
    19931433    expressions.append(WTFMove(*first));
    19941434
    19951435    while (tryType(Lexer::Token::Type::Comma)) {
    1996         auto expression = parsePossibleTernaryConditional();
    1997         if (!expression)
    1998             return Unexpected<Error>(expression.error());
     1436        PARSE(expression, PossibleTernaryConditional);
    19991437        expressions.append(WTFMove(*expression));
    20001438    }
     
    20051443}
    20061444
    2007 auto Parser::parseTernaryConditional() -> Expected<UniqueRef<AST::Expression>, Error>
    2008 {
    2009     auto origin = peek();
    2010     if (!origin)
    2011         return Unexpected<Error>(origin.error());
    2012 
    2013     auto predicate = parsePossibleLogicalBinaryOperation();
    2014     if (!predicate)
    2015         return Unexpected<Error>(predicate.error());
    2016 
    2017     auto questionMark = consumeType(Lexer::Token::Type::QuestionMark);
    2018     if (!questionMark)
    2019         return Unexpected<Error>(questionMark.error());
    2020 
    2021     auto bodyExpression = parseExpression();
    2022     if (!bodyExpression)
    2023         return Unexpected<Error>(bodyExpression.error());
    2024 
    2025     auto colon = consumeType(Lexer::Token::Type::Colon);
    2026     if (!colon)
    2027         return Unexpected<Error>(colon.error());
    2028 
    2029     auto elseExpression = parsePossibleTernaryConditional();
    2030     if (!elseExpression)
    2031         return Unexpected<Error>(elseExpression.error());
     1445auto Parser::completeTernaryConditional(Lexer::Token&& origin, UniqueRef<AST::Expression>&& predicate) -> Expected<UniqueRef<AST::Expression>, Error>
     1446{
     1447    CONSUME_TYPE(questionMark, QuestionMark);
     1448    PARSE(bodyExpression, Expression);
     1449    CONSUME_TYPE(colon, Colon);
     1450    PARSE(elseExpression, PossibleTernaryConditional);
    20321451
    20331452    Vector<UniqueRef<AST::Expression>> castArguments;
    2034     castArguments.append(WTFMove(*predicate));
    2035     auto boolCast = makeUniqueRef<AST::CallExpression>(Lexer::Token(*origin), "bool"_str, WTFMove(castArguments));
    2036     return { makeUniqueRef<AST::TernaryExpression>(WTFMove(*origin), WTFMove(boolCast), WTFMove(*bodyExpression), WTFMove(*elseExpression)) };
    2037 }
    2038 
    2039 auto Parser::parseAssignment() -> Expected<UniqueRef<AST::Expression>, Error>
    2040 {
    2041     auto origin = peek();
    2042     if (!origin)
    2043         return Unexpected<Error>(origin.error());
    2044 
    2045     auto left = parsePossiblePrefix();
    2046     if (!left)
    2047         return Unexpected<Error>(left.error());
    2048 
     1453    castArguments.append(WTFMove(predicate));
     1454    auto boolCast = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), "bool"_str, WTFMove(castArguments));
     1455    return { makeUniqueRef<AST::TernaryExpression>(WTFMove(origin), WTFMove(boolCast), WTFMove(*bodyExpression), WTFMove(*elseExpression)) };
     1456}
     1457
     1458auto Parser::completeAssignment(Lexer::Token&& origin, UniqueRef<AST::Expression>&& left) -> Expected<UniqueRef<AST::Expression>, Error>
     1459{
    20491460    auto assignmentOperator = consumeTypes({
    20501461        Lexer::Token::Type::EqualsSign,
     
    20631474        return Unexpected<Error>(assignmentOperator.error());
    20641475
    2065     auto right = parsePossibleTernaryConditional();
    2066     if (!right)
    2067         return Unexpected<Error>(right.error());
     1476    PARSE(right, PossibleTernaryConditional);
    20681477
    20691478    if (assignmentOperator->type == Lexer::Token::Type::EqualsSign)
    2070         return { makeUniqueRef<AST::AssignmentExpression>(WTFMove(*origin), WTFMove(*left), WTFMove(*right))};
     1479        return { makeUniqueRef<AST::AssignmentExpression>(WTFMove(origin), WTFMove(left), WTFMove(*right))};
    20711480
    20721481    String name;
     
    21051514    }
    21061515
    2107     auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*origin), WTFMove(*left));
     1516    auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(origin), WTFMove(left));
    21081517    Vector<UniqueRef<AST::Expression>> callArguments;
    21091518    callArguments.append(result->oldVariableReference());
    21101519    callArguments.append(WTFMove(*right));
    2111     result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(*origin), WTFMove(name), WTFMove(callArguments)));
     1520    result->setNewValueExpression(makeUniqueRef<AST::CallExpression>(WTFMove(origin), WTFMove(name), WTFMove(callArguments)));
    21121521    result->setResultExpression(result->newVariableReference());
    21131522    return { WTFMove(result) };
     
    21161525auto Parser::parsePossibleTernaryConditional() -> Expected<UniqueRef<AST::Expression>, Error>
    21171526{
    2118     auto ternaryExpression = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() {
    2119         return parseTernaryConditional();
    2120     });
    2121     if (ternaryExpression)
    2122         return ternaryExpression;
    2123 
    2124     auto assignmentExpression = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() {
    2125         return parseAssignment();
    2126     });
    2127     if (assignmentExpression)
    2128         return assignmentExpression;
    2129 
    2130     auto binaryOperation = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() {
    2131         return parsePossibleLogicalBinaryOperation();
    2132     });
    2133     if (binaryOperation)
    2134         return binaryOperation;
    2135 
    2136     return Unexpected<Error>(binaryOperation.error());
     1527    PEEK(origin);
     1528
     1529    PARSE(expression, PossiblePrefix);
     1530
     1531    if (peekTypes({Lexer::Token::Type::EqualsSign,
     1532        Lexer::Token::Type::PlusEquals,
     1533        Lexer::Token::Type::MinusEquals,
     1534        Lexer::Token::Type::TimesEquals,
     1535        Lexer::Token::Type::DivideEquals,
     1536        Lexer::Token::Type::ModEquals,
     1537        Lexer::Token::Type::XorEquals,
     1538        Lexer::Token::Type::AndEquals,
     1539        Lexer::Token::Type::OrEquals,
     1540        Lexer::Token::Type::RightShiftEquals,
     1541        Lexer::Token::Type::LeftShiftEquals})) {
     1542        return completeAssignment(WTFMove(*origin), WTFMove(*expression));
     1543    }
     1544
     1545    expression = completePossibleShift(WTFMove(*expression));
     1546    expression = completePossibleMultiply(WTFMove(*expression));
     1547    expression = completePossibleAdd(WTFMove(*expression));
     1548    expression = completePossibleRelationalBinaryOperation(WTFMove(*expression));
     1549    expression = completePossibleLogicalBinaryOperation(WTFMove(*expression));
     1550
     1551    PEEK(nextToken);
     1552    if (nextToken->type == Lexer::Token::Type::QuestionMark)
     1553        return completeTernaryConditional(WTFMove(*origin), WTFMove(*expression));
     1554    return expression;
    21371555}
    21381556
    21391557auto Parser::parsePossibleLogicalBinaryOperation() -> Expected<UniqueRef<AST::Expression>, Error>
    21401558{
    2141     auto parsedPrevious = parsePossibleRelationalBinaryOperation();
    2142     if (!parsedPrevious)
    2143         return Unexpected<Error>(parsedPrevious.error());
    2144     UniqueRef<AST::Expression> previous = WTFMove(*parsedPrevious);
    2145 
     1559    PARSE(parsedPrevious, PossibleRelationalBinaryOperation);
     1560    return completePossibleLogicalBinaryOperation(WTFMove(*parsedPrevious));
     1561}
     1562
     1563auto Parser::completePossibleLogicalBinaryOperation(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error>
     1564{
    21461565    while (auto logicalBinaryOperation = tryTypes({
    21471566        Lexer::Token::Type::OrOr,
     
    21511570        Lexer::Token::Type::And
    21521571        })) {
    2153         auto next = parsePossibleRelationalBinaryOperation();
    2154         if (!next)
    2155             return Unexpected<Error>(next.error());
     1572        PARSE(next, PossibleRelationalBinaryOperation);
    21561573
    21571574        switch (logicalBinaryOperation->type) {
     
    21921609auto Parser::parsePossibleRelationalBinaryOperation() -> Expected<UniqueRef<AST::Expression>, Error>
    21931610{
    2194     auto parsedPrevious = parsePossibleShift();
    2195     if (!parsedPrevious)
    2196         return Unexpected<Error>(parsedPrevious.error());
    2197     UniqueRef<AST::Expression> previous = WTFMove(*parsedPrevious);
    2198 
     1611    PARSE(parsedPrevious, PossibleShift);
     1612    return completePossibleRelationalBinaryOperation(WTFMove(*parsedPrevious));
     1613}
     1614
     1615auto Parser::completePossibleRelationalBinaryOperation(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error>
     1616{
    21991617    while (auto relationalBinaryOperation = tryTypes({
    22001618        Lexer::Token::Type::LessThanSign,
     
    22051623        Lexer::Token::Type::NotEqual
    22061624        })) {
    2207         auto next = parsePossibleShift();
    2208         if (!next)
    2209             return Unexpected<Error>(next.error());
     1625        PARSE(next, PossibleShift);
     1626
     1627        Vector<UniqueRef<AST::Expression>> callArguments;
     1628        callArguments.append(WTFMove(previous));
     1629        callArguments.append(WTFMove(*next));
    22101630
    22111631        switch (relationalBinaryOperation->type) {
    22121632        case Lexer::Token::Type::LessThanSign: {
    2213             Vector<UniqueRef<AST::Expression>> callArguments;
    2214             callArguments.append(WTFMove(previous));
    2215             callArguments.append(WTFMove(*next));
    22161633            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*relationalBinaryOperation), "operator<"_str, WTFMove(callArguments));
    22171634            break;
    22181635        }
    22191636        case Lexer::Token::Type::GreaterThanSign: {
    2220             Vector<UniqueRef<AST::Expression>> callArguments;
    2221             callArguments.append(WTFMove(previous));
    2222             callArguments.append(WTFMove(*next));
    22231637            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*relationalBinaryOperation), "operator>"_str, WTFMove(callArguments));
    22241638            break;
    22251639        }
    22261640        case Lexer::Token::Type::LessThanOrEqualTo: {
    2227             Vector<UniqueRef<AST::Expression>> callArguments;
    2228             callArguments.append(WTFMove(previous));
    2229             callArguments.append(WTFMove(*next));
    22301641            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*relationalBinaryOperation), "operator<="_str, WTFMove(callArguments));
    22311642            break;
    22321643        }
    22331644        case Lexer::Token::Type::GreaterThanOrEqualTo: {
    2234             Vector<UniqueRef<AST::Expression>> callArguments;
    2235             callArguments.append(WTFMove(previous));
    2236             callArguments.append(WTFMove(*next));
    22371645            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*relationalBinaryOperation), "operator>="_str, WTFMove(callArguments));
    22381646            break;
    22391647        }
    22401648        case Lexer::Token::Type::EqualComparison: {
    2241             Vector<UniqueRef<AST::Expression>> callArguments;
    2242             callArguments.append(WTFMove(previous));
    2243             callArguments.append(WTFMove(*next));
    22441649            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*relationalBinaryOperation), "operator=="_str, WTFMove(callArguments));
    22451650            break;
     
    22471652        default: {
    22481653            ASSERT(relationalBinaryOperation->type == Lexer::Token::Type::NotEqual);
    2249             Vector<UniqueRef<AST::Expression>> callArguments;
    2250             callArguments.append(WTFMove(previous));
    2251             callArguments.append(WTFMove(*next));
    22521654            previous = makeUniqueRef<AST::CallExpression>(Lexer::Token(*relationalBinaryOperation), "operator=="_str, WTFMove(callArguments));
    22531655            previous = makeUniqueRef<AST::LogicalNotExpression>(WTFMove(*relationalBinaryOperation), WTFMove(previous));
     
    22621664auto Parser::parsePossibleShift() -> Expected<UniqueRef<AST::Expression>, Error>
    22631665{
    2264     auto parsedPrevious = parsePossibleAdd();
    2265     if (!parsedPrevious)
    2266         return Unexpected<Error>(parsedPrevious.error());
    2267     UniqueRef<AST::Expression> previous = WTFMove(*parsedPrevious);
    2268 
     1666    PARSE(parsedPrevious, PossibleAdd);
     1667    return completePossibleShift(WTFMove(*parsedPrevious));
     1668}
     1669
     1670auto Parser::completePossibleShift(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error>
     1671{
    22691672    while (auto shift = tryTypes({
    22701673        Lexer::Token::Type::LeftShift,
    22711674        Lexer::Token::Type::RightShift
    22721675        })) {
    2273         auto next = parsePossibleAdd();
    2274         if (!next)
    2275             return Unexpected<Error>(next.error());
     1676        PARSE(next, PossibleAdd);
     1677
     1678        Vector<UniqueRef<AST::Expression>> callArguments;
     1679        callArguments.append(WTFMove(previous));
     1680        callArguments.append(WTFMove(*next));
    22761681
    22771682        switch (shift->type) {
    22781683        case Lexer::Token::Type::LeftShift: {
    2279             Vector<UniqueRef<AST::Expression>> callArguments;
    2280             callArguments.append(WTFMove(previous));
    2281             callArguments.append(WTFMove(*next));
    22821684            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*shift), "operator<<"_str, WTFMove(callArguments));
    22831685            break;
     
    22851687        default: {
    22861688            ASSERT(shift->type == Lexer::Token::Type::RightShift);
    2287             Vector<UniqueRef<AST::Expression>> callArguments;
    2288             callArguments.append(WTFMove(previous));
    2289             callArguments.append(WTFMove(*next));
    22901689            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*shift), "operator>>"_str, WTFMove(callArguments));
    22911690            break;
     
    22991698auto Parser::parsePossibleAdd() -> Expected<UniqueRef<AST::Expression>, Error>
    23001699{
    2301     auto parsedPrevious = parsePossibleMultiply();
    2302     if (!parsedPrevious)
    2303         return Unexpected<Error>(parsedPrevious.error());
    2304     UniqueRef<AST::Expression> previous = WTFMove(*parsedPrevious);
    2305 
     1700    PARSE(parsedPrevious, PossibleMultiply);
     1701    return completePossibleAdd(WTFMove(*parsedPrevious));
     1702}
     1703
     1704auto Parser::completePossibleAdd(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error>
     1705{
    23061706    while (auto add = tryTypes({
    23071707        Lexer::Token::Type::Plus,
    23081708        Lexer::Token::Type::Minus
    23091709        })) {
    2310         auto next = parsePossibleMultiply();
    2311         if (!next)
    2312             return Unexpected<Error>(next.error());
     1710        PARSE(next, PossibleMultiply);
     1711
     1712        Vector<UniqueRef<AST::Expression>> callArguments;
     1713        callArguments.append(WTFMove(previous));
     1714        callArguments.append(WTFMove(*next));
    23131715
    23141716        switch (add->type) {
    23151717        case Lexer::Token::Type::Plus: {
    2316             Vector<UniqueRef<AST::Expression>> callArguments;
    2317             callArguments.append(WTFMove(previous));
    2318             callArguments.append(WTFMove(*next));
    23191718            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*add), "operator+"_str, WTFMove(callArguments));
    23201719            break;
     
    23221721        default: {
    23231722            ASSERT(add->type == Lexer::Token::Type::Minus);
    2324             Vector<UniqueRef<AST::Expression>> callArguments;
    2325             callArguments.append(WTFMove(previous));
    2326             callArguments.append(WTFMove(*next));
    23271723            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*add), "operator-"_str, WTFMove(callArguments));
    23281724            break;
     
    23361732auto Parser::parsePossibleMultiply() -> Expected<UniqueRef<AST::Expression>, Error>
    23371733{
    2338     auto parsedPrevious = parsePossiblePrefix();
    2339     if (!parsedPrevious)
    2340         return Unexpected<Error>(parsedPrevious.error());
    2341     UniqueRef<AST::Expression> previous = WTFMove(*parsedPrevious);
    2342 
     1734    PARSE(parsedPrevious, PossiblePrefix);
     1735    return completePossibleMultiply(WTFMove(*parsedPrevious));
     1736}
     1737
     1738auto Parser::completePossibleMultiply(UniqueRef<AST::Expression>&& previous) -> Expected<UniqueRef<AST::Expression>, Error>
     1739{
    23431740    while (auto multiply = tryTypes({
    23441741        Lexer::Token::Type::Star,
     
    23461743        Lexer::Token::Type::Mod
    23471744        })) {
    2348         auto next = parsePossiblePrefix();
    2349         if (!next)
    2350             return Unexpected<Error>(next.error());
     1745        PARSE(next, PossiblePrefix);
     1746
     1747        Vector<UniqueRef<AST::Expression>> callArguments;
     1748        callArguments.append(WTFMove(previous));
     1749        callArguments.append(WTFMove(*next));
    23511750
    23521751        switch (multiply->type) {
    23531752        case Lexer::Token::Type::Star: {
    2354             Vector<UniqueRef<AST::Expression>> callArguments;
    2355             callArguments.append(WTFMove(previous));
    2356             callArguments.append(WTFMove(*next));
    23571753            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*multiply), "operator*"_str, WTFMove(callArguments));
    23581754            break;
    23591755        }
    23601756        case Lexer::Token::Type::Divide: {
    2361             Vector<UniqueRef<AST::Expression>> callArguments;
    2362             callArguments.append(WTFMove(previous));
    2363             callArguments.append(WTFMove(*next));
    23641757            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*multiply), "operator/"_str, WTFMove(callArguments));
    23651758            break;
     
    23671760        default: {
    23681761            ASSERT(multiply->type == Lexer::Token::Type::Mod);
    2369             Vector<UniqueRef<AST::Expression>> callArguments;
    2370             callArguments.append(WTFMove(previous));
    2371             callArguments.append(WTFMove(*next));
    23721762            previous = makeUniqueRef<AST::CallExpression>(WTFMove(*multiply), "operator%"_str, WTFMove(callArguments));
    23731763            break;
     
    23791769}
    23801770
    2381 auto Parser::parsePossiblePrefix() -> Expected<UniqueRef<AST::Expression>, Error>
     1771auto Parser::parsePossiblePrefix(bool *isEffectful) -> Expected<UniqueRef<AST::Expression>, Error>
    23821772{
    23831773    if (auto prefix = tryTypes({
     
    23921782        Lexer::Token::Type::Star
    23931783    })) {
    2394         auto next = parsePossiblePrefix();
    2395         if (!next)
    2396             return Unexpected<Error>(next.error());
     1784        PARSE(next, PossiblePrefix);
    23971785
    23981786        switch (prefix->type) {
    23991787        case Lexer::Token::Type::PlusPlus: {
     1788            if (isEffectful)
     1789                *isEffectful = true;
    24001790            auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*prefix), WTFMove(*next));
    24011791            Vector<UniqueRef<AST::Expression>> callArguments;
     
    24061796        }
    24071797        case Lexer::Token::Type::MinusMinus: {
     1798            if (isEffectful)
     1799                *isEffectful = true;
    24081800            auto result = AST::ReadModifyWriteExpression::create(Lexer::Token(*prefix), WTFMove(*next));
    24091801            Vector<UniqueRef<AST::Expression>> callArguments;
     
    24441836    }
    24451837
    2446     return parsePossibleSuffix();
    2447 }
    2448 
    2449 auto Parser::parsePossibleSuffix() -> Expected<UniqueRef<AST::Expression>, Error>
    2450 {
    2451     auto suffix = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> {
    2452         auto expression = parseCallExpression();
    2453         if (!expression)
    2454             return Unexpected<Error>(expression.error());
    2455 
     1838    return parsePossibleSuffix(isEffectful);
     1839}
     1840
     1841auto Parser::parsePossibleSuffix(bool *isEffectful) -> Expected<UniqueRef<AST::Expression>, Error>
     1842{
     1843    PEEK(token);
     1844    PEEK_FURTHER(nextToken);
     1845
     1846    if (token->type == Lexer::Token::Type::Identifier && nextToken->type == Lexer::Token::Type::LeftParenthesis) {
     1847        PARSE(expression, CallExpression);
     1848        if (isEffectful)
     1849            *isEffectful = true;
    24561850        while (true) {
    2457             auto result = backtrackingScope<SuffixExpression>([&]() -> SuffixExpression {
    2458                 return parseLimitedSuffixOperator(WTFMove(*expression));
    2459             });
     1851            PEEK(suffixToken);
     1852            if (suffixToken->type != Lexer::Token::Type::FullStop && suffixToken->type != Lexer::Token::Type::Arrow && suffixToken->type != Lexer::Token::Type::LeftSquareBracket)
     1853                break;
     1854            auto result = parseLimitedSuffixOperator(WTFMove(*expression));
    24601855            expression = WTFMove(result.result);
    2461             if (!result)
    2462                 break;
    24631856        }
    24641857        return expression;
    2465     });
    2466     if (suffix)
    2467         return suffix;
    2468 
    2469     suffix = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> {
    2470         auto expression = parseTerm();
    2471         if (!expression)
    2472             return Unexpected<Error>(expression.error());
    2473 
    2474         while (true) {
    2475             auto result = backtrackingScope<SuffixExpression>([&]() -> SuffixExpression {
    2476                 return parseSuffixOperator(WTFMove(*expression));
    2477             });
    2478             expression = WTFMove(result.result);
    2479             if (!result)
    2480                 break;
    2481         }
    2482         return expression;
    2483     });
    2484     if (suffix)
    2485         return suffix;
    2486 
    2487     return Unexpected<Error>(suffix.error());
     1858    }
     1859
     1860    if (token->type == Lexer::Token::Type::LeftParenthesis && isEffectful)
     1861        *isEffectful = true;
     1862
     1863    PARSE(expression, Term);
     1864    bool isLastSuffixTokenEffectful = false;
     1865    while (true) {
     1866        PEEK(suffixToken);
     1867        if (suffixToken->type != Lexer::Token::Type::FullStop
     1868            && suffixToken->type != Lexer::Token::Type::Arrow
     1869            && suffixToken->type != Lexer::Token::Type::LeftSquareBracket
     1870            && suffixToken->type != Lexer::Token::Type::PlusPlus
     1871            && suffixToken->type != Lexer::Token::Type::MinusMinus) {
     1872            break;
     1873        }
     1874        isLastSuffixTokenEffectful = suffixToken->type == Lexer::Token::Type::PlusPlus || suffixToken->type == Lexer::Token::Type::MinusMinus;
     1875        auto result = parseSuffixOperator(WTFMove(*expression));
     1876        expression = WTFMove(result.result);
     1877    }
     1878    if (isLastSuffixTokenEffectful && isEffectful)
     1879        *isEffectful = true;
     1880    return expression;
    24881881}
    24891882
    24901883auto Parser::parseCallExpression() -> Expected<UniqueRef<AST::Expression>, Error>
    24911884{
    2492     auto name = consumeType(Lexer::Token::Type::Identifier);
    2493     if (!name)
    2494         return Unexpected<Error>(name.error());
     1885    CONSUME_TYPE(name, Identifier);
    24951886    auto callName = name->stringView.toString();
    24961887
    2497     auto leftParenthesis = consumeType(Lexer::Token::Type::LeftParenthesis);
    2498     if (!leftParenthesis)
    2499         return Unexpected<Error>(leftParenthesis.error());
     1888    CONSUME_TYPE(leftParenthesis, LeftParenthesis);
    25001889
    25011890    Vector<UniqueRef<AST::Expression>> arguments;
     
    25031892        return { makeUniqueRef<AST::CallExpression>(WTFMove(*name), WTFMove(callName), WTFMove(arguments)) };
    25041893
    2505     auto firstArgument = parsePossibleTernaryConditional();
    2506     if (!firstArgument)
    2507         return Unexpected<Error>(firstArgument.error());
     1894    PARSE(firstArgument, PossibleTernaryConditional);
    25081895    arguments.append(WTFMove(*firstArgument));
    25091896    while (tryType(Lexer::Token::Type::Comma)) {
    2510         auto argument = parsePossibleTernaryConditional();
    2511         if (!argument)
    2512             return Unexpected<Error>(argument.error());
     1897        PARSE(argument, PossibleTernaryConditional);
    25131898        arguments.append(WTFMove(*argument));
    25141899    }
    25151900
    2516     auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    2517     if (!rightParenthesis)
    2518         return Unexpected<Error>(rightParenthesis.error());
     1901    CONSUME_TYPE(rightParenthesis, RightParenthesis);
    25191902
    25201903    return { makeUniqueRef<AST::CallExpression>(WTFMove(*name), WTFMove(callName), WTFMove(arguments)) };
     
    25671950    default: {
    25681951        ASSERT(type->type == Lexer::Token::Type::LeftParenthesis);
    2569         auto expression = parseExpression();
    2570         if (!expression)
    2571             return Unexpected<Error>(expression.error());
    2572 
    2573         auto rightParenthesis = consumeType(Lexer::Token::Type::RightParenthesis);
    2574         if (!rightParenthesis)
    2575             return Unexpected<Error>(rightParenthesis.error());
     1952        PARSE(expression, Expression);
     1953        CONSUME_TYPE(rightParenthesis, RightParenthesis);
    25761954
    25771955        return { WTFMove(*expression) };
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h

    r246108 r246135  
    9797#include <wtf/Expected.h>
    9898#include <wtf/Optional.h>
     99#include <wtf/PrintStream.h>
    99100
    100101namespace WebCore {
     
    116117
    117118        String error;
     119
     120        void dump(PrintStream& out) const
     121        {
     122            out.print(error);
     123        }
    118124    };
    119125
     
    121127
    122128private:
     129    // FIXME: We should not need this
     130    // https://bugs.webkit.org/show_bug.cgi?id=198357
    123131    template<typename T> T backtrackingScope(std::function<T()> callback)
    124132    {
     
    137145    Unexpected<Error> fail(const String& message, TryToPeek = TryToPeek::Yes);
    138146    Expected<Lexer::Token, Error> peek();
     147    Expected<Lexer::Token, Error> peekFurther();
     148    bool peekTypes(const Vector<Lexer::Token::Type>&);
    139149    Optional<Lexer::Token> tryType(Lexer::Token::Type);
    140     Optional<Lexer::Token> tryTypes(Vector<Lexer::Token::Type>);
     150    Optional<Lexer::Token> tryTypes(const Vector<Lexer::Token::Type>&);
    141151    Expected<Lexer::Token, Error> consumeType(Lexer::Token::Type);
    142     Expected<Lexer::Token, Error> consumeTypes(Vector<Lexer::Token::Type>);
     152    Expected<Lexer::Token, Error> consumeTypes(const Vector<Lexer::Token::Type>&);
    143153
    144154    Expected<Variant<int, unsigned>, Error> consumeIntegralLiteral();
     
    166176    Expected<AST::SpecializationConstantSemantic, Error> parseSpecializationConstantSemantic();
    167177    Expected<AST::StageInOutSemantic, Error> parseStageInOutSemantic();
    168     Expected<AST::Semantic, Error> parseSemantic();
     178    Expected<Optional<AST::Semantic>, Error> parseSemantic();
    169179    AST::Qualifiers parseQualifiers();
    170180    Expected<AST::StructureElement, Error> parseStructureElement();
     
    177187    Expected<AST::VariableDeclaration, Error> parseParameter();
    178188    Expected<AST::VariableDeclarations, Error> parseParameters();
    179     Expected<AST::FunctionDeclaration, Error> parseEntryPointFunctionDeclaration();
     189    Expected<AST::FunctionDeclaration, Error> parseComputeFunctionDeclaration();
     190    Expected<AST::FunctionDeclaration, Error> parseVertexOrFragmentFunctionDeclaration();
    180191    Expected<AST::FunctionDeclaration, Error> parseRegularFunctionDeclaration();
    181192    Expected<AST::FunctionDeclaration, Error> parseOperatorFunctionDeclaration();
     
    185196
    186197    Expected<AST::Block, Error> parseBlock();
    187     AST::Block parseBlockBody(Lexer::Token&& origin);
     198    Expected<AST::Block, Error> parseBlockBody(Lexer::Token&& origin);
    188199    Expected<AST::IfStatement, Error> parseIfStatement();
    189200    Expected<AST::SwitchStatement, Error> parseSwitchStatement();
     
    198209    Expected<UniqueRef<AST::Expression>, Error> parseEffectfulExpression();
    199210    Expected<UniqueRef<AST::Expression>, Error> parseEffectfulAssignment();
    200     Expected<UniqueRef<AST::Expression>, Error> parseEffectfulPrefix();
    201     Expected<UniqueRef<AST::Expression>, Error> parseEffectfulSuffix();
    202211    struct SuffixExpression {
    203212        SuffixExpression(UniqueRef<AST::Expression>&& result, bool success)
     
    215224
    216225    Expected<UniqueRef<AST::Expression>, Error> parseExpression();
    217     Expected<UniqueRef<AST::Expression>, Error> parseTernaryConditional();
    218     Expected<UniqueRef<AST::Expression>, Error> parseAssignment();
    219226    Expected<UniqueRef<AST::Expression>, Error> parsePossibleTernaryConditional();
     227    Expected<UniqueRef<AST::Expression>, Error> completeTernaryConditional(Lexer::Token&& origin, UniqueRef<AST::Expression>&& predicate);
     228    Expected<UniqueRef<AST::Expression>, Error> completeAssignment(Lexer::Token&& origin, UniqueRef<AST::Expression>&& left);
    220229    Expected<UniqueRef<AST::Expression>, Error> parsePossibleLogicalBinaryOperation();
     230    Expected<UniqueRef<AST::Expression>, Error> completePossibleLogicalBinaryOperation(UniqueRef<AST::Expression>&& previous);
    221231    Expected<UniqueRef<AST::Expression>, Error> parsePossibleRelationalBinaryOperation();
     232    Expected<UniqueRef<AST::Expression>, Error> completePossibleRelationalBinaryOperation(UniqueRef<AST::Expression>&& previous);
    222233    Expected<UniqueRef<AST::Expression>, Error> parsePossibleShift();
     234    Expected<UniqueRef<AST::Expression>, Error> completePossibleShift(UniqueRef<AST::Expression>&& previous);
    223235    Expected<UniqueRef<AST::Expression>, Error> parsePossibleAdd();
     236    Expected<UniqueRef<AST::Expression>, Error> completePossibleAdd(UniqueRef<AST::Expression>&& previous);
    224237    Expected<UniqueRef<AST::Expression>, Error> parsePossibleMultiply();
    225     Expected<UniqueRef<AST::Expression>, Error> parsePossiblePrefix();
    226     Expected<UniqueRef<AST::Expression>, Error> parsePossibleSuffix();
     238    Expected<UniqueRef<AST::Expression>, Error> completePossibleMultiply(UniqueRef<AST::Expression>&& previous);
     239    Expected<UniqueRef<AST::Expression>, Error> parsePossiblePrefix(bool *isEffectful = nullptr);
     240    Expected<UniqueRef<AST::Expression>, Error> parsePossibleSuffix(bool *isEffectful = nullptr);
    227241    Expected<UniqueRef<AST::Expression>, Error> parseCallExpression();
    228242    Expected<UniqueRef<AST::Expression>, Error> parseTerm();
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp

    r246121 r246135  
    5959static constexpr bool dumpASTAfterParsing = false;
    6060static constexpr bool dumpASTAtEnd = false;
    61 static constexpr bool alwaysDumpPassFailures = false;
     61static constexpr bool alwaysDumpPassFailures = true;
    6262static constexpr bool dumpPassFailure = dumpASTBeforeEachPass || dumpASTAfterParsing || dumpASTAtEnd || alwaysDumpPassFailures;
    6363
     
    104104    Parser parser;
    105105    auto standardLibrary = String::fromUTF8(WHLSLStandardLibrary, sizeof(WHLSLStandardLibrary));
    106     auto failure = static_cast<bool>(parser.parse(program, standardLibrary, Parser::Mode::StandardLibrary));
    107     ASSERT_UNUSED(failure, !failure);
    108     if (parser.parse(program, whlslSource, Parser::Mode::User))
     106    auto parseStdLibFailure = parser.parse(program, standardLibrary, Parser::Mode::StandardLibrary);
     107    if (!ASSERT_DISABLED && parseStdLibFailure) {
     108        dataLogLn("failed to parse the standard library: ", *parseStdLibFailure);
     109        RELEASE_ASSERT_NOT_REACHED();
     110    }
     111    if (auto parseFailure = parser.parse(program, whlslSource, Parser::Mode::User)) {
     112        if (dumpPassFailure)
     113            dataLogLn("failed to parse the program: ", *parseFailure);
    109114        return WTF::nullopt;
     115    }
    110116
    111117    if (!dumpASTBetweenEachPassIfNeeded(program, "AST after parsing"))
Note: See TracChangeset for help on using the changeset viewer.