Coverage Report

Created: 2024-05-20 07:14

/src/skia/src/sksl/SkSLParser.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2021 Google LLC.
3
 *
4
 * Use of this source code is governed by a BSD-style license that can be
5
 * found in the LICENSE file.
6
 */
7
8
#include "src/sksl/SkSLParser.h"
9
10
#include "include/core/SkSpan.h"
11
#include "include/private/base/SkTArray.h"
12
#include "include/sksl/SkSLVersion.h"
13
#include "src/base/SkEnumBitMask.h"
14
#include "src/base/SkNoDestructor.h"
15
#include "src/core/SkTHash.h"
16
#include "src/sksl/SkSLBuiltinTypes.h"
17
#include "src/sksl/SkSLCompiler.h"
18
#include "src/sksl/SkSLConstantFolder.h"
19
#include "src/sksl/SkSLContext.h"
20
#include "src/sksl/SkSLErrorReporter.h"
21
#include "src/sksl/SkSLOperator.h"
22
#include "src/sksl/SkSLString.h"
23
#include "src/sksl/ir/SkSLBinaryExpression.h"
24
#include "src/sksl/ir/SkSLBlock.h"
25
#include "src/sksl/ir/SkSLBreakStatement.h"
26
#include "src/sksl/ir/SkSLContinueStatement.h"
27
#include "src/sksl/ir/SkSLDiscardStatement.h"
28
#include "src/sksl/ir/SkSLDoStatement.h"
29
#include "src/sksl/ir/SkSLExpression.h"
30
#include "src/sksl/ir/SkSLExpressionStatement.h"
31
#include "src/sksl/ir/SkSLExtension.h"
32
#include "src/sksl/ir/SkSLFieldAccess.h"
33
#include "src/sksl/ir/SkSLForStatement.h"
34
#include "src/sksl/ir/SkSLFunctionCall.h"
35
#include "src/sksl/ir/SkSLFunctionDeclaration.h"
36
#include "src/sksl/ir/SkSLFunctionDefinition.h"
37
#include "src/sksl/ir/SkSLFunctionPrototype.h"
38
#include "src/sksl/ir/SkSLIfStatement.h"
39
#include "src/sksl/ir/SkSLIndexExpression.h"
40
#include "src/sksl/ir/SkSLInterfaceBlock.h"
41
#include "src/sksl/ir/SkSLLayout.h"
42
#include "src/sksl/ir/SkSLLiteral.h"
43
#include "src/sksl/ir/SkSLModifierFlags.h"
44
#include "src/sksl/ir/SkSLModifiersDeclaration.h"
45
#include "src/sksl/ir/SkSLNop.h"
46
#include "src/sksl/ir/SkSLPoison.h"
47
#include "src/sksl/ir/SkSLPostfixExpression.h"
48
#include "src/sksl/ir/SkSLPrefixExpression.h"
49
#include "src/sksl/ir/SkSLProgram.h"
50
#include "src/sksl/ir/SkSLProgramElement.h"
51
#include "src/sksl/ir/SkSLReturnStatement.h"
52
#include "src/sksl/ir/SkSLStatement.h"
53
#include "src/sksl/ir/SkSLStructDefinition.h"
54
#include "src/sksl/ir/SkSLSwitchStatement.h"
55
#include "src/sksl/ir/SkSLSwizzle.h"
56
#include "src/sksl/ir/SkSLSymbol.h"
57
#include "src/sksl/ir/SkSLSymbolTable.h"
58
#include "src/sksl/ir/SkSLTernaryExpression.h"
59
#include "src/sksl/ir/SkSLType.h"
60
#include "src/sksl/ir/SkSLTypeReference.h"
61
#include "src/sksl/ir/SkSLVarDeclarations.h"
62
#include "src/sksl/ir/SkSLVariable.h"
63
64
#include <algorithm>
65
#include <climits>
66
#include <initializer_list>
67
#include <memory>
68
#include <utility>
69
#include <vector>
70
71
using namespace skia_private;
72
73
namespace SkSL {
74
75
static constexpr int kMaxParseDepth = 50;
76
77
50.8k
static ModifierFlags parse_modifier_token(Token::Kind token) {
78
50.8k
    switch (token) {
79
281
        case Token::Kind::TK_UNIFORM:        return ModifierFlag::kUniform;
80
74
        case Token::Kind::TK_CONST:          return ModifierFlag::kConst;
81
542
        case Token::Kind::TK_IN:             return ModifierFlag::kIn;
82
121
        case Token::Kind::TK_OUT:            return ModifierFlag::kOut;
83
54
        case Token::Kind::TK_INOUT:          return ModifierFlag::kIn | ModifierFlag::kOut;
84
233
        case Token::Kind::TK_FLAT:           return ModifierFlag::kFlat;
85
0
        case Token::Kind::TK_NOPERSPECTIVE:  return ModifierFlag::kNoPerspective;
86
1.90k
        case Token::Kind::TK_PURE:           return ModifierFlag::kPure;
87
0
        case Token::Kind::TK_INLINE:         return ModifierFlag::kInline;
88
0
        case Token::Kind::TK_NOINLINE:       return ModifierFlag::kNoInline;
89
0
        case Token::Kind::TK_HIGHP:          return ModifierFlag::kHighp;
90
0
        case Token::Kind::TK_MEDIUMP:        return ModifierFlag::kMediump;
91
0
        case Token::Kind::TK_LOWP:           return ModifierFlag::kLowp;
92
0
        case Token::Kind::TK_EXPORT:         return ModifierFlag::kExport;
93
768
        case Token::Kind::TK_ES3:            return ModifierFlag::kES3;
94
0
        case Token::Kind::TK_WORKGROUP:      return ModifierFlag::kWorkgroup;
95
0
        case Token::Kind::TK_READONLY:       return ModifierFlag::kReadOnly;
96
0
        case Token::Kind::TK_WRITEONLY:      return ModifierFlag::kWriteOnly;
97
0
        case Token::Kind::TK_BUFFER:         return ModifierFlag::kBuffer;
98
0
        case Token::Kind::TK_PIXELLOCAL:     return ModifierFlag::kPixelLocal;
99
46.8k
        default:                             return ModifierFlag::kNone;
100
50.8k
    }
101
50.8k
}
102
103
class Parser::AutoDepth {
104
public:
105
5.39M
    AutoDepth(Parser* p) : fParser(p), fDepth(0) {}
106
107
5.39M
    ~AutoDepth() {
108
5.39M
        fParser->fDepth -= fDepth;
109
5.39M
    }
110
111
664k
    bool increase() {
112
664k
        ++fDepth;
113
664k
        ++fParser->fDepth;
114
664k
        if (fParser->fDepth > kMaxParseDepth) {
115
547
            fParser->error(fParser->peek(), "exceeded max parse depth");
116
547
            fParser->fEncounteredFatalError = true;
117
547
            return false;
118
547
        }
119
663k
        return true;
120
664k
    }
121
122
private:
123
    Parser* fParser;
124
    int fDepth;
125
};
126
127
class Parser::AutoSymbolTable {
128
public:
129
18.5k
    AutoSymbolTable(Parser* p, std::unique_ptr<SymbolTable>* newSymbolTable, bool enable = true) {
130
18.5k
        if (enable) {
131
13.1k
            fParser = p;
132
13.1k
            SymbolTable*& ctxSymbols = this->contextSymbolTable();
133
13.1k
            *newSymbolTable = std::make_unique<SymbolTable>(ctxSymbols, ctxSymbols->isBuiltin());
134
13.1k
            ctxSymbols = newSymbolTable->get();
135
13.1k
        }
136
18.5k
    }
137
138
18.5k
    ~AutoSymbolTable() {
139
18.5k
        if (fParser) {
140
13.1k
            SymbolTable*& ctxSymbols = this->contextSymbolTable();
141
13.1k
            ctxSymbols = ctxSymbols->fParent;
142
13.1k
        }
143
18.5k
    }
144
145
private:
146
26.2k
    SymbolTable*& contextSymbolTable() { return fParser->fCompiler.context().fSymbolTable; }
147
148
    Parser* fParser = nullptr;
149
};
150
151
class Parser::Checkpoint {
152
public:
153
5.70k
    Checkpoint(Parser* p) : fParser(p) {
154
5.70k
        Context& context = fParser->fCompiler.context();
155
5.70k
        fPushbackCheckpoint = fParser->fPushback;
156
5.70k
        fLexerCheckpoint = fParser->fLexer.getCheckpoint();
157
5.70k
        fOldErrorReporter = context.fErrors;
158
5.70k
        fOldEncounteredFatalError = fParser->fEncounteredFatalError;
159
5.70k
        SkASSERT(fOldErrorReporter);
160
5.70k
        context.setErrorReporter(&fErrorReporter);
161
5.70k
    }
162
163
5.70k
    ~Checkpoint() {
164
5.70k
        SkASSERTF(!fOldErrorReporter, "Checkpoint was not accepted or rewound before destruction");
165
5.70k
    }
166
167
2.60k
    void accept() {
168
2.60k
        this->restoreErrorReporter();
169
        // Parser errors should have been fatal, but we can encounter other errors like type
170
        // mismatches despite accepting the parse. Forward those messages to the actual error
171
        // handler now.
172
2.60k
        fErrorReporter.forwardErrors(fParser);
173
2.60k
    }
174
175
3.10k
    void rewind() {
176
3.10k
        this->restoreErrorReporter();
177
3.10k
        fParser->fPushback = fPushbackCheckpoint;
178
3.10k
        fParser->fLexer.rewindToCheckpoint(fLexerCheckpoint);
179
3.10k
        fParser->fEncounteredFatalError = fOldEncounteredFatalError;
180
3.10k
    }
181
182
private:
183
    class ForwardingErrorReporter : public ErrorReporter {
184
    public:
185
130k
        void handleError(std::string_view msg, Position pos) override {
186
130k
            fErrors.push_back({std::string(msg), pos});
187
130k
        }
188
189
2.60k
        void forwardErrors(Parser* parser) {
190
6.36k
            for (const Error& error : fErrors) {
191
6.36k
                parser->error(error.fPos, error.fMsg);
192
6.36k
            }
193
2.60k
        }
194
195
    private:
196
        struct Error {
197
            std::string fMsg;
198
            Position fPos;
199
        };
200
201
        skia_private::TArray<Error> fErrors;
202
    };
203
204
5.70k
    void restoreErrorReporter() {
205
5.70k
        SkASSERT(fOldErrorReporter);
206
5.70k
        fParser->fCompiler.context().setErrorReporter(fOldErrorReporter);
207
5.70k
        fOldErrorReporter = nullptr;
208
5.70k
    }
209
210
    Parser* fParser;
211
    Token fPushbackCheckpoint;
212
    SkSL::Lexer::Checkpoint fLexerCheckpoint;
213
    ForwardingErrorReporter fErrorReporter;
214
    ErrorReporter* fOldErrorReporter;
215
    bool fOldEncounteredFatalError;
216
};
217
218
Parser::Parser(Compiler* compiler,
219
               const ProgramSettings& settings,
220
               ProgramKind kind,
221
               std::unique_ptr<std::string> text)
222
        : fCompiler(*compiler)
223
        , fSettings(settings)
224
        , fKind(kind)
225
        , fText(std::move(text))
226
9.49k
        , fPushback(Token::Kind::TK_NONE, /*offset=*/-1, /*length=*/-1) {
227
9.49k
    fLexer.start(*fText);
228
9.49k
}
229
230
9.49k
Parser::~Parser() = default;
231
232
326k
SymbolTable* Parser::symbolTable() {
233
326k
    return fCompiler.symbolTable();
234
326k
}
235
236
2.58M
Token Parser::nextRawToken() {
237
2.58M
    Token token;
238
2.58M
    if (fPushback.fKind != Token::Kind::TK_NONE) {
239
        // Retrieve the token from the pushback buffer.
240
1.21M
        token = fPushback;
241
1.21M
        fPushback.fKind = Token::Kind::TK_NONE;
242
1.37M
    } else {
243
        // Fetch a token from the lexer.
244
1.37M
        token = fLexer.next();
245
246
        // Some tokens are always invalid, so we detect and report them here.
247
1.37M
        switch (token.fKind) {
248
41.3k
            case Token::Kind::TK_PRIVATE_IDENTIFIER:
249
41.3k
                if (ProgramConfig::AllowsPrivateIdentifiers(fKind)) {
250
41.3k
                    token.fKind = Token::Kind::TK_IDENTIFIER;
251
41.3k
                    break;
252
41.3k
                }
253
41.3k
                [[fallthrough]];
254
255
485
            case Token::Kind::TK_RESERVED:
256
485
                this->error(token, "name '" + std::string(this->text(token)) + "' is reserved");
257
485
                token.fKind = Token::Kind::TK_IDENTIFIER;  // reduces additional follow-up errors
258
485
                break;
259
260
331
            case Token::Kind::TK_BAD_OCTAL:
261
331
                this->error(token, "'" + std::string(this->text(token)) +
262
331
                                   "' is not a valid octal number");
263
331
                break;
264
265
1.32M
            default:
266
1.32M
                break;
267
1.37M
        }
268
1.37M
    }
269
270
2.58M
    return token;
271
2.58M
}
272
273
2.56M
static bool is_whitespace(Token::Kind kind) {
274
2.56M
    switch (kind) {
275
78.6k
        case Token::Kind::TK_WHITESPACE:
276
95.8k
        case Token::Kind::TK_LINE_COMMENT:
277
95.8k
        case Token::Kind::TK_BLOCK_COMMENT:
278
95.8k
            return true;
279
280
2.46M
        default:
281
2.46M
            return false;
282
2.56M
    }
283
2.56M
}
284
285
28
bool Parser::expectNewline() {
286
28
    Token token = this->nextRawToken();
287
28
    if (token.fKind == Token::Kind::TK_WHITESPACE) {
288
        // The lexer doesn't distinguish newlines from other forms of whitespace, so we check
289
        // for newlines by searching through the token text.
290
17
        std::string_view tokenText = this->text(token);
291
17
        if (tokenText.find_first_of('\r') != std::string_view::npos ||
292
17
            tokenText.find_first_of('\n') != std::string_view::npos) {
293
10
            return true;
294
10
        }
295
17
    }
296
    // We didn't find a newline.
297
18
    this->pushback(token);
298
18
    return false;
299
28
}
300
301
2.42M
Token Parser::nextToken() {
302
2.51M
    for (;;) {
303
2.51M
        Token token = this->nextRawToken();
304
2.51M
        if (!is_whitespace(token.fKind)) {
305
2.42M
            return token;
306
2.42M
        }
307
2.51M
    }
308
2.42M
}
309
310
155k
void Parser::pushback(Token t) {
311
155k
    SkASSERT(fPushback.fKind == Token::Kind::TK_NONE);
312
155k
    fPushback = t;
313
155k
}
314
315
5.49M
Token Parser::peek() {
316
5.49M
    if (fPushback.fKind == Token::Kind::TK_NONE) {
317
1.06M
        fPushback = this->nextToken();
318
1.06M
    }
319
5.49M
    return fPushback;
320
5.49M
}
321
322
587k
bool Parser::checkNext(Token::Kind kind, Token* result) {
323
587k
    if (fPushback.fKind != Token::Kind::TK_NONE && fPushback.fKind != kind) {
324
396k
        return false;
325
396k
    }
326
190k
    Token next = this->nextToken();
327
190k
    if (next.fKind == kind) {
328
84.0k
        if (result) {
329
9.65k
            *result = next;
330
9.65k
        }
331
84.0k
        return true;
332
84.0k
    }
333
106k
    this->pushback(next);
334
106k
    return false;
335
190k
}
336
337
677k
bool Parser::expect(Token::Kind kind, const char* expected, Token* result) {
338
677k
    Token next = this->nextToken();
339
677k
    if (next.fKind == kind) {
340
510k
        if (result) {
341
475k
            *result = next;
342
475k
        }
343
510k
        return true;
344
510k
    } else {
345
166k
        this->error(next, "expected " + std::string(expected) + ", but found '" +
346
166k
                          std::string(this->text(next)) + "'");
347
166k
        this->fEncounteredFatalError = true;
348
166k
        return false;
349
166k
    }
350
677k
}
351
352
52.7k
bool Parser::expectIdentifier(Token* result) {
353
52.7k
    if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", result)) {
354
3.38k
        return false;
355
3.38k
    }
356
49.4k
    if (this->symbolTable()->isBuiltinType(this->text(*result))) {
357
40
        this->error(*result, "expected an identifier, but found type '" +
358
40
                             std::string(this->text(*result)) + "'");
359
40
        this->fEncounteredFatalError = true;
360
40
        return false;
361
40
    }
362
49.3k
    return true;
363
49.4k
}
364
365
13.1k
bool Parser::checkIdentifier(Token* result) {
366
13.1k
    if (!this->checkNext(Token::Kind::TK_IDENTIFIER, result)) {
367
10.6k
        return false;
368
10.6k
    }
369
2.49k
    if (this->symbolTable()->isBuiltinType(this->text(*result))) {
370
6
        this->pushback(*result);
371
6
        return false;
372
6
    }
373
2.48k
    return true;
374
2.49k
}
375
376
813k
std::string_view Parser::text(Token token) {
377
813k
    return std::string_view(fText->data() + token.fOffset, token.fLength);
378
813k
}
379
380
778k
Position Parser::position(Token t) {
381
778k
    if (t.fOffset >= 0) {
382
778k
        return Position::Range(t.fOffset, t.fOffset + t.fLength);
383
778k
    } else {
384
0
        return Position();
385
0
    }
386
778k
}
387
388
203k
void Parser::error(Token token, std::string_view msg) {
389
203k
    this->error(this->position(token), msg);
390
203k
}
391
392
217k
void Parser::error(Position position, std::string_view msg) {
393
217k
    fCompiler.context().fErrors->error(position, msg);
394
217k
}
395
396
370k
Position Parser::rangeFrom(Position start) {
397
370k
    int offset = fPushback.fKind != Token::Kind::TK_NONE ? fPushback.fOffset
398
370k
                                                         : fLexer.getCheckpoint().fOffset;
399
370k
    return Position::Range(start.startOffset(), offset);
400
370k
}
401
402
29.7k
Position Parser::rangeFrom(Token start) {
403
29.7k
    return this->rangeFrom(this->position(start));
404
29.7k
}
405
406
/* declaration* END_OF_FILE */
407
9.47k
std::unique_ptr<Program> Parser::programInheritingFrom(const SkSL::Module* module) {
408
9.47k
    this->declarations();
409
9.47k
    std::unique_ptr<Program> result;
410
9.47k
    if (fCompiler.errorReporter().errorCount() == 0) {
411
340
        result = fCompiler.releaseProgram(std::move(fText), std::move(fProgramElements));
412
9.13k
    } else {
413
9.13k
        fProgramElements.clear();
414
9.13k
    }
415
9.47k
    return result;
416
9.47k
}
417
418
22
std::unique_ptr<SkSL::Module> Parser::moduleInheritingFrom(const SkSL::Module* parentModule) {
419
22
    this->declarations();
420
22
    this->symbolTable()->takeOwnershipOfString(std::move(*fText));
421
22
    auto result = std::make_unique<SkSL::Module>();
422
22
    result->fParent = parentModule;
423
22
    result->fSymbols = std::move(fCompiler.fGlobalSymbols);
424
22
    result->fElements = std::move(fProgramElements);
425
22
    return result;
426
22
}
427
428
9.49k
void Parser::declarations() {
429
9.49k
    fEncounteredFatalError = false;
430
431
    // If the program is 8MB or longer (Position::kMaxOffset), error reporting goes off the rails.
432
    // At any rate, there's no good reason for a program to be this long.
433
9.49k
    if (fText->size() >= Position::kMaxOffset) {
434
0
        this->error(Position(), "program is too large");
435
0
        return;
436
0
    }
437
438
    // Any #version directive must appear as the first thing in a file
439
9.49k
    if (this->peek().fKind == Token::Kind::TK_DIRECTIVE) {
440
404
        this->directive(/*allowVersion=*/true);
441
404
    }
442
443
49.1k
    while (!fEncounteredFatalError) {
444
        // We should always be at global scope when processing top-level declarations.
445
40.3k
        SkASSERT(fCompiler.context().fSymbolTable == fCompiler.globalSymbols());
446
447
40.3k
        switch (this->peek().fKind) {
448
498
            case Token::Kind::TK_END_OF_FILE:
449
498
                return;
450
451
241
            case Token::Kind::TK_INVALID:
452
241
                this->error(this->peek(), "invalid token");
453
241
                return;
454
455
1.08k
            case Token::Kind::TK_DIRECTIVE:
456
1.08k
                this->directive(/*allowVersion=*/false);
457
1.08k
                break;
458
459
38.5k
            default:
460
38.5k
                this->declaration();
461
38.5k
                break;
462
40.3k
        }
463
40.3k
    }
464
9.49k
}
SkSL::Parser::declarations()
Line
Count
Source
428
9.49k
void Parser::declarations() {
429
9.49k
    fEncounteredFatalError = false;
430
431
    // If the program is 8MB or longer (Position::kMaxOffset), error reporting goes off the rails.
432
    // At any rate, there's no good reason for a program to be this long.
433
9.49k
    if (fText->size() >= Position::kMaxOffset) {
434
0
        this->error(Position(), "program is too large");
435
0
        return;
436
0
    }
437
438
    // Any #version directive must appear as the first thing in a file
439
9.49k
    if (this->peek().fKind == Token::Kind::TK_DIRECTIVE) {
440
404
        this->directive(/*allowVersion=*/true);
441
404
    }
442
443
49.1k
    while (!fEncounteredFatalError) {
444
        // We should always be at global scope when processing top-level declarations.
445
40.3k
        SkASSERT(fCompiler.context().fSymbolTable == fCompiler.globalSymbols());
446
447
40.3k
        switch (this->peek().fKind) {
448
498
            case Token::Kind::TK_END_OF_FILE:
449
498
                return;
450
451
241
            case Token::Kind::TK_INVALID:
452
241
                this->error(this->peek(), "invalid token");
453
241
                return;
454
455
1.08k
            case Token::Kind::TK_DIRECTIVE:
456
1.08k
                this->directive(/*allowVersion=*/false);
457
1.08k
                break;
458
459
38.5k
            default:
460
38.5k
                this->declaration();
461
38.5k
                break;
462
40.3k
        }
463
40.3k
    }
464
9.49k
}
Unexecuted instantiation: SkSL::Parser::declarations()
465
466
/* DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER NEWLINE */
467
27
void Parser::extensionDirective(Position start) {
468
27
    Token name;
469
27
    if (!this->expectIdentifier(&name)) {
470
6
        return;
471
6
    }
472
21
    if (!this->expect(Token::Kind::TK_COLON, "':'")) {
473
2
        return;
474
2
    }
475
19
    Token behavior;
476
19
    if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &behavior)) {
477
2
        return;
478
2
    }
479
    // We expect a newline immediately after `#extension name : behavior`.
480
17
    if (this->expectNewline()) {
481
5
        std::unique_ptr<SkSL::Extension> ext = Extension::Convert(fCompiler.context(),
482
5
                                                                  this->rangeFrom(start),
483
5
                                                                  this->text(name),
484
5
                                                                  this->text(behavior));
485
5
        if (ext) {
486
0
            fProgramElements.push_back(std::move(ext));
487
0
        }
488
12
    } else {
489
12
        this->error(start, "invalid #extension directive");
490
12
    }
491
17
}
492
493
/* DIRECTIVE(#version) INTLITERAL NEWLINE */
494
149
void Parser::versionDirective(Position start, bool allowVersion) {
495
149
    if (!allowVersion) {
496
76
        this->error(start, "#version directive must appear before anything else");
497
76
        return;
498
76
    }
499
73
    SKSL_INT version;
500
73
    if (!this->intLiteral(&version)) {
501
2
        return;
502
2
    }
503
71
    switch (version) {
504
2
        case 100:
505
2
            fCompiler.context().fConfig->fRequiredSkSLVersion = Version::k100;
506
2
            break;
507
9
        case 300:
508
9
            fCompiler.context().fConfig->fRequiredSkSLVersion = Version::k300;
509
9
            break;
510
60
        default:
511
60
            this->error(start, "unsupported version number");
512
60
            return;
513
71
    }
514
    // We expect a newline after a #version directive.
515
11
    if (!this->expectNewline()) {
516
6
        this->error(start, "invalid #version directive");
517
6
    }
518
11
}
519
520
/* DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER NEWLINE |
521
   DIRECTIVE(#version) INTLITERAL NEWLINE */
522
1.48k
void Parser::directive(bool allowVersion) {
523
1.48k
    Token start;
524
1.48k
    if (!this->expect(Token::Kind::TK_DIRECTIVE, "a directive", &start)) {
525
0
        return;
526
0
    }
527
1.48k
    std::string_view text = this->text(start);
528
1.48k
    if (text == "#extension") {
529
27
        return this->extensionDirective(this->position(start));
530
27
    }
531
1.45k
    if (text == "#version") {
532
149
        return this->versionDirective(this->position(start), allowVersion);
533
149
    }
534
1.31k
    this->error(start, "unsupported directive '" + std::string(this->text(start)) + "'");
535
1.31k
}
536
537
246
bool Parser::modifiersDeclarationEnd(const SkSL::Modifiers& mods) {
538
246
    std::unique_ptr<ModifiersDeclaration> decl = ModifiersDeclaration::Convert(fCompiler.context(),
539
246
                                                                               mods);
540
246
    if (!decl) {
541
246
        return false;
542
246
    }
543
0
    fProgramElements.push_back(std::move(decl));
544
0
    return true;
545
246
}
546
547
/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter (COMMA parameter)* RPAREN
548
   (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
549
38.5k
bool Parser::declaration() {
550
38.5k
    Token start = this->peek();
551
38.5k
    if (start.fKind == Token::Kind::TK_SEMICOLON) {
552
10.0k
        this->nextToken();
553
10.0k
        this->error(start, "expected a declaration, but found ';'");
554
10.0k
        return false;
555
10.0k
    }
556
28.5k
    Modifiers modifiers = this->modifiers();
557
28.5k
    Token lookahead = this->peek();
558
28.5k
    if (lookahead.fKind == Token::Kind::TK_IDENTIFIER &&
559
28.5k
        !this->symbolTable()->isType(this->text(lookahead))) {
560
        // we have an identifier that's not a type, could be the start of an interface block
561
12.8k
        return this->interfaceBlock(modifiers);
562
12.8k
    }
563
15.6k
    if (lookahead.fKind == Token::Kind::TK_SEMICOLON) {
564
246
        this->nextToken();
565
246
        return this->modifiersDeclarationEnd(modifiers);
566
246
    }
567
15.4k
    if (lookahead.fKind == Token::Kind::TK_STRUCT) {
568
9
        this->structVarDeclaration(this->position(start), modifiers);
569
9
        return true;
570
9
    }
571
15.4k
    const Type* type = this->type(&modifiers);
572
15.4k
    if (!type) {
573
542
        return false;
574
542
    }
575
14.9k
    Token name;
576
14.9k
    if (!this->expectIdentifier(&name)) {
577
1.06k
        return false;
578
1.06k
    }
579
13.8k
    if (this->checkNext(Token::Kind::TK_LPAREN)) {
580
9.80k
        return this->functionDeclarationEnd(this->position(start), modifiers, type, name);
581
9.80k
    } else {
582
4.03k
        this->globalVarDeclarationEnd(this->position(start), modifiers, type, name);
583
4.03k
        return true;
584
4.03k
    }
585
13.8k
}
586
587
/* (RPAREN | VOID RPAREN | parameter (COMMA parameter)* RPAREN) (block | SEMICOLON) */
588
bool Parser::functionDeclarationEnd(Position start,
589
                                    Modifiers& modifiers,
590
                                    const Type* returnType,
591
9.80k
                                    const Token& name) {
592
9.80k
    Token lookahead = this->peek();
593
9.80k
    bool validParams = true;
594
9.80k
    STArray<8, std::unique_ptr<Variable>> parameters;
595
9.80k
    if (lookahead.fKind == Token::Kind::TK_RPAREN) {
596
        // `()` means no parameters at all.
597
5.07k
    } else if (lookahead.fKind == Token::Kind::TK_IDENTIFIER && this->text(lookahead) == "void") {
598
        // `(void)` also means no parameters at all.
599
64
        this->nextToken();
600
4.67k
    } else {
601
12.1k
        for (;;) {
602
12.1k
            std::unique_ptr<SkSL::Variable> param;
603
12.1k
            if (!this->parameter(&param)) {
604
72
                return false;
605
72
            }
606
12.1k
            validParams = validParams && param;
607
12.1k
            parameters.push_back(std::move(param));
608
12.1k
            if (!this->checkNext(Token::Kind::TK_COMMA)) {
609
4.59k
                break;
610
4.59k
            }
611
12.1k
        }
612
4.67k
    }
613
9.73k
    if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
614
114
        return false;
615
114
    }
616
617
9.62k
    SkSL::FunctionDeclaration* decl = nullptr;
618
9.62k
    if (validParams) {
619
9.62k
        decl = SkSL::FunctionDeclaration::Convert(fCompiler.context(),
620
9.62k
                                                  this->rangeFrom(start),
621
9.62k
                                                  modifiers,
622
9.62k
                                                  this->text(name),
623
9.62k
                                                  std::move(parameters),
624
9.62k
                                                  start,
625
9.62k
                                                  returnType);
626
9.62k
    }
627
628
9.62k
    if (this->checkNext(Token::Kind::TK_SEMICOLON)) {
629
4.19k
        return this->prototypeFunction(decl);
630
5.42k
    } else {
631
5.42k
        return this->defineFunction(decl);
632
5.42k
    }
633
9.62k
}
634
635
4.19k
bool Parser::prototypeFunction(SkSL::FunctionDeclaration* decl) {
636
4.19k
    if (!decl) {
637
1.15k
        return false;
638
1.15k
    }
639
3.04k
    fProgramElements.push_back(std::make_unique<SkSL::FunctionPrototype>(
640
3.04k
            decl->fPosition, decl, fCompiler.context().fConfig->fIsBuiltinCode));
641
3.04k
    return true;
642
4.19k
}
643
644
5.42k
bool Parser::defineFunction(SkSL::FunctionDeclaration* decl) {
645
5.42k
    const Context& context = fCompiler.context();
646
5.42k
    Token bodyStart = this->peek();
647
648
5.42k
    std::unique_ptr<SymbolTable> symbolTable;
649
5.42k
    std::unique_ptr<Statement> body;
650
5.42k
    {
651
        // Create a symbol table for the function which includes the parameters.
652
5.42k
        AutoSymbolTable symbols(this, &symbolTable);
653
5.42k
        if (decl) {
654
4.85k
            for (Variable* param : decl->parameters()) {
655
2.46k
                symbolTable->addWithoutOwnership(fCompiler.context(), param);
656
2.46k
            }
657
4.85k
        }
658
659
        // Parse the function body.
660
5.42k
        body = this->block(/*introduceNewScope=*/false, /*adoptExistingSymbolTable=*/&symbolTable);
661
5.42k
    }
662
663
    // If there was a problem with the declarations or body, don't actually create a definition.
664
5.42k
    if (!decl || !body) {
665
4.42k
        return false;
666
4.42k
    }
667
668
1.00k
    std::unique_ptr<SkSL::Statement> block = std::move(body);
669
1.00k
    SkASSERT(block->is<Block>());
670
1.00k
    Position pos = this->rangeFrom(bodyStart);
671
1.00k
    block->fPosition = pos;
672
673
1.00k
    std::unique_ptr<FunctionDefinition> function = FunctionDefinition::Convert(context,
674
1.00k
                                                                               pos,
675
1.00k
                                                                               *decl,
676
1.00k
                                                                               std::move(block),
677
1.00k
                                                                               /*builtin=*/false);
678
1.00k
    if (!function) {
679
0
        return false;
680
0
    }
681
1.00k
    decl->setDefinition(function.get());
682
1.00k
    fProgramElements.push_back(std::move(function));
683
1.00k
    return true;
684
1.00k
}
685
686
7.53k
bool Parser::arraySize(SKSL_INT* outResult) {
687
    // Start out with a safe value that won't generate any errors downstream
688
7.53k
    *outResult = 1;
689
7.53k
    Token next = this->peek();
690
7.53k
    if (next.fKind == Token::Kind::TK_RBRACKET) {
691
15
        this->error(this->position(next), "unsized arrays are not permitted here");
692
15
        return true;
693
15
    }
694
7.52k
    std::unique_ptr<Expression> sizeLiteral = this->expression();
695
7.52k
    if (!sizeLiteral) {
696
1.53k
        return false;
697
1.53k
    }
698
5.98k
    if (!sizeLiteral->is<Poison>()) {
699
2.56k
        SKSL_INT size;
700
2.56k
        if (!ConstantFolder::GetConstantInt(*sizeLiteral, &size)) {
701
1.78k
            this->error(sizeLiteral->fPosition, "array size must be an integer");
702
1.78k
            return true;
703
1.78k
        }
704
776
        if (size > INT32_MAX) {
705
23
            this->error(sizeLiteral->fPosition, "array size out of bounds");
706
23
            return true;
707
23
        }
708
753
        if (size <= 0) {
709
266
            this->error(sizeLiteral->fPosition, "array size must be positive");
710
266
            return true;
711
266
        }
712
        // Now that we've validated it, output the real value
713
487
        *outResult = size;
714
487
    }
715
3.91k
    return true;
716
5.98k
}
717
718
5.02k
const Type* Parser::arrayType(const Type* base, int count, Position pos) {
719
5.02k
    const Context& context = fCompiler.context();
720
5.02k
    count = base->convertArraySize(context, pos, pos, count);
721
5.02k
    if (!count) {
722
947
        return context.fTypes.fPoison.get();
723
947
    }
724
4.07k
    return this->symbolTable()->addArrayDimension(fCompiler.context(), base, count);
725
5.02k
}
726
727
0
const Type* Parser::unsizedArrayType(const Type* base, Position pos) {
728
0
    const Context& context = fCompiler.context();
729
0
    if (!base->checkIfUsableInArray(context, pos)) {
730
0
        return context.fTypes.fPoison.get();
731
0
    }
732
0
    return this->symbolTable()->addArrayDimension(fCompiler.context(), base,
733
0
                                                  SkSL::Type::kUnsizedArray);
734
0
}
735
736
38.4k
bool Parser::parseArrayDimensions(Position pos, const Type** type) {
737
38.4k
    Token next;
738
38.9k
    while (this->checkNext(Token::Kind::TK_LBRACKET, &next)) {
739
1.04k
        if (this->checkNext(Token::Kind::TK_RBRACKET)) {
740
273
            if (this->allowUnsizedArrays()) {
741
0
                *type = this->unsizedArrayType(*type, this->rangeFrom(pos));
742
273
            } else {
743
273
                this->error(this->rangeFrom(pos), "unsized arrays are not permitted here");
744
273
            }
745
771
        } else {
746
771
            SKSL_INT size;
747
771
            if (!this->arraySize(&size)) {
748
179
                return false;
749
179
            }
750
592
            if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
751
402
                return false;
752
402
            }
753
190
            *type = this->arrayType(*type, size, this->rangeFrom(pos));
754
190
        }
755
1.04k
    }
756
37.9k
    return true;
757
38.4k
}
758
759
25.7k
bool Parser::parseInitializer(Position pos, std::unique_ptr<Expression>* initializer) {
760
25.7k
    if (this->checkNext(Token::Kind::TK_EQ)) {
761
4.75k
        *initializer = this->assignmentExpression();
762
4.75k
        return *initializer != nullptr;
763
4.75k
    }
764
21.0k
    return true;
765
25.7k
}
766
767
14.5k
void Parser::addGlobalVarDeclaration(std::unique_ptr<VarDeclaration> decl) {
768
14.5k
    if (decl) {
769
7.44k
        fProgramElements.push_back(std::make_unique<SkSL::GlobalVarDeclaration>(std::move(decl)));
770
7.44k
    }
771
14.5k
}
772
773
/* (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)? (COMMA IDENTIFER
774
   (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
775
void Parser::globalVarDeclarationEnd(Position pos,
776
                                     const Modifiers& mods,
777
                                     const Type* baseType,
778
4.03k
                                     Token name) {
779
4.03k
    const Type* type = baseType;
780
4.03k
    std::unique_ptr<Expression> initializer;
781
4.03k
    if (!this->parseArrayDimensions(pos, &type)) {
782
168
        return;
783
168
    }
784
3.86k
    if (!this->parseInitializer(pos, &initializer)) {
785
96
        return;
786
96
    }
787
3.76k
    this->addGlobalVarDeclaration(VarDeclaration::Convert(fCompiler.context(),
788
3.76k
                                                          this->rangeFrom(pos),
789
3.76k
                                                          mods,
790
3.76k
                                                          *type,
791
3.76k
                                                          this->position(name),
792
3.76k
                                                          this->text(name),
793
3.76k
                                                          VariableStorage::kGlobal,
794
3.76k
                                                          std::move(initializer)));
795
14.5k
    while (this->checkNext(Token::Kind::TK_COMMA)) {
796
11.3k
        type = baseType;
797
11.3k
        Token identifierName;
798
11.3k
        if (!this->expectIdentifier(&identifierName)) {
799
53
            return;
800
53
        }
801
11.2k
        if (!this->parseArrayDimensions(pos, &type)) {
802
317
            return;
803
317
        }
804
10.9k
        std::unique_ptr<Expression> anotherInitializer;
805
10.9k
        if (!this->parseInitializer(pos, &anotherInitializer)) {
806
188
            return;
807
188
        }
808
10.7k
        this->addGlobalVarDeclaration(VarDeclaration::Convert(fCompiler.context(),
809
10.7k
                                                              this->rangeFrom(identifierName),
810
10.7k
                                                              mods,
811
10.7k
                                                              *type,
812
10.7k
                                                              this->position(identifierName),
813
10.7k
                                                              this->text(identifierName),
814
10.7k
                                                              VariableStorage::kGlobal,
815
10.7k
                                                              std::move(anotherInitializer)));
816
10.7k
    }
817
3.21k
    this->expect(Token::Kind::TK_SEMICOLON, "';'");
818
3.21k
}
819
820
/* (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)? (COMMA IDENTIFER
821
   (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
822
std::unique_ptr<Statement> Parser::localVarDeclarationEnd(Position pos,
823
                                                          const Modifiers& mods,
824
                                                          const Type* baseType,
825
2.62k
                                                          Token name) {
826
2.62k
    const Type* type = baseType;
827
2.62k
    std::unique_ptr<Expression> initializer;
828
2.62k
    if (!this->parseArrayDimensions(pos, &type)) {
829
22
        return nullptr;
830
22
    }
831
2.60k
    if (!this->parseInitializer(pos, &initializer)) {
832
3
        return nullptr;
833
3
    }
834
2.60k
    std::unique_ptr<Statement> result = VarDeclaration::Convert(fCompiler.context(),
835
2.60k
                                                                this->rangeFrom(pos),
836
2.60k
                                                                mods,
837
2.60k
                                                                *type,
838
2.60k
                                                                this->position(name),
839
2.60k
                                                                this->text(name),
840
2.60k
                                                                VariableStorage::kLocal,
841
2.60k
                                                                std::move(initializer));
842
10.9k
    for (;;) {
843
10.9k
        if (!this->checkNext(Token::Kind::TK_COMMA)) {
844
2.50k
            this->expect(Token::Kind::TK_SEMICOLON, "';'");
845
2.50k
            break;
846
2.50k
        }
847
8.42k
        type = baseType;
848
8.42k
        Token identifierName;
849
8.42k
        if (!this->expectIdentifier(&identifierName)) {
850
37
            break;
851
37
        }
852
8.38k
        if (!this->parseArrayDimensions(pos, &type)) {
853
48
            break;
854
48
        }
855
8.33k
        std::unique_ptr<Expression> anotherInitializer;
856
8.33k
        if (!this->parseInitializer(pos, &anotherInitializer)) {
857
12
            break;
858
12
        }
859
8.32k
        std::unique_ptr<Statement> next = VarDeclaration::Convert(fCompiler.context(),
860
8.32k
                                                                  this->rangeFrom(identifierName),
861
8.32k
                                                                  mods,
862
8.32k
                                                                  *type,
863
8.32k
                                                                  this->position(identifierName),
864
8.32k
                                                                  this->text(identifierName),
865
8.32k
                                                                  VariableStorage::kLocal,
866
8.32k
                                                                  std::move(anotherInitializer));
867
868
8.32k
        result = Block::MakeCompoundStatement(std::move(result), std::move(next));
869
8.32k
    }
870
2.60k
    pos = this->rangeFrom(pos);
871
2.60k
    return this->statementOrNop(pos, std::move(result));
872
2.60k
}
873
874
/* (varDeclarations | expressionStatement) */
875
13.7k
std::unique_ptr<Statement> Parser::varDeclarationsOrExpressionStatement() {
876
13.7k
    Token nextToken = this->peek();
877
13.7k
    if (nextToken.fKind == Token::Kind::TK_CONST) {
878
        // Statements that begin with `const` might be variable declarations, but can't be legal
879
        // SkSL expression-statements. (SkSL constructors don't take a `const` modifier.)
880
0
        return this->varDeclarations();
881
0
    }
882
883
13.7k
    if (nextToken.fKind == Token::Kind::TK_HIGHP ||
884
13.7k
        nextToken.fKind == Token::Kind::TK_MEDIUMP ||
885
13.7k
        nextToken.fKind == Token::Kind::TK_LOWP ||
886
13.7k
        this->symbolTable()->isType(this->text(nextToken))) {
887
        // Statements that begin with a typename are most often variable declarations, but
888
        // occasionally the type is part of a constructor, and these are actually expression-
889
        // statements in disguise. First, attempt the common case: parse it as a vardecl.
890
5.70k
        Checkpoint checkpoint(this);
891
5.70k
        VarDeclarationsPrefix prefix;
892
5.70k
        if (this->varDeclarationsPrefix(&prefix)) {
893
2.60k
            checkpoint.accept();
894
2.60k
            return this->localVarDeclarationEnd(prefix.fPosition, prefix.fModifiers, prefix.fType,
895
2.60k
                                                prefix.fName);
896
2.60k
        }
897
898
        // If this statement wasn't actually a vardecl after all, rewind and try parsing it as an
899
        // expression-statement instead.
900
3.10k
        checkpoint.rewind();
901
3.10k
    }
902
11.1k
    return this->expressionStatement();
903
13.7k
}
904
905
// Helper function for varDeclarations(). If this function succeeds, we assume that the rest of the
906
// statement is a variable-declaration statement, not an expression-statement.
907
5.72k
bool Parser::varDeclarationsPrefix(VarDeclarationsPrefix* prefixData) {
908
5.72k
    prefixData->fPosition = this->position(this->peek());
909
5.72k
    prefixData->fModifiers = this->modifiers();
910
5.72k
    prefixData->fType = this->type(&prefixData->fModifiers);
911
5.72k
    if (!prefixData->fType) {
912
890
        return false;
913
890
    }
914
4.83k
    return this->expectIdentifier(&prefixData->fName);
915
5.72k
}
916
917
/* modifiers type IDENTIFIER varDeclarationEnd */
918
21
std::unique_ptr<Statement> Parser::varDeclarations() {
919
21
    VarDeclarationsPrefix prefix;
920
21
    if (!this->varDeclarationsPrefix(&prefix)) {
921
0
        return nullptr;
922
0
    }
923
21
    return this->localVarDeclarationEnd(prefix.fPosition, prefix.fModifiers, prefix.fType,
924
21
                                        prefix.fName);
925
21
}
926
927
/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
928
9
const Type* Parser::structDeclaration() {
929
9
    AutoDepth depth(this);
930
9
    Position start = this->position(this->peek());
931
9
    if (!this->expect(Token::Kind::TK_STRUCT, "'struct'")) {
932
0
        return nullptr;
933
0
    }
934
9
    Token name;
935
9
    if (!this->expectIdentifier(&name)) {
936
0
        return nullptr;
937
0
    }
938
9
    if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
939
0
        return nullptr;
940
0
    }
941
9
    if (!depth.increase()) {
942
0
        return nullptr;
943
0
    }
944
9
    TArray<SkSL::Field> fields;
945
27
    while (!this->checkNext(Token::Kind::TK_RBRACE)) {
946
18
        Token fieldStart = this->peek();
947
18
        Modifiers modifiers = this->modifiers();
948
18
        const Type* type = this->type(&modifiers);
949
18
        if (!type) {
950
0
            return nullptr;
951
0
        }
952
953
18
        do {
954
18
            const Type* actualType = type;
955
18
            Token memberName;
956
18
            if (!this->expectIdentifier(&memberName)) {
957
0
                return nullptr;
958
0
            }
959
960
18
            while (this->checkNext(Token::Kind::TK_LBRACKET)) {
961
0
                SKSL_INT size;
962
0
                if (!this->arraySize(&size)) {
963
0
                    return nullptr;
964
0
                }
965
0
                if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
966
0
                    return nullptr;
967
0
                }
968
0
                actualType = this->arrayType(actualType, size,
969
0
                                             this->rangeFrom(this->position(fieldStart)));
970
0
            }
971
972
18
            fields.push_back(SkSL::Field(this->rangeFrom(fieldStart),
973
18
                                         modifiers.fLayout,
974
18
                                         modifiers.fFlags,
975
18
                                         this->text(memberName),
976
18
                                         actualType));
977
18
        } while (this->checkNext(Token::Kind::TK_COMMA));
978
979
18
        if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
980
0
            return nullptr;
981
0
        }
982
18
    }
983
9
    std::unique_ptr<SkSL::StructDefinition> def = StructDefinition::Convert(fCompiler.context(),
984
9
                                                                            this->rangeFrom(start),
985
9
                                                                            this->text(name),
986
9
                                                                            std::move(fields));
987
9
    if (!def) {
988
0
        return nullptr;
989
0
    }
990
991
9
    const Type* result = &def->type();
992
9
    fProgramElements.push_back(std::move(def));
993
9
    return result;
994
9
}
995
996
/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
997
9
void Parser::structVarDeclaration(Position start, const Modifiers& modifiers) {
998
9
    const Type* type = this->structDeclaration();
999
9
    if (!type) {
1000
0
        return;
1001
0
    }
1002
9
    Token name;
1003
9
    if (this->checkIdentifier(&name)) {
1004
0
        this->globalVarDeclarationEnd(this->rangeFrom(name), modifiers, type, name);
1005
9
    } else {
1006
9
        this->expect(Token::Kind::TK_SEMICOLON, "';'");
1007
9
    }
1008
9
}
1009
1010
/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
1011
12.1k
bool Parser::parameter(std::unique_ptr<SkSL::Variable>* outParam) {
1012
12.1k
    Position pos = this->position(this->peek());
1013
12.1k
    Modifiers modifiers = this->modifiers();
1014
12.1k
    const Type* type = this->type(&modifiers);
1015
12.1k
    if (!type) {
1016
46
        return false;
1017
46
    }
1018
12.1k
    Token name;
1019
12.1k
    std::string_view nameText;
1020
12.1k
    Position namePos;
1021
12.1k
    if (this->checkIdentifier(&name)) {
1022
1.60k
        nameText = this->text(name);
1023
1.60k
        namePos = this->position(name);
1024
10.5k
    } else {
1025
10.5k
        namePos = this->rangeFrom(pos);
1026
10.5k
    }
1027
12.1k
    if (!this->parseArrayDimensions(pos, &type)) {
1028
26
        return false;
1029
26
    }
1030
12.1k
    *outParam = SkSL::Variable::Convert(fCompiler.context(),
1031
12.1k
                                        this->rangeFrom(pos),
1032
12.1k
                                        modifiers.fPosition,
1033
12.1k
                                        modifiers.fLayout,
1034
12.1k
                                        modifiers.fFlags,
1035
12.1k
                                        type,
1036
12.1k
                                        namePos,
1037
12.1k
                                        nameText,
1038
12.1k
                                        VariableStorage::kParameter);
1039
12.1k
    return true;
1040
12.1k
}
1041
1042
/** EQ INT_LITERAL */
1043
6
int Parser::layoutInt() {
1044
6
    if (!this->expect(Token::Kind::TK_EQ, "'='")) {
1045
0
        return -1;
1046
0
    }
1047
6
    Token resultToken;
1048
6
    if (!this->expect(Token::Kind::TK_INT_LITERAL, "a non-negative integer", &resultToken)) {
1049
0
        return -1;
1050
0
    }
1051
6
    std::string_view resultFrag = this->text(resultToken);
1052
6
    SKSL_INT resultValue;
1053
6
    if (!SkSL::stoi(resultFrag, &resultValue)) {
1054
0
        this->error(resultToken, "value in layout is too large: " + std::string(resultFrag));
1055
0
        return -1;
1056
0
    }
1057
6
    return resultValue;
1058
6
}
1059
1060
/** EQ IDENTIFIER */
1061
0
std::string_view Parser::layoutIdentifier() {
1062
0
    if (!this->expect(Token::Kind::TK_EQ, "'='")) {
1063
0
        return {};
1064
0
    }
1065
0
    Token resultToken;
1066
0
    if (!this->expectIdentifier(&resultToken)) {
1067
0
        return {};
1068
0
    }
1069
0
    return this->text(resultToken);
1070
0
}
1071
1072
/* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
1073
46.8k
SkSL::Layout Parser::layout() {
1074
46.8k
    using LayoutMap = THashMap<std::string_view, SkSL::LayoutFlag>;
1075
46.8k
    static SkNoDestructor<LayoutMap> sLayoutTokens(LayoutMap{
1076
46.8k
            {"location",                    SkSL::LayoutFlag::kLocation},
1077
46.8k
            {"offset",                      SkSL::LayoutFlag::kOffset},
1078
46.8k
            {"binding",                     SkSL::LayoutFlag::kBinding},
1079
46.8k
            {"texture",                     SkSL::LayoutFlag::kTexture},
1080
46.8k
            {"sampler",                     SkSL::LayoutFlag::kSampler},
1081
46.8k
            {"index",                       SkSL::LayoutFlag::kIndex},
1082
46.8k
            {"set",                         SkSL::LayoutFlag::kSet},
1083
46.8k
            {"builtin",                     SkSL::LayoutFlag::kBuiltin},
1084
46.8k
            {"input_attachment_index",      SkSL::LayoutFlag::kInputAttachmentIndex},
1085
46.8k
            {"origin_upper_left",           SkSL::LayoutFlag::kOriginUpperLeft},
1086
46.8k
            {"blend_support_all_equations", SkSL::LayoutFlag::kBlendSupportAllEquations},
1087
46.8k
            {"push_constant",               SkSL::LayoutFlag::kPushConstant},
1088
46.8k
            {"color",                       SkSL::LayoutFlag::kColor},
1089
46.8k
            {"vulkan",                      SkSL::LayoutFlag::kVulkan},
1090
46.8k
            {"metal",                       SkSL::LayoutFlag::kMetal},
1091
46.8k
            {"webgpu",                      SkSL::LayoutFlag::kWebGPU},
1092
46.8k
            {"direct3d",                    SkSL::LayoutFlag::kDirect3D},
1093
46.8k
            {"rgba8",                       SkSL::LayoutFlag::kRGBA8},
1094
46.8k
            {"rgba32f",                     SkSL::LayoutFlag::kRGBA32F},
1095
46.8k
            {"r32f",                        SkSL::LayoutFlag::kR32F},
1096
46.8k
            {"local_size_x",                SkSL::LayoutFlag::kLocalSizeX},
1097
46.8k
            {"local_size_y",                SkSL::LayoutFlag::kLocalSizeY},
1098
46.8k
            {"local_size_z",                SkSL::LayoutFlag::kLocalSizeZ},
1099
46.8k
    });
1100
1101
46.8k
    Layout result;
1102
46.8k
    if (this->checkNext(Token::Kind::TK_LAYOUT) &&
1103
46.8k
        this->expect(Token::Kind::TK_LPAREN, "'('")) {
1104
1105
6
        for (;;) {
1106
6
            Token t = this->nextToken();
1107
6
            std::string_view text = this->text(t);
1108
6
            SkSL::LayoutFlag* found = sLayoutTokens->find(text);
1109
1110
6
            if (!found) {
1111
0
                this->error(t, "'" + std::string(text) + "' is not a valid layout qualifier");
1112
6
            } else {
1113
6
                if (result.fFlags & *found) {
1114
0
                    this->error(t, "layout qualifier '" + std::string(text) +
1115
0
                                   "' appears more than once");
1116
0
                }
1117
1118
6
                result.fFlags |= *found;
1119
1120
6
                switch (*found) {
1121
0
                    case SkSL::LayoutFlag::kLocation:
1122
0
                        result.fLocation = this->layoutInt();
1123
0
                        break;
1124
0
                    case SkSL::LayoutFlag::kOffset:
1125
0
                        result.fOffset = this->layoutInt();
1126
0
                        break;
1127
0
                    case SkSL::LayoutFlag::kBinding:
1128
0
                        result.fBinding = this->layoutInt();
1129
0
                        break;
1130
0
                    case SkSL::LayoutFlag::kIndex:
1131
0
                        result.fIndex = this->layoutInt();
1132
0
                        break;
1133
0
                    case SkSL::LayoutFlag::kSet:
1134
0
                        result.fSet = this->layoutInt();
1135
0
                        break;
1136
0
                    case SkSL::LayoutFlag::kTexture:
1137
0
                        result.fTexture = this->layoutInt();
1138
0
                        break;
1139
0
                    case SkSL::LayoutFlag::kSampler:
1140
0
                        result.fSampler = this->layoutInt();
1141
0
                        break;
1142
6
                    case SkSL::LayoutFlag::kBuiltin:
1143
6
                        result.fBuiltin = this->layoutInt();
1144
6
                        break;
1145
0
                    case SkSL::LayoutFlag::kInputAttachmentIndex:
1146
0
                        result.fInputAttachmentIndex = this->layoutInt();
1147
0
                        break;
1148
0
                    case SkSL::LayoutFlag::kLocalSizeX:
1149
0
                        result.fLocalSizeX = this->layoutInt();
1150
0
                        break;
1151
0
                    case SkSL::LayoutFlag::kLocalSizeY:
1152
0
                        result.fLocalSizeY = this->layoutInt();
1153
0
                        break;
1154
0
                    case SkSL::LayoutFlag::kLocalSizeZ:
1155
0
                        result.fLocalSizeZ = this->layoutInt();
1156
0
                        break;
1157
0
                    default:
1158
0
                        break;
1159
6
                }
1160
6
            }
1161
6
            if (this->checkNext(Token::Kind::TK_RPAREN)) {
1162
6
                break;
1163
6
            }
1164
0
            if (!this->expect(Token::Kind::TK_COMMA, "','")) {
1165
0
                break;
1166
0
            }
1167
0
        }
1168
6
    }
1169
46.8k
    return result;
1170
46.8k
}
1171
1172
/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE |
1173
            VARYING | INLINE | WORKGROUP | READONLY | WRITEONLY | BUFFER)* */
1174
46.8k
Modifiers Parser::modifiers() {
1175
46.8k
    int start = this->peek().fOffset;
1176
46.8k
    SkSL::Layout layout = this->layout();
1177
46.8k
    Token raw = this->nextRawToken();
1178
46.8k
    int end = raw.fOffset;
1179
46.8k
    if (!is_whitespace(raw.fKind)) {
1180
46.8k
        this->pushback(raw);
1181
46.8k
    }
1182
46.8k
    ModifierFlags flags = ModifierFlag::kNone;
1183
50.8k
    for (;;) {
1184
50.8k
        ModifierFlags tokenFlag = parse_modifier_token(peek().fKind);
1185
50.8k
        if (tokenFlag == ModifierFlag::kNone) {
1186
46.8k
            break;
1187
46.8k
        }
1188
3.98k
        Token modifier = this->nextToken();
1189
3.98k
        if (ModifierFlags duplicateFlags = (tokenFlag & flags)) {
1190
294
            this->error(modifier, "'" + duplicateFlags.description() + "' appears more than once");
1191
294
        }
1192
3.98k
        flags |= tokenFlag;
1193
3.98k
        end = this->position(modifier).endOffset();
1194
3.98k
    }
1195
46.8k
    return Modifiers{Position::Range(start, end), layout, flags};
1196
46.8k
}
1197
1198
12.8k
std::unique_ptr<Statement> Parser::statementOrNop(Position pos, std::unique_ptr<Statement> stmt) {
1199
12.8k
    if (!stmt) {
1200
721
        stmt = Nop::Make();
1201
721
    }
1202
12.8k
    if (pos.valid() && !stmt->position().valid()) {
1203
9.06k
        stmt->setPosition(pos);
1204
9.06k
    }
1205
12.8k
    return stmt;
1206
12.8k
}
1207
1208
/* ifStatement | forStatement | doStatement | whileStatement | block | expression */
1209
30.8k
std::unique_ptr<Statement> Parser::statement(bool bracesIntroduceNewScope) {
1210
30.8k
    AutoDepth depth(this);
1211
30.8k
    if (!depth.increase()) {
1212
22
        return nullptr;
1213
22
    }
1214
30.8k
    switch (this->peek().fKind) {
1215
786
        case Token::Kind::TK_IF:
1216
786
            return this->ifStatement();
1217
600
        case Token::Kind::TK_FOR:
1218
600
            return this->forStatement();
1219
131
        case Token::Kind::TK_DO:
1220
131
            return this->doStatement();
1221
0
        case Token::Kind::TK_WHILE:
1222
0
            return this->whileStatement();
1223
16
        case Token::Kind::TK_SWITCH:
1224
16
            return this->switchStatement();
1225
284
        case Token::Kind::TK_RETURN:
1226
284
            return this->returnStatement();
1227
96
        case Token::Kind::TK_BREAK:
1228
96
            return this->breakStatement();
1229
0
        case Token::Kind::TK_CONTINUE:
1230
0
            return this->continueStatement();
1231
0
        case Token::Kind::TK_DISCARD:
1232
0
            return this->discardStatement();
1233
7.33k
        case Token::Kind::TK_LBRACE:
1234
7.33k
            return this->block(bracesIntroduceNewScope, /*adoptExistingSymbolTable=*/nullptr);
1235
6.69k
        case Token::Kind::TK_SEMICOLON:
1236
6.69k
            this->nextToken();
1237
6.69k
            return Nop::Make();
1238
21
        case Token::Kind::TK_CONST:
1239
21
            return this->varDeclarations();
1240
0
        case Token::Kind::TK_HIGHP:
1241
0
        case Token::Kind::TK_MEDIUMP:
1242
0
        case Token::Kind::TK_LOWP:
1243
13.3k
        case Token::Kind::TK_IDENTIFIER:
1244
13.3k
            return this->varDeclarationsOrExpressionStatement();
1245
1.44k
        default:
1246
1.44k
            return this->expressionStatement();
1247
30.8k
    }
1248
30.8k
}
1249
1250
const Type* Parser::findType(Position pos,
1251
                             Modifiers* modifiers,
1252
25.3k
                             std::string_view name) {
1253
25.3k
    const Context& context = fCompiler.context();
1254
25.3k
    const Symbol* symbol = this->symbolTable()->find(name);
1255
25.3k
    if (!symbol) {
1256
0
        this->error(pos, "no symbol named '" + std::string(name) + "'");
1257
0
        return context.fTypes.fPoison.get();
1258
0
    }
1259
25.3k
    if (!symbol->is<Type>()) {
1260
0
        this->error(pos, "symbol '" + std::string(name) + "' is not a type");
1261
0
        return context.fTypes.fPoison.get();
1262
0
    }
1263
25.3k
    const SkSL::Type* type = &symbol->as<Type>();
1264
25.3k
    if (!context.fConfig->fIsBuiltinCode) {
1265
20.0k
        if (!TypeReference::VerifyType(context, type, pos)) {
1266
1.34k
            return context.fTypes.fPoison.get();
1267
1.34k
        }
1268
20.0k
    }
1269
24.0k
    Position qualifierRange = modifiers->fPosition;
1270
24.0k
    if (qualifierRange.startOffset() == qualifierRange.endOffset()) {
1271
21.6k
        qualifierRange = this->rangeFrom(qualifierRange);
1272
21.6k
    }
1273
24.0k
    return modifiers ? type->applyQualifiers(context, &modifiers->fFlags, qualifierRange)
1274
24.0k
                     : type;
1275
25.3k
}
1276
1277
/* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* QUESTION? */
1278
33.8k
const Type* Parser::type(Modifiers* modifiers) {
1279
33.8k
    Token type;
1280
33.8k
    if (!this->expect(Token::Kind::TK_IDENTIFIER, "a type", &type)) {
1281
410
        return nullptr;
1282
410
    }
1283
33.3k
    if (!this->symbolTable()->isType(this->text(type))) {
1284
8.03k
        this->error(type, "no type named '" + std::string(this->text(type)) + "'");
1285
8.03k
        return fCompiler.context().fTypes.fInvalid.get();
1286
8.03k
    }
1287
25.3k
    const Type* result = this->findType(this->position(type), modifiers, this->text(type));
1288
25.3k
    if (result->isInterfaceBlock()) {
1289
        // SkSL puts interface blocks into the symbol table, but they aren't general-purpose types;
1290
        // you can't use them to declare a variable type or a function return type.
1291
0
        this->error(type, "expected a type, found '" + std::string(this->text(type)) + "'");
1292
0
        return fCompiler.context().fTypes.fInvalid.get();
1293
0
    }
1294
25.3k
    Token bracket;
1295
30.3k
    while (this->checkNext(Token::Kind::TK_LBRACKET, &bracket)) {
1296
6.11k
        if (this->checkNext(Token::Kind::TK_RBRACKET)) {
1297
228
            if (this->allowUnsizedArrays()) {
1298
0
                result = this->unsizedArrayType(result, this->rangeFrom(type));
1299
228
            } else {
1300
228
                this->error(this->rangeFrom(bracket), "unsized arrays are not permitted here");
1301
228
            }
1302
5.89k
        } else {
1303
5.89k
            SKSL_INT size;
1304
5.89k
            if (!this->arraySize(&size)) {
1305
1.12k
                return nullptr;
1306
1.12k
            }
1307
4.76k
            this->expect(Token::Kind::TK_RBRACKET, "']'");
1308
4.76k
            result = this->arrayType(result, size, this->rangeFrom(type));
1309
4.76k
        }
1310
6.11k
    }
1311
24.2k
    return result;
1312
25.3k
}
1313
1314
/* IDENTIFIER LBRACE
1315
     varDeclaration+
1316
   RBRACE (IDENTIFIER (LBRACKET expression RBRACKET)*)? SEMICOLON */
1317
12.8k
bool Parser::interfaceBlock(const Modifiers& modifiers) {
1318
12.8k
    Token typeName;
1319
12.8k
    if (!this->expectIdentifier(&typeName)) {
1320
0
        return false;
1321
0
    }
1322
12.8k
    if (this->peek().fKind != Token::Kind::TK_LBRACE) {
1323
        // we only get into interfaceBlock if we found a top-level identifier which was not a type.
1324
        // 99% of the time, the user was not actually intending to create an interface block, so
1325
        // it's better to report it as an unknown type
1326
11.5k
        this->error(typeName, "no type named '" + std::string(this->text(typeName)) + "'");
1327
11.5k
        return false;
1328
11.5k
    }
1329
1.23k
    this->nextToken();
1330
1.23k
    TArray<SkSL::Field> fields;
1331
1.40k
    while (!this->checkNext(Token::Kind::TK_RBRACE)) {
1332
415
        Position fieldPos = this->position(this->peek());
1333
415
        Modifiers fieldModifiers = this->modifiers();
1334
415
        const Type* type = this->type(&fieldModifiers);
1335
415
        if (!type) {
1336
61
            return false;
1337
61
        }
1338
405
        do {
1339
405
            Token fieldName;
1340
405
            if (!this->expectIdentifier(&fieldName)) {
1341
55
                return false;
1342
55
            }
1343
350
            const Type* actualType = type;
1344
350
            if (this->checkNext(Token::Kind::TK_LBRACKET)) {
1345
115
                Token sizeToken = this->peek();
1346
115
                if (sizeToken.fKind != Token::Kind::TK_RBRACKET) {
1347
104
                    SKSL_INT size;
1348
104
                    if (!this->arraySize(&size)) {
1349
35
                        return false;
1350
35
                    }
1351
69
                    actualType = this->arrayType(actualType, size, this->position(typeName));
1352
69
                } else if (this->allowUnsizedArrays()) {
1353
0
                    actualType = this->unsizedArrayType(actualType, this->position(typeName));
1354
11
                } else {
1355
11
                    this->error(sizeToken, "unsized arrays are not permitted here");
1356
11
                }
1357
80
                this->expect(Token::Kind::TK_RBRACKET, "']'");
1358
80
            }
1359
315
            if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1360
91
                return false;
1361
91
            }
1362
1363
224
            fields.push_back(SkSL::Field(this->rangeFrom(fieldPos),
1364
224
                                         fieldModifiers.fLayout,
1365
224
                                         fieldModifiers.fFlags,
1366
224
                                         this->text(fieldName),
1367
224
                                         actualType));
1368
224
        } while (this->checkNext(Token::Kind::TK_COMMA));
1369
354
    }
1370
988
    std::string_view instanceName;
1371
988
    Token instanceNameToken;
1372
988
    SKSL_INT size = 0;
1373
988
    if (this->checkIdentifier(&instanceNameToken)) {
1374
881
        instanceName = this->text(instanceNameToken);
1375
881
        if (this->checkNext(Token::Kind::TK_LBRACKET)) {
1376
772
            if (!this->arraySize(&size)) {
1377
192
                return false;
1378
192
            }
1379
580
            this->expect(Token::Kind::TK_RBRACKET, "']'");
1380
580
        }
1381
881
    }
1382
796
    this->expect(Token::Kind::TK_SEMICOLON, "';'");
1383
1384
796
    if (std::unique_ptr<SkSL::InterfaceBlock> ib = InterfaceBlock::Convert(fCompiler.context(),
1385
796
                                                                           this->position(typeName),
1386
796
                                                                           modifiers,
1387
796
                                                                           this->text(typeName),
1388
796
                                                                           std::move(fields),
1389
796
                                                                           instanceName,
1390
796
                                                                           size)) {
1391
0
        fProgramElements.push_back(std::move(ib));
1392
0
        return true;
1393
0
    }
1394
796
    return false;
1395
796
}
1396
1397
/* IF LPAREN expression RPAREN statement (ELSE statement)? */
1398
786
std::unique_ptr<Statement> Parser::ifStatement() {
1399
786
    Token start;
1400
786
    if (!this->expect(Token::Kind::TK_IF, "'if'", &start)) {
1401
0
        return nullptr;
1402
0
    }
1403
786
    if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1404
4
        return nullptr;
1405
4
    }
1406
782
    std::unique_ptr<Expression> test = this->expression();
1407
782
    if (!test) {
1408
12
        return nullptr;
1409
12
    }
1410
770
    if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1411
5
        return nullptr;
1412
5
    }
1413
765
    std::unique_ptr<Statement> ifTrue = this->statement();
1414
765
    if (!ifTrue) {
1415
109
        return nullptr;
1416
109
    }
1417
656
    std::unique_ptr<Statement> ifFalse;
1418
656
    if (this->checkNext(Token::Kind::TK_ELSE)) {
1419
114
        ifFalse = this->statement();
1420
114
        if (!ifFalse) {
1421
0
            return nullptr;
1422
0
        }
1423
114
    }
1424
656
    Position pos = this->rangeFrom(start);
1425
656
    return this->statementOrNop(pos, IfStatement::Convert(fCompiler.context(),
1426
656
                                                          pos,
1427
656
                                                          std::move(test),
1428
656
                                                          std::move(ifTrue),
1429
656
                                                          std::move(ifFalse)));
1430
656
}
1431
1432
/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
1433
131
std::unique_ptr<Statement> Parser::doStatement() {
1434
131
    Token start;
1435
131
    if (!this->expect(Token::Kind::TK_DO, "'do'", &start)) {
1436
0
        return nullptr;
1437
0
    }
1438
131
    std::unique_ptr<Statement> statement = this->statement();
1439
131
    if (!statement) {
1440
127
        return nullptr;
1441
127
    }
1442
4
    if (!this->expect(Token::Kind::TK_WHILE, "'while'")) {
1443
4
        return nullptr;
1444
4
    }
1445
0
    if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1446
0
        return nullptr;
1447
0
    }
1448
0
    std::unique_ptr<Expression> test = this->expression();
1449
0
    if (!test) {
1450
0
        return nullptr;
1451
0
    }
1452
0
    if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1453
0
        return nullptr;
1454
0
    }
1455
0
    if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1456
0
        return nullptr;
1457
0
    }
1458
0
    Position pos = this->rangeFrom(start);
1459
0
    return this->statementOrNop(pos, DoStatement::Convert(fCompiler.context(), pos,
1460
0
                                                          std::move(statement), std::move(test)));
1461
0
}
1462
1463
/* WHILE LPAREN expression RPAREN STATEMENT */
1464
0
std::unique_ptr<Statement> Parser::whileStatement() {
1465
0
    Token start;
1466
0
    if (!this->expect(Token::Kind::TK_WHILE, "'while'", &start)) {
1467
0
        return nullptr;
1468
0
    }
1469
0
    if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1470
0
        return nullptr;
1471
0
    }
1472
0
    std::unique_ptr<Expression> test = this->expression();
1473
0
    if (!test) {
1474
0
        return nullptr;
1475
0
    }
1476
0
    if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1477
0
        return nullptr;
1478
0
    }
1479
0
    std::unique_ptr<Statement> statement = this->statement();
1480
0
    if (!statement) {
1481
0
        return nullptr;
1482
0
    }
1483
0
    Position pos = this->rangeFrom(start);
1484
0
    return this->statementOrNop(pos, ForStatement::ConvertWhile(fCompiler.context(), pos,
1485
0
                                                                std::move(test),
1486
0
                                                                std::move(statement)));
1487
0
}
1488
1489
/* COLON statement* */
1490
bool Parser::switchCaseBody(ExpressionArray* values,
1491
                            StatementArray* caseBlocks,
1492
128
                            std::unique_ptr<Expression> caseValue) {
1493
128
    if (!this->expect(Token::Kind::TK_COLON, "':'")) {
1494
0
        return false;
1495
0
    }
1496
128
    StatementArray statements;
1497
336
    while (this->peek().fKind != Token::Kind::TK_RBRACE &&
1498
336
           this->peek().fKind != Token::Kind::TK_CASE &&
1499
336
           this->peek().fKind != Token::Kind::TK_DEFAULT) {
1500
208
        std::unique_ptr<Statement> s = this->statement();
1501
208
        if (!s) {
1502
0
            return false;
1503
0
        }
1504
208
        statements.push_back(std::move(s));
1505
208
    }
1506
128
    values->push_back(std::move(caseValue));
1507
128
    caseBlocks->push_back(SkSL::Block::Make(Position(), std::move(statements),
1508
128
                                            Block::Kind::kUnbracedBlock));
1509
128
    return true;
1510
128
}
1511
1512
/* CASE expression COLON statement* */
1513
128
bool Parser::switchCase(ExpressionArray* values, StatementArray* caseBlocks) {
1514
128
    Token start;
1515
128
    if (!this->expect(Token::Kind::TK_CASE, "'case'", &start)) {
1516
0
        return false;
1517
0
    }
1518
128
    std::unique_ptr<Expression> caseValue = this->expression();
1519
128
    if (!caseValue) {
1520
0
        return false;
1521
0
    }
1522
128
    return this->switchCaseBody(values, caseBlocks, std::move(caseValue));
1523
128
}
1524
1525
/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
1526
16
std::unique_ptr<Statement> Parser::switchStatement() {
1527
16
    Token start;
1528
16
    if (!this->expect(Token::Kind::TK_SWITCH, "'switch'", &start)) {
1529
0
        return nullptr;
1530
0
    }
1531
16
    if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1532
0
        return nullptr;
1533
0
    }
1534
16
    std::unique_ptr<Expression> value = this->expression();
1535
16
    if (!value) {
1536
0
        return nullptr;
1537
0
    }
1538
16
    if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1539
0
        return nullptr;
1540
0
    }
1541
16
    if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
1542
0
        return nullptr;
1543
0
    }
1544
1545
16
    std::unique_ptr<SymbolTable> symbolTable;
1546
16
    ExpressionArray values;
1547
16
    StatementArray caseBlocks;
1548
16
    {
1549
        // Keeping a tight scope around AutoSymbolTable is important here. SwitchStatement::Convert
1550
        // may end up creating a new symbol table if the HoistSwitchVarDeclarationsAtTopLevel
1551
        // transform is used. We want ~AutoSymbolTable to happen first, so it can restore the
1552
        // context's active symbol table to the enclosing block instead of the switch's inner block.
1553
16
        AutoSymbolTable symbols(this, &symbolTable);
1554
1555
144
        while (this->peek().fKind == Token::Kind::TK_CASE) {
1556
128
            if (!this->switchCase(&values, &caseBlocks)) {
1557
0
                return nullptr;
1558
0
            }
1559
128
        }
1560
        // Requiring `default:` to be last (in defiance of C and GLSL) was a deliberate decision.
1561
        // Other parts of the compiler are allowed to rely upon this assumption.
1562
16
        if (this->checkNext(Token::Kind::TK_DEFAULT)) {
1563
0
            if (!this->switchCaseBody(&values, &caseBlocks, /*value=*/nullptr)) {
1564
0
                return nullptr;
1565
0
            }
1566
0
        }
1567
16
        if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
1568
0
            return nullptr;
1569
0
        }
1570
16
    }
1571
1572
16
    Position pos = this->rangeFrom(start);
1573
16
    return this->statementOrNop(pos, SwitchStatement::Convert(fCompiler.context(), pos,
1574
16
                                                              std::move(value),
1575
16
                                                              std::move(values),
1576
16
                                                              std::move(caseBlocks),
1577
16
                                                              std::move(symbolTable)));
1578
16
}
1579
1580
1.00k
static Position range_of_at_least_one_char(int start, int end) {
1581
1.00k
    return Position::Range(start, std::max(end, start + 1));
1582
1.00k
}
1583
1584
/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
1585
   STATEMENT */
1586
600
std::unique_ptr<Statement> Parser::forStatement() {
1587
600
    Token start;
1588
600
    if (!this->expect(Token::Kind::TK_FOR, "'for'", &start)) {
1589
0
        return nullptr;
1590
0
    }
1591
600
    Token lparen;
1592
600
    if (!this->expect(Token::Kind::TK_LPAREN, "'('", &lparen)) {
1593
6
        return nullptr;
1594
6
    }
1595
594
    std::unique_ptr<SymbolTable> symbolTable;
1596
594
    std::unique_ptr<Statement> initializer;
1597
594
    std::unique_ptr<Expression> test;
1598
594
    std::unique_ptr<Expression> next;
1599
594
    std::unique_ptr<Statement> statement;
1600
594
    int firstSemicolonOffset;
1601
594
    Token secondSemicolon;
1602
594
    Token rparen;
1603
594
    {
1604
594
        AutoSymbolTable symbols(this, &symbolTable);
1605
1606
594
        Token nextToken = this->peek();
1607
594
        if (nextToken.fKind == Token::Kind::TK_SEMICOLON) {
1608
            // An empty init-statement.
1609
211
            firstSemicolonOffset = this->nextToken().fOffset;
1610
383
        } else {
1611
            // The init-statement must be an expression or variable declaration.
1612
383
            initializer = this->varDeclarationsOrExpressionStatement();
1613
383
            if (!initializer) {
1614
15
                return nullptr;
1615
15
            }
1616
368
            firstSemicolonOffset = fLexer.getCheckpoint().fOffset - 1;
1617
368
        }
1618
579
        if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
1619
194
            test = this->expression();
1620
194
            if (!test) {
1621
10
                return nullptr;
1622
10
            }
1623
194
        }
1624
569
        if (!this->expect(Token::Kind::TK_SEMICOLON, "';'", &secondSemicolon)) {
1625
8
            return nullptr;
1626
8
        }
1627
561
        if (this->peek().fKind != Token::Kind::TK_RPAREN) {
1628
285
            next = this->expression();
1629
285
            if (!next) {
1630
14
                return nullptr;
1631
14
            }
1632
285
        }
1633
547
        if (!this->expect(Token::Kind::TK_RPAREN, "')'", &rparen)) {
1634
5
            return nullptr;
1635
5
        }
1636
542
        statement = this->statement(/*bracesIntroduceNewScope=*/false);
1637
542
        if (!statement) {
1638
208
            return nullptr;
1639
208
        }
1640
542
    }
1641
334
    Position pos = this->rangeFrom(start);
1642
334
    ForLoopPositions loopPositions{
1643
334
            range_of_at_least_one_char(lparen.fOffset + 1, firstSemicolonOffset),
1644
334
            range_of_at_least_one_char(firstSemicolonOffset + 1, secondSemicolon.fOffset),
1645
334
            range_of_at_least_one_char(secondSemicolon.fOffset + 1, rparen.fOffset),
1646
334
    };
1647
334
    return this->statementOrNop(pos, ForStatement::Convert(fCompiler.context(), pos, loopPositions,
1648
334
                                                           std::move(initializer),
1649
334
                                                           std::move(test),
1650
334
                                                           std::move(next),
1651
334
                                                           std::move(statement),
1652
334
                                                           std::move(symbolTable)));
1653
542
}
1654
1655
/* RETURN expression? SEMICOLON */
1656
284
std::unique_ptr<Statement> Parser::returnStatement() {
1657
284
    Token start;
1658
284
    if (!this->expect(Token::Kind::TK_RETURN, "'return'", &start)) {
1659
0
        return nullptr;
1660
0
    }
1661
284
    std::unique_ptr<Expression> expression;
1662
284
    if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
1663
284
        expression = this->expression();
1664
284
        if (!expression) {
1665
0
            return nullptr;
1666
0
        }
1667
284
    }
1668
284
    if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1669
0
        return nullptr;
1670
0
    }
1671
    // We do not check for errors, or coerce the value to the correct type, until the return
1672
    // statement is actually added to a function. (This is done in FunctionDefinition::Convert.)
1673
284
    return ReturnStatement::Make(this->rangeFrom(start), std::move(expression));
1674
284
}
1675
1676
/* BREAK SEMICOLON */
1677
96
std::unique_ptr<Statement> Parser::breakStatement() {
1678
96
    Token start;
1679
96
    if (!this->expect(Token::Kind::TK_BREAK, "'break'", &start)) {
1680
0
        return nullptr;
1681
0
    }
1682
96
    if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1683
0
        return nullptr;
1684
0
    }
1685
96
    return SkSL::BreakStatement::Make(this->position(start));
1686
96
}
1687
1688
/* CONTINUE SEMICOLON */
1689
0
std::unique_ptr<Statement> Parser::continueStatement() {
1690
0
    Token start;
1691
0
    if (!this->expect(Token::Kind::TK_CONTINUE, "'continue'", &start)) {
1692
0
        return nullptr;
1693
0
    }
1694
0
    if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1695
0
        return nullptr;
1696
0
    }
1697
0
    return SkSL::ContinueStatement::Make(this->position(start));
1698
0
}
1699
1700
/* DISCARD SEMICOLON */
1701
0
std::unique_ptr<Statement> Parser::discardStatement() {
1702
0
    Token start;
1703
0
    if (!this->expect(Token::Kind::TK_DISCARD, "'continue'", &start)) {
1704
0
        return nullptr;
1705
0
    }
1706
0
    if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1707
0
        return nullptr;
1708
0
    }
1709
0
    Position pos = this->position(start);
1710
0
    return this->statementOrNop(pos, SkSL::DiscardStatement::Convert(fCompiler.context(), pos));
1711
0
}
1712
1713
/* LBRACE statement* RBRACE */
1714
std::unique_ptr<Statement> Parser::block(bool introduceNewScope,
1715
12.7k
                                         std::unique_ptr<SymbolTable>* adoptExistingSymbolTable) {
1716
    // We can't introduce a new scope _and_ adopt an existing symbol table.
1717
12.7k
    SkASSERT(!(introduceNewScope && adoptExistingSymbolTable));
1718
1719
12.7k
    AutoDepth depth(this);
1720
12.7k
    Token start;
1721
12.7k
    if (!this->expect(Token::Kind::TK_LBRACE, "'{'", &start)) {
1722
231
        return nullptr;
1723
231
    }
1724
12.5k
    if (!depth.increase()) {
1725
23
        return nullptr;
1726
23
    }
1727
1728
12.5k
    std::unique_ptr<SymbolTable> newSymbolTable;
1729
12.5k
    std::unique_ptr<SymbolTable>* symbolTableToUse =
1730
12.5k
            adoptExistingSymbolTable ? adoptExistingSymbolTable : &newSymbolTable;
1731
1732
12.5k
    StatementArray statements;
1733
12.5k
    {
1734
12.5k
        AutoSymbolTable symbols(this, symbolTableToUse, /*enable=*/introduceNewScope);
1735
1736
        // Consume statements until we reach the closing brace.
1737
31.8k
        for (;;) {
1738
31.8k
            Token::Kind tokenKind = this->peek().fKind;
1739
31.8k
            if (tokenKind == Token::Kind::TK_RBRACE) {
1740
2.54k
                this->nextToken();
1741
2.54k
                break;
1742
2.54k
            }
1743
29.3k
            if (tokenKind == Token::Kind::TK_END_OF_FILE) {
1744
281
                this->error(this->peek(), "expected '}', but found end of file");
1745
281
                return nullptr;
1746
281
            }
1747
29.0k
            if (std::unique_ptr<Statement> statement = this->statement()) {
1748
19.5k
                statements.push_back(std::move(statement));
1749
19.5k
            }
1750
29.0k
            if (fEncounteredFatalError) {
1751
9.67k
                return nullptr;
1752
9.67k
            }
1753
29.0k
        }
1754
12.5k
    }
1755
2.54k
    return SkSL::Block::MakeBlock(this->rangeFrom(start),
1756
2.54k
                                  std::move(statements),
1757
2.54k
                                  Block::Kind::kBracedScope,
1758
2.54k
                                  std::move(*symbolTableToUse));
1759
12.5k
}
SkSL::Parser::block(bool, std::__1::unique_ptr<SkSL::SymbolTable, std::__1::default_delete<SkSL::SymbolTable> >*)
Line
Count
Source
1715
12.7k
                                         std::unique_ptr<SymbolTable>* adoptExistingSymbolTable) {
1716
    // We can't introduce a new scope _and_ adopt an existing symbol table.
1717
12.7k
    SkASSERT(!(introduceNewScope && adoptExistingSymbolTable));
1718
1719
12.7k
    AutoDepth depth(this);
1720
12.7k
    Token start;
1721
12.7k
    if (!this->expect(Token::Kind::TK_LBRACE, "'{'", &start)) {
1722
231
        return nullptr;
1723
231
    }
1724
12.5k
    if (!depth.increase()) {
1725
23
        return nullptr;
1726
23
    }
1727
1728
12.5k
    std::unique_ptr<SymbolTable> newSymbolTable;
1729
12.5k
    std::unique_ptr<SymbolTable>* symbolTableToUse =
1730
12.5k
            adoptExistingSymbolTable ? adoptExistingSymbolTable : &newSymbolTable;
1731
1732
12.5k
    StatementArray statements;
1733
12.5k
    {
1734
12.5k
        AutoSymbolTable symbols(this, symbolTableToUse, /*enable=*/introduceNewScope);
1735
1736
        // Consume statements until we reach the closing brace.
1737
31.8k
        for (;;) {
1738
31.8k
            Token::Kind tokenKind = this->peek().fKind;
1739
31.8k
            if (tokenKind == Token::Kind::TK_RBRACE) {
1740
2.54k
                this->nextToken();
1741
2.54k
                break;
1742
2.54k
            }
1743
29.3k
            if (tokenKind == Token::Kind::TK_END_OF_FILE) {
1744
281
                this->error(this->peek(), "expected '}', but found end of file");
1745
281
                return nullptr;
1746
281
            }
1747
29.0k
            if (std::unique_ptr<Statement> statement = this->statement()) {
1748
19.5k
                statements.push_back(std::move(statement));
1749
19.5k
            }
1750
29.0k
            if (fEncounteredFatalError) {
1751
9.67k
                return nullptr;
1752
9.67k
            }
1753
29.0k
        }
1754
12.5k
    }
1755
2.54k
    return SkSL::Block::MakeBlock(this->rangeFrom(start),
1756
2.54k
                                  std::move(statements),
1757
2.54k
                                  Block::Kind::kBracedScope,
1758
2.54k
                                  std::move(*symbolTableToUse));
1759
12.5k
}
Unexecuted instantiation: SkSL::Parser::block(bool, std::__1::unique_ptr<SkSL::SymbolTable, std::__1::default_delete<SkSL::SymbolTable> >*)
1760
1761
/* expression SEMICOLON */
1762
12.6k
std::unique_ptr<Statement> Parser::expressionStatement() {
1763
12.6k
    std::unique_ptr<Expression> expr = this->expression();
1764
12.6k
    if (!expr) {
1765
1.29k
        return nullptr;
1766
1.29k
    }
1767
11.3k
    if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1768
2.04k
        return nullptr;
1769
2.04k
    }
1770
9.28k
    Position pos = expr->position();
1771
9.28k
    return this->statementOrNop(pos, SkSL::ExpressionStatement::Convert(fCompiler.context(),
1772
9.28k
                                                                        std::move(expr)));
1773
11.3k
}
1774
1775
272k
std::unique_ptr<Expression> Parser::poison(Position pos) {
1776
272k
    return Poison::Make(pos, fCompiler.context());
1777
272k
}
1778
1779
std::unique_ptr<Expression> Parser::expressionOrPoison(Position pos,
1780
723k
                                                       std::unique_ptr<Expression> expr) {
1781
723k
    if (!expr) {
1782
        // If no expression was passed in, create a poison expression.
1783
268k
        expr = this->poison(pos);
1784
268k
    }
1785
    // If a valid position was passed in, it must match the expression's position.
1786
723k
    SkASSERTF(!pos.valid() || expr->position() == pos,
1787
723k
              "expected expression position (%d-%d), but received (%d-%d)",
1788
723k
              pos.startOffset(),
1789
723k
              pos.endOffset(),
1790
723k
              expr->position().startOffset(),
1791
723k
              expr->position().endOffset());
1792
723k
    return expr;
1793
723k
}
1794
1795
bool Parser::operatorRight(Parser::AutoDepth& depth,
1796
                           Operator::Kind op,
1797
                           BinaryParseFn rightFn,
1798
202k
                           std::unique_ptr<Expression>& expr) {
1799
202k
    this->nextToken();
1800
202k
    if (!depth.increase()) {
1801
93
        return false;
1802
93
    }
1803
202k
    std::unique_ptr<Expression> right = (this->*rightFn)();
1804
202k
    if (!right) {
1805
10.7k
        return false;
1806
10.7k
    }
1807
191k
    Position pos = expr->position().rangeThrough(right->position());
1808
191k
    expr = this->expressionOrPoison(pos, BinaryExpression::Convert(fCompiler.context(), pos,
1809
191k
                                                                   std::move(expr), op,
1810
191k
                                                                   std::move(right)));
1811
191k
    return true;
1812
202k
}
1813
1814
/* assignmentExpression (COMMA assignmentExpression)* */
1815
127k
std::unique_ptr<Expression> Parser::expression() {
1816
127k
    AutoDepth depth(this);
1817
127k
    [[maybe_unused]] Token start = this->peek();
1818
127k
    std::unique_ptr<Expression> result = this->assignmentExpression();
1819
127k
    if (!result) {
1820
15.4k
        return nullptr;
1821
15.4k
    }
1822
138k
    while (this->peek().fKind == Token::Kind::TK_COMMA) {
1823
27.7k
        if (!this->operatorRight(depth, Operator::Kind::COMMA, &Parser::assignmentExpression,
1824
27.7k
                                 result)) {
1825
2.01k
            return nullptr;
1826
2.01k
        }
1827
27.7k
    }
1828
110k
    SkASSERTF(result->position().valid(), "Expression %s has invalid position",
1829
110k
              result->description().c_str());
1830
110k
    SkASSERTF(result->position().startOffset() == this->position(start).startOffset(),
1831
110k
              "Expected %s to start at %d (first token: '%.*s'), but it has range %d-%d\n",
1832
110k
              result->description().c_str(), this->position(start).startOffset(),
1833
110k
              (int)this->text(start).length(), this->text(start).data(),
1834
110k
              result->position().startOffset(), result->position().endOffset());
1835
110k
    return result;
1836
112k
}
SkSL::Parser::expression()
Line
Count
Source
1815
127k
std::unique_ptr<Expression> Parser::expression() {
1816
127k
    AutoDepth depth(this);
1817
127k
    [[maybe_unused]] Token start = this->peek();
1818
127k
    std::unique_ptr<Expression> result = this->assignmentExpression();
1819
127k
    if (!result) {
1820
15.4k
        return nullptr;
1821
15.4k
    }
1822
138k
    while (this->peek().fKind == Token::Kind::TK_COMMA) {
1823
27.7k
        if (!this->operatorRight(depth, Operator::Kind::COMMA, &Parser::assignmentExpression,
1824
27.7k
                                 result)) {
1825
2.01k
            return nullptr;
1826
2.01k
        }
1827
27.7k
    }
1828
110k
    SkASSERTF(result->position().valid(), "Expression %s has invalid position",
1829
110k
              result->description().c_str());
1830
110k
    SkASSERTF(result->position().startOffset() == this->position(start).startOffset(),
1831
110k
              "Expected %s to start at %d (first token: '%.*s'), but it has range %d-%d\n",
1832
110k
              result->description().c_str(), this->position(start).startOffset(),
1833
110k
              (int)this->text(start).length(), this->text(start).data(),
1834
110k
              result->position().startOffset(), result->position().endOffset());
1835
110k
    return result;
1836
112k
}
Unexecuted instantiation: SkSL::Parser::expression()
1837
1838
/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1839
   BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1840
   assignmentExpression)*
1841
 */
1842
272k
std::unique_ptr<Expression> Parser::assignmentExpression() {
1843
272k
    AutoDepth depth(this);
1844
272k
    std::unique_ptr<Expression> result = this->ternaryExpression();
1845
272k
    if (!result) {
1846
24.8k
        return nullptr;
1847
24.8k
    }
1848
271k
    for (;;) {
1849
271k
        Operator::Kind op;
1850
271k
        switch (this->peek().fKind) {
1851
19.5k
            case Token::Kind::TK_EQ:           op = Operator::Kind::EQ;           break;
1852
1.72k
            case Token::Kind::TK_STAREQ:       op = Operator::Kind::STAREQ;       break;
1853
2.06k
            case Token::Kind::TK_SLASHEQ:      op = Operator::Kind::SLASHEQ;      break;
1854
129
            case Token::Kind::TK_PERCENTEQ:    op = Operator::Kind::PERCENTEQ;    break;
1855
1.08k
            case Token::Kind::TK_PLUSEQ:       op = Operator::Kind::PLUSEQ;       break;
1856
983
            case Token::Kind::TK_MINUSEQ:      op = Operator::Kind::MINUSEQ;      break;
1857
42
            case Token::Kind::TK_SHLEQ:        op = Operator::Kind::SHLEQ;        break;
1858
13
            case Token::Kind::TK_SHREQ:        op = Operator::Kind::SHREQ;        break;
1859
62
            case Token::Kind::TK_BITWISEANDEQ: op = Operator::Kind::BITWISEANDEQ; break;
1860
33
            case Token::Kind::TK_BITWISEXOREQ: op = Operator::Kind::BITWISEXOREQ; break;
1861
187
            case Token::Kind::TK_BITWISEOREQ:  op = Operator::Kind::BITWISEOREQ;  break;
1862
245k
            default:                           return result;
1863
271k
        }
1864
25.9k
        if (!this->operatorRight(depth, op, &Parser::assignmentExpression, result)) {
1865
1.87k
            return nullptr;
1866
1.87k
        }
1867
25.9k
    }
1868
247k
}
1869
1870
/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
1871
272k
std::unique_ptr<Expression> Parser::ternaryExpression() {
1872
272k
    AutoDepth depth(this);
1873
272k
    std::unique_ptr<Expression> base = this->logicalOrExpression();
1874
272k
    if (!base) {
1875
23.5k
        return nullptr;
1876
23.5k
    }
1877
248k
    if (!this->checkNext(Token::Kind::TK_QUESTION)) {
1878
244k
        return base;
1879
244k
    }
1880
4.04k
    if (!depth.increase()) {
1881
32
        return nullptr;
1882
32
    }
1883
4.01k
    std::unique_ptr<Expression> trueExpr = this->expression();
1884
4.01k
    if (!trueExpr) {
1885
596
        return nullptr;
1886
596
    }
1887
3.41k
    if (!this->expect(Token::Kind::TK_COLON, "':'")) {
1888
315
        return nullptr;
1889
315
    }
1890
3.10k
    std::unique_ptr<Expression> falseExpr = this->assignmentExpression();
1891
3.10k
    if (!falseExpr) {
1892
357
        return nullptr;
1893
357
    }
1894
2.74k
    Position pos = base->position().rangeThrough(falseExpr->position());
1895
2.74k
    return this->expressionOrPoison(pos, TernaryExpression::Convert(fCompiler.context(),
1896
2.74k
                                                                    pos, std::move(base),
1897
2.74k
                                                                    std::move(trueExpr),
1898
2.74k
                                                                    std::move(falseExpr)));
1899
3.10k
}
1900
1901
/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
1902
272k
std::unique_ptr<Expression> Parser::logicalOrExpression() {
1903
272k
    AutoDepth depth(this);
1904
272k
    std::unique_ptr<Expression> result = this->logicalXorExpression();
1905
272k
    if (!result) {
1906
23.3k
        return nullptr;
1907
23.3k
    }
1908
250k
    while (this->peek().fKind == Token::Kind::TK_LOGICALOR) {
1909
1.57k
        if (!this->operatorRight(depth, Operator::Kind::LOGICALOR, &Parser::logicalXorExpression,
1910
1.57k
                                 result)) {
1911
134
            return nullptr;
1912
134
        }
1913
1.57k
    }
1914
248k
    return result;
1915
248k
}
1916
1917
/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
1918
273k
std::unique_ptr<Expression> Parser::logicalXorExpression() {
1919
273k
    AutoDepth depth(this);
1920
273k
    std::unique_ptr<Expression> result = this->logicalAndExpression();
1921
273k
    if (!result) {
1922
23.4k
        return nullptr;
1923
23.4k
    }
1924
251k
    while (this->peek().fKind == Token::Kind::TK_LOGICALXOR) {
1925
726
        if (!this->operatorRight(depth, Operator::Kind::LOGICALXOR, &Parser::logicalAndExpression,
1926
726
                                 result)) {
1927
110
            return nullptr;
1928
110
        }
1929
726
    }
1930
250k
    return result;
1931
250k
}
1932
1933
/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
1934
274k
std::unique_ptr<Expression> Parser::logicalAndExpression() {
1935
274k
    AutoDepth depth(this);
1936
274k
    std::unique_ptr<Expression> result = this->bitwiseOrExpression();
1937
274k
    if (!result) {
1938
23.4k
        return nullptr;
1939
23.4k
    }
1940
252k
    while (this->peek().fKind == Token::Kind::TK_LOGICALAND) {
1941
1.10k
        if (!this->operatorRight(depth, Operator::Kind::LOGICALAND, &Parser::bitwiseOrExpression,
1942
1.10k
                                 result)) {
1943
97
            return nullptr;
1944
97
        }
1945
1.10k
    }
1946
251k
    return result;
1947
251k
}
1948
1949
/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
1950
275k
std::unique_ptr<Expression> Parser::bitwiseOrExpression() {
1951
275k
    AutoDepth depth(this);
1952
275k
    std::unique_ptr<Expression> result = this->bitwiseXorExpression();
1953
275k
    if (!result) {
1954
23.2k
        return nullptr;
1955
23.2k
    }
1956
254k
    while (this->peek().fKind == Token::Kind::TK_BITWISEOR) {
1957
2.11k
        if (!this->operatorRight(depth, Operator::Kind::BITWISEOR, &Parser::bitwiseXorExpression,
1958
2.11k
                                 result)) {
1959
315
            return nullptr;
1960
315
        }
1961
2.11k
    }
1962
252k
    return result;
1963
252k
}
1964
1965
/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
1966
277k
std::unique_ptr<Expression> Parser::bitwiseXorExpression() {
1967
277k
    AutoDepth depth(this);
1968
277k
    std::unique_ptr<Expression> result = this->bitwiseAndExpression();
1969
277k
    if (!result) {
1970
23.3k
        return nullptr;
1971
23.3k
    }
1972
254k
    while (this->peek().fKind == Token::Kind::TK_BITWISEXOR) {
1973
705
        if (!this->operatorRight(depth, Operator::Kind::BITWISEXOR, &Parser::bitwiseAndExpression,
1974
705
                                 result)) {
1975
159
            return nullptr;
1976
159
        }
1977
705
    }
1978
254k
    return result;
1979
254k
}
1980
1981
/* equalityExpression (BITWISEAND equalityExpression)* */
1982
278k
std::unique_ptr<Expression> Parser::bitwiseAndExpression() {
1983
278k
    AutoDepth depth(this);
1984
278k
    std::unique_ptr<Expression> result = this->equalityExpression();
1985
278k
    if (!result) {
1986
22.8k
        return nullptr;
1987
22.8k
    }
1988
259k
    while (this->peek().fKind == Token::Kind::TK_BITWISEAND) {
1989
4.19k
        if (!this->operatorRight(depth, Operator::Kind::BITWISEAND, &Parser::equalityExpression,
1990
4.19k
                                 result)) {
1991
631
            return nullptr;
1992
631
        }
1993
4.19k
    }
1994
254k
    return result;
1995
255k
}
1996
1997
/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
1998
282k
std::unique_ptr<Expression> Parser::equalityExpression() {
1999
282k
    AutoDepth depth(this);
2000
282k
    std::unique_ptr<Expression> result = this->relationalExpression();
2001
282k
    if (!result) {
2002
22.9k
        return nullptr;
2003
22.9k
    }
2004
271k
    for (;;) {
2005
271k
        Operator::Kind op;
2006
271k
        switch (this->peek().fKind) {
2007
7.28k
            case Token::Kind::TK_EQEQ: op = Operator::Kind::EQEQ; break;
2008
4.94k
            case Token::Kind::TK_NEQ:  op = Operator::Kind::NEQ;  break;
2009
259k
            default:                   return result;
2010
271k
        }
2011
12.2k
        if (!this->operatorRight(depth, op, &Parser::relationalExpression, result)) {
2012
529
            return nullptr;
2013
529
        }
2014
12.2k
    }
2015
259k
}
2016
2017
/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
2018
294k
std::unique_ptr<Expression> Parser::relationalExpression() {
2019
294k
    AutoDepth depth(this);
2020
294k
    std::unique_ptr<Expression> result = this->shiftExpression();
2021
294k
    if (!result) {
2022
22.8k
        return nullptr;
2023
22.8k
    }
2024
290k
    for (;;) {
2025
290k
        Operator::Kind op;
2026
290k
        switch (this->peek().fKind) {
2027
9.60k
            case Token::Kind::TK_LT:   op = Operator::Kind::LT;   break;
2028
7.88k
            case Token::Kind::TK_GT:   op = Operator::Kind::GT;   break;
2029
752
            case Token::Kind::TK_LTEQ: op = Operator::Kind::LTEQ; break;
2030
459
            case Token::Kind::TK_GTEQ: op = Operator::Kind::GTEQ; break;
2031
271k
            default:                   return result;
2032
290k
        }
2033
18.7k
        if (!this->operatorRight(depth, op, &Parser::shiftExpression, result)) {
2034
666
            return nullptr;
2035
666
        }
2036
18.7k
    }
2037
272k
}
2038
2039
/* additiveExpression ((SHL | SHR) additiveExpression)* */
2040
313k
std::unique_ptr<Expression> Parser::shiftExpression() {
2041
313k
    AutoDepth depth(this);
2042
313k
    std::unique_ptr<Expression> result = this->additiveExpression();
2043
313k
    if (!result) {
2044
23.3k
        return nullptr;
2045
23.3k
    }
2046
291k
    for (;;) {
2047
291k
        Operator::Kind op;
2048
291k
        switch (this->peek().fKind) {
2049
280
            case Token::Kind::TK_SHL: op = Operator::Kind::SHL; break;
2050
1.55k
            case Token::Kind::TK_SHR: op = Operator::Kind::SHR; break;
2051
290k
            default:                  return result;
2052
291k
        }
2053
1.83k
        if (!this->operatorRight(depth, op, &Parser::additiveExpression, result)) {
2054
145
            return nullptr;
2055
145
        }
2056
1.83k
    }
2057
290k
}
2058
2059
/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
2060
315k
std::unique_ptr<Expression> Parser::additiveExpression() {
2061
315k
    AutoDepth depth(this);
2062
315k
    std::unique_ptr<Expression> result = this->multiplicativeExpression();
2063
315k
    if (!result) {
2064
21.3k
        return nullptr;
2065
21.3k
    }
2066
339k
    for (;;) {
2067
339k
        Operator::Kind op;
2068
339k
        switch (this->peek().fKind) {
2069
22.7k
            case Token::Kind::TK_PLUS:  op = Operator::Kind::PLUS;  break;
2070
24.8k
            case Token::Kind::TK_MINUS: op = Operator::Kind::MINUS; break;
2071
291k
            default:                    return result;
2072
339k
        }
2073
47.6k
        if (!this->operatorRight(depth, op, &Parser::multiplicativeExpression, result)) {
2074
2.15k
            return nullptr;
2075
2.15k
        }
2076
47.6k
    }
2077
294k
}
2078
2079
/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
2080
363k
std::unique_ptr<Expression> Parser::multiplicativeExpression() {
2081
363k
    AutoDepth depth(this);
2082
363k
    std::unique_ptr<Expression> result = this->unaryExpression();
2083
363k
    if (!result) {
2084
21.4k
        return nullptr;
2085
21.4k
    }
2086
397k
    for (;;) {
2087
397k
        Operator::Kind op;
2088
397k
        switch (this->peek().fKind) {
2089
37.4k
            case Token::Kind::TK_STAR:    op = Operator::Kind::STAR;    break;
2090
18.7k
            case Token::Kind::TK_SLASH:   op = Operator::Kind::SLASH;   break;
2091
1.47k
            case Token::Kind::TK_PERCENT: op = Operator::Kind::PERCENT; break;
2092
339k
            default:                      return result;
2093
397k
        }
2094
57.6k
        if (!this->operatorRight(depth, op, &Parser::unaryExpression, result)) {
2095
1.98k
            return nullptr;
2096
1.98k
        }
2097
57.6k
    }
2098
341k
}
2099
2100
/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
2101
468k
std::unique_ptr<Expression> Parser::unaryExpression() {
2102
468k
    AutoDepth depth(this);
2103
468k
    Operator::Kind op;
2104
468k
    Token start = this->peek();
2105
468k
    switch (start.fKind) {
2106
7.37k
        case Token::Kind::TK_PLUS:       op = Operator::Kind::PLUS;       break;
2107
27.5k
        case Token::Kind::TK_MINUS:      op = Operator::Kind::MINUS;      break;
2108
5.04k
        case Token::Kind::TK_LOGICALNOT: op = Operator::Kind::LOGICALNOT; break;
2109
4.67k
        case Token::Kind::TK_BITWISENOT: op = Operator::Kind::BITWISENOT; break;
2110
1.02k
        case Token::Kind::TK_PLUSPLUS:   op = Operator::Kind::PLUSPLUS;   break;
2111
1.73k
        case Token::Kind::TK_MINUSMINUS: op = Operator::Kind::MINUSMINUS; break;
2112
420k
        default:                         return this->postfixExpression();
2113
468k
    }
2114
47.4k
    this->nextToken();
2115
47.4k
    if (!depth.increase()) {
2116
58
        return nullptr;
2117
58
    }
2118
47.3k
    std::unique_ptr<Expression> expr = this->unaryExpression();
2119
47.3k
    if (!expr) {
2120
3.05k
        return nullptr;
2121
3.05k
    }
2122
44.3k
    Position pos = Position::Range(start.fOffset, expr->position().endOffset());
2123
44.3k
    return this->expressionOrPoison(pos, PrefixExpression::Convert(fCompiler.context(),
2124
44.3k
                                                                   pos, op, std::move(expr)));
2125
47.3k
}
2126
2127
/* term suffix* */
2128
420k
std::unique_ptr<Expression> Parser::postfixExpression() {
2129
420k
    AutoDepth depth(this);
2130
420k
    std::unique_ptr<Expression> result = this->term();
2131
420k
    if (!result) {
2132
12.2k
        return nullptr;
2133
12.2k
    }
2134
546k
    for (;;) {
2135
546k
        Token t = this->peek();
2136
546k
        switch (t.fKind) {
2137
10.6k
            case Token::Kind::TK_FLOAT_LITERAL:
2138
10.6k
                if (this->text(t)[0] != '.') {
2139
544
                    return result;
2140
544
                }
2141
10.6k
                [[fallthrough]];
2142
45.1k
            case Token::Kind::TK_LBRACKET:
2143
81.8k
            case Token::Kind::TK_DOT:
2144
146k
            case Token::Kind::TK_LPAREN:
2145
148k
            case Token::Kind::TK_PLUSPLUS:
2146
149k
            case Token::Kind::TK_MINUSMINUS: {
2147
149k
                if (!depth.increase()) {
2148
71
                    return nullptr;
2149
71
                }
2150
149k
                result = this->suffix(std::move(result));
2151
149k
                if (!result) {
2152
11.0k
                    return nullptr;
2153
11.0k
                }
2154
138k
                break;
2155
149k
            }
2156
396k
            default:
2157
396k
                return result;
2158
546k
        }
2159
546k
    }
2160
408k
}
2161
2162
std::unique_ptr<Expression> Parser::swizzle(Position pos,
2163
                                            std::unique_ptr<Expression> base,
2164
                                            std::string_view swizzleMask,
2165
43.3k
                                            Position maskPos) {
2166
43.3k
    SkASSERT(!swizzleMask.empty());
2167
43.3k
    if (!base->type().isVector() && !base->type().isScalar()) {
2168
17.2k
        return this->expressionOrPoison(pos, FieldAccess::Convert(fCompiler.context(), pos,
2169
17.2k
                                                                  std::move(base), swizzleMask));
2170
2171
17.2k
    }
2172
26.0k
    return this->expressionOrPoison(pos, Swizzle::Convert(fCompiler.context(), pos, maskPos,
2173
26.0k
                                                          std::move(base), swizzleMask));
2174
43.3k
}
2175
2176
std::unique_ptr<Expression> Parser::call(Position pos,
2177
                                         std::unique_ptr<Expression> base,
2178
58.0k
                                         ExpressionArray args) {
2179
58.0k
    return this->expressionOrPoison(pos, SkSL::FunctionCall::Convert(fCompiler.context(), pos,
2180
58.0k
                                                                     std::move(base),
2181
58.0k
                                                                     std::move(args)));
2182
58.0k
}
2183
2184
/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN arguments RPAREN |
2185
   PLUSPLUS | MINUSMINUS | COLONCOLON IDENTIFIER | FLOAT_LITERAL [IDENTIFIER] */
2186
149k
std::unique_ptr<Expression> Parser::suffix(std::unique_ptr<Expression> base) {
2187
149k
    AutoDepth depth(this);
2188
149k
    Token next = this->nextToken();
2189
149k
    if (!depth.increase()) {
2190
158
        return nullptr;
2191
158
    }
2192
149k
    switch (next.fKind) {
2193
35.0k
        case Token::Kind::TK_LBRACKET: {
2194
35.0k
            if (this->checkNext(Token::Kind::TK_RBRACKET)) {
2195
738
                this->error(this->rangeFrom(next), "missing index in '[]'");
2196
738
                return this->poison(this->rangeFrom(base->position()));
2197
738
            }
2198
34.2k
            std::unique_ptr<Expression> index = this->expression();
2199
34.2k
            if (!index) {
2200
4.22k
                return nullptr;
2201
4.22k
            }
2202
30.0k
            this->expect(Token::Kind::TK_RBRACKET, "']' to complete array access expression");
2203
2204
30.0k
            Position pos = this->rangeFrom(base->position());
2205
30.0k
            return this->expressionOrPoison(pos, IndexExpression::Convert(fCompiler.context(), pos,
2206
30.0k
                                                                          std::move(base),
2207
30.0k
                                                                          std::move(index)));
2208
34.2k
        }
2209
36.6k
        case Token::Kind::TK_DOT: {
2210
36.6k
            std::string_view text;
2211
36.6k
            if (this->identifier(&text)) {
2212
24.0k
                Position pos = this->rangeFrom(base->position());
2213
24.0k
                return this->swizzle(pos, std::move(base), text,
2214
24.0k
                                     this->rangeFrom(this->position(next).after()));
2215
24.0k
            }
2216
36.6k
            [[fallthrough]];
2217
12.6k
        }
2218
22.6k
        case Token::Kind::TK_FLOAT_LITERAL: {
2219
            // Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
2220
            // floating point literals, possibly followed by an identifier. Handle that here.
2221
22.6k
            std::string_view field = this->text(next);
2222
22.6k
            SkASSERT(field[0] == '.');
2223
22.6k
            field.remove_prefix(1);
2224
            // use the next *raw* token so we don't ignore whitespace - we only care about
2225
            // identifiers that directly follow the float
2226
22.6k
            Position pos = this->rangeFrom(base->position());
2227
22.6k
            Position start = this->position(next);
2228
            // skip past the "."
2229
22.6k
            start = Position::Range(start.startOffset() + 1, start.endOffset());
2230
22.6k
            Position maskPos = this->rangeFrom(start);
2231
22.6k
            Token id = this->nextRawToken();
2232
22.6k
            if (id.fKind == Token::Kind::TK_IDENTIFIER) {
2233
17.2k
                pos = this->rangeFrom(base->position());
2234
17.2k
                maskPos = this->rangeFrom(start);
2235
17.2k
                return this->swizzle(pos,
2236
17.2k
                                     std::move(base),
2237
17.2k
                                     std::string(field) + std::string(this->text(id)),
2238
17.2k
                                     maskPos);
2239
17.2k
            }
2240
5.46k
            if (field.empty()) {
2241
3.43k
                this->error(pos, "expected field name or swizzle mask after '.'");
2242
3.43k
                return this->poison(pos);
2243
3.43k
            }
2244
2.03k
            this->pushback(id);
2245
2.03k
            return this->swizzle(pos, std::move(base), field, maskPos);
2246
5.46k
        }
2247
64.8k
        case Token::Kind::TK_LPAREN: {
2248
64.8k
            ExpressionArray args;
2249
64.8k
            if (this->peek().fKind != Token::Kind::TK_RPAREN) {
2250
83.0k
                for (;;) {
2251
83.0k
                    std::unique_ptr<Expression> expr = this->assignmentExpression();
2252
83.0k
                    if (!expr) {
2253
6.71k
                        return nullptr;
2254
6.71k
                    }
2255
76.3k
                    args.push_back(std::move(expr));
2256
76.3k
                    if (!this->checkNext(Token::Kind::TK_COMMA)) {
2257
55.3k
                        break;
2258
55.3k
                    }
2259
76.3k
                }
2260
62.0k
            }
2261
58.0k
            this->expect(Token::Kind::TK_RPAREN, "')' to complete function arguments");
2262
58.0k
            Position pos = this->rangeFrom(base->position());
2263
58.0k
            return this->call(pos, std::move(base), std::move(args));
2264
64.8k
        }
2265
1.22k
        case Token::Kind::TK_PLUSPLUS:
2266
2.86k
        case Token::Kind::TK_MINUSMINUS: {
2267
2.86k
            Operator::Kind op = (next.fKind == Token::Kind::TK_PLUSPLUS)
2268
2.86k
                                        ? Operator::Kind::PLUSPLUS
2269
2.86k
                                        : Operator::Kind::MINUSMINUS;
2270
2.86k
            Position pos = this->rangeFrom(base->position());
2271
2.86k
            return this->expressionOrPoison(pos, PostfixExpression::Convert(fCompiler.context(),
2272
2.86k
                                                                            pos, std::move(base),
2273
2.86k
                                                                            op));
2274
1.22k
        }
2275
0
        default: {
2276
0
            this->error(next, "expected expression suffix, but found '" +
2277
0
                              std::string(this->text(next)) + "'");
2278
0
            return nullptr;
2279
1.22k
        }
2280
149k
    }
2281
149k
}
SkSL::Parser::suffix(std::__1::unique_ptr<SkSL::Expression, std::__1::default_delete<SkSL::Expression> >)
Line
Count
Source
2186
149k
std::unique_ptr<Expression> Parser::suffix(std::unique_ptr<Expression> base) {
2187
149k
    AutoDepth depth(this);
2188
149k
    Token next = this->nextToken();
2189
149k
    if (!depth.increase()) {
2190
158
        return nullptr;
2191
158
    }
2192
149k
    switch (next.fKind) {
2193
35.0k
        case Token::Kind::TK_LBRACKET: {
2194
35.0k
            if (this->checkNext(Token::Kind::TK_RBRACKET)) {
2195
738
                this->error(this->rangeFrom(next), "missing index in '[]'");
2196
738
                return this->poison(this->rangeFrom(base->position()));
2197
738
            }
2198
34.2k
            std::unique_ptr<Expression> index = this->expression();
2199
34.2k
            if (!index) {
2200
4.22k
                return nullptr;
2201
4.22k
            }
2202
30.0k
            this->expect(Token::Kind::TK_RBRACKET, "']' to complete array access expression");
2203
2204
30.0k
            Position pos = this->rangeFrom(base->position());
2205
30.0k
            return this->expressionOrPoison(pos, IndexExpression::Convert(fCompiler.context(), pos,
2206
30.0k
                                                                          std::move(base),
2207
30.0k
                                                                          std::move(index)));
2208
34.2k
        }
2209
36.6k
        case Token::Kind::TK_DOT: {
2210
36.6k
            std::string_view text;
2211
36.6k
            if (this->identifier(&text)) {
2212
24.0k
                Position pos = this->rangeFrom(base->position());
2213
24.0k
                return this->swizzle(pos, std::move(base), text,
2214
24.0k
                                     this->rangeFrom(this->position(next).after()));
2215
24.0k
            }
2216
36.6k
            [[fallthrough]];
2217
12.6k
        }
2218
22.6k
        case Token::Kind::TK_FLOAT_LITERAL: {
2219
            // Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
2220
            // floating point literals, possibly followed by an identifier. Handle that here.
2221
22.6k
            std::string_view field = this->text(next);
2222
22.6k
            SkASSERT(field[0] == '.');
2223
22.6k
            field.remove_prefix(1);
2224
            // use the next *raw* token so we don't ignore whitespace - we only care about
2225
            // identifiers that directly follow the float
2226
22.6k
            Position pos = this->rangeFrom(base->position());
2227
22.6k
            Position start = this->position(next);
2228
            // skip past the "."
2229
22.6k
            start = Position::Range(start.startOffset() + 1, start.endOffset());
2230
22.6k
            Position maskPos = this->rangeFrom(start);
2231
22.6k
            Token id = this->nextRawToken();
2232
22.6k
            if (id.fKind == Token::Kind::TK_IDENTIFIER) {
2233
17.2k
                pos = this->rangeFrom(base->position());
2234
17.2k
                maskPos = this->rangeFrom(start);
2235
17.2k
                return this->swizzle(pos,
2236
17.2k
                                     std::move(base),
2237
17.2k
                                     std::string(field) + std::string(this->text(id)),
2238
17.2k
                                     maskPos);
2239
17.2k
            }
2240
5.46k
            if (field.empty()) {
2241
3.43k
                this->error(pos, "expected field name or swizzle mask after '.'");
2242
3.43k
                return this->poison(pos);
2243
3.43k
            }
2244
2.03k
            this->pushback(id);
2245
2.03k
            return this->swizzle(pos, std::move(base), field, maskPos);
2246
5.46k
        }
2247
64.8k
        case Token::Kind::TK_LPAREN: {
2248
64.8k
            ExpressionArray args;
2249
64.8k
            if (this->peek().fKind != Token::Kind::TK_RPAREN) {
2250
83.0k
                for (;;) {
2251
83.0k
                    std::unique_ptr<Expression> expr = this->assignmentExpression();
2252
83.0k
                    if (!expr) {
2253
6.71k
                        return nullptr;
2254
6.71k
                    }
2255
76.3k
                    args.push_back(std::move(expr));
2256
76.3k
                    if (!this->checkNext(Token::Kind::TK_COMMA)) {
2257
55.3k
                        break;
2258
55.3k
                    }
2259
76.3k
                }
2260
62.0k
            }
2261
58.0k
            this->expect(Token::Kind::TK_RPAREN, "')' to complete function arguments");
2262
58.0k
            Position pos = this->rangeFrom(base->position());
2263
58.0k
            return this->call(pos, std::move(base), std::move(args));
2264
64.8k
        }
2265
1.22k
        case Token::Kind::TK_PLUSPLUS:
2266
2.86k
        case Token::Kind::TK_MINUSMINUS: {
2267
2.86k
            Operator::Kind op = (next.fKind == Token::Kind::TK_PLUSPLUS)
2268
2.86k
                                        ? Operator::Kind::PLUSPLUS
2269
2.86k
                                        : Operator::Kind::MINUSMINUS;
2270
2.86k
            Position pos = this->rangeFrom(base->position());
2271
2.86k
            return this->expressionOrPoison(pos, PostfixExpression::Convert(fCompiler.context(),
2272
2.86k
                                                                            pos, std::move(base),
2273
2.86k
                                                                            op));
2274
1.22k
        }
2275
0
        default: {
2276
0
            this->error(next, "expected expression suffix, but found '" +
2277
0
                              std::string(this->text(next)) + "'");
2278
0
            return nullptr;
2279
1.22k
        }
2280
149k
    }
2281
149k
}
Unexecuted instantiation: SkSL::Parser::suffix(std::__1::unique_ptr<SkSL::Expression, std::__1::default_delete<SkSL::Expression> >)
2282
2283
/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */
2284
420k
std::unique_ptr<Expression> Parser::term() {
2285
420k
    AutoDepth depth(this);
2286
420k
    Token t = this->peek();
2287
420k
    switch (t.fKind) {
2288
169k
        case Token::Kind::TK_IDENTIFIER: {
2289
169k
            std::string_view text;
2290
169k
            if (this->identifier(&text)) {
2291
169k
                Position pos = this->position(t);
2292
169k
                return this->expressionOrPoison(
2293
169k
                        pos,
2294
169k
                        this->symbolTable()->instantiateSymbolRef(fCompiler.context(), text, pos));
2295
169k
            }
2296
0
            break;
2297
169k
        }
2298
160k
        case Token::Kind::TK_INT_LITERAL: {
2299
160k
            SKSL_INT i;
2300
160k
            if (!this->intLiteral(&i)) {
2301
1.27k
                i = 0;
2302
1.27k
            }
2303
160k
            Position pos = this->position(t);
2304
160k
            return this->expressionOrPoison(pos, SkSL::Literal::MakeInt(fCompiler.context(),
2305
160k
                                                                        pos, i));
2306
169k
        }
2307
19.9k
        case Token::Kind::TK_FLOAT_LITERAL: {
2308
19.9k
            SKSL_FLOAT f;
2309
19.9k
            if (!this->floatLiteral(&f)) {
2310
320
                f = 0.0f;
2311
320
            }
2312
19.9k
            Position pos = this->position(t);
2313
19.9k
            return this->expressionOrPoison(pos, SkSL::Literal::MakeFloat(fCompiler.context(),
2314
19.9k
                                                                          pos, f));
2315
169k
        }
2316
187
        case Token::Kind::TK_TRUE_LITERAL: // fall through
2317
190
        case Token::Kind::TK_FALSE_LITERAL: {
2318
190
            bool b;
2319
190
            SkAssertResult(this->boolLiteral(&b));
2320
190
            Position pos = this->position(t);
2321
190
            return this->expressionOrPoison(pos, SkSL::Literal::MakeBool(fCompiler.context(),
2322
190
                                                                         pos, b));
2323
187
        }
2324
67.6k
        case Token::Kind::TK_LPAREN: {
2325
67.6k
            this->nextToken();
2326
67.6k
            if (!depth.increase()) {
2327
90
                return nullptr;
2328
90
            }
2329
67.6k
            std::unique_ptr<Expression> result = this->expression();
2330
67.6k
            if (result != nullptr) {
2331
57.8k
                this->expect(Token::Kind::TK_RPAREN, "')' to complete expression");
2332
57.8k
                result->setPosition(this->rangeFrom(this->position(t)));
2333
57.8k
                return result;
2334
57.8k
            }
2335
9.78k
            break;
2336
67.6k
        }
2337
9.78k
        default:
2338
2.34k
            this->nextToken();
2339
2.34k
            this->error(t, "expected expression, but found '" + std::string(this->text(t)) + "'");
2340
2.34k
            fEncounteredFatalError = true;
2341
2.34k
            break;
2342
420k
    }
2343
12.1k
    return nullptr;
2344
420k
}
SkSL::Parser::term()
Line
Count
Source
2284
420k
std::unique_ptr<Expression> Parser::term() {
2285
420k
    AutoDepth depth(this);
2286
420k
    Token t = this->peek();
2287
420k
    switch (t.fKind) {
2288
169k
        case Token::Kind::TK_IDENTIFIER: {
2289
169k
            std::string_view text;
2290
169k
            if (this->identifier(&text)) {
2291
169k
                Position pos = this->position(t);
2292
169k
                return this->expressionOrPoison(
2293
169k
                        pos,
2294
169k
                        this->symbolTable()->instantiateSymbolRef(fCompiler.context(), text, pos));
2295
169k
            }
2296
0
            break;
2297
169k
        }
2298
160k
        case Token::Kind::TK_INT_LITERAL: {
2299
160k
            SKSL_INT i;
2300
160k
            if (!this->intLiteral(&i)) {
2301
1.27k
                i = 0;
2302
1.27k
            }
2303
160k
            Position pos = this->position(t);
2304
160k
            return this->expressionOrPoison(pos, SkSL::Literal::MakeInt(fCompiler.context(),
2305
160k
                                                                        pos, i));
2306
169k
        }
2307
19.9k
        case Token::Kind::TK_FLOAT_LITERAL: {
2308
19.9k
            SKSL_FLOAT f;
2309
19.9k
            if (!this->floatLiteral(&f)) {
2310
320
                f = 0.0f;
2311
320
            }
2312
19.9k
            Position pos = this->position(t);
2313
19.9k
            return this->expressionOrPoison(pos, SkSL::Literal::MakeFloat(fCompiler.context(),
2314
19.9k
                                                                          pos, f));
2315
169k
        }
2316
187
        case Token::Kind::TK_TRUE_LITERAL: // fall through
2317
190
        case Token::Kind::TK_FALSE_LITERAL: {
2318
190
            bool b;
2319
190
            SkAssertResult(this->boolLiteral(&b));
2320
190
            Position pos = this->position(t);
2321
190
            return this->expressionOrPoison(pos, SkSL::Literal::MakeBool(fCompiler.context(),
2322
190
                                                                         pos, b));
2323
187
        }
2324
67.6k
        case Token::Kind::TK_LPAREN: {
2325
67.6k
            this->nextToken();
2326
67.6k
            if (!depth.increase()) {
2327
90
                return nullptr;
2328
90
            }
2329
67.6k
            std::unique_ptr<Expression> result = this->expression();
2330
67.6k
            if (result != nullptr) {
2331
57.8k
                this->expect(Token::Kind::TK_RPAREN, "')' to complete expression");
2332
57.8k
                result->setPosition(this->rangeFrom(this->position(t)));
2333
57.8k
                return result;
2334
57.8k
            }
2335
9.78k
            break;
2336
67.6k
        }
2337
9.78k
        default:
2338
2.34k
            this->nextToken();
2339
2.34k
            this->error(t, "expected expression, but found '" + std::string(this->text(t)) + "'");
2340
2.34k
            fEncounteredFatalError = true;
2341
2.34k
            break;
2342
420k
    }
2343
12.1k
    return nullptr;
2344
420k
}
Unexecuted instantiation: SkSL::Parser::term()
2345
2346
/* INT_LITERAL */
2347
160k
bool Parser::intLiteral(SKSL_INT* dest) {
2348
160k
    Token t;
2349
160k
    if (!this->expect(Token::Kind::TK_INT_LITERAL, "integer literal", &t)) {
2350
2
        return false;
2351
2
    }
2352
160k
    std::string_view s = this->text(t);
2353
160k
    if (!SkSL::stoi(s, dest)) {
2354
1.27k
        this->error(t, "integer is too large: " + std::string(s));
2355
1.27k
        return false;
2356
1.27k
    }
2357
159k
    return true;
2358
160k
}
2359
2360
/* FLOAT_LITERAL */
2361
19.9k
bool Parser::floatLiteral(SKSL_FLOAT* dest) {
2362
19.9k
    Token t;
2363
19.9k
    if (!this->expect(Token::Kind::TK_FLOAT_LITERAL, "float literal", &t)) {
2364
0
        return false;
2365
0
    }
2366
19.9k
    std::string_view s = this->text(t);
2367
19.9k
    if (!SkSL::stod(s, dest)) {
2368
320
        this->error(t, "floating-point value is too large: " + std::string(s));
2369
320
        return false;
2370
320
    }
2371
19.6k
    return true;
2372
19.9k
}
2373
2374
/* TRUE_LITERAL | FALSE_LITERAL */
2375
190
bool Parser::boolLiteral(bool* dest) {
2376
190
    Token t = this->nextToken();
2377
190
    switch (t.fKind) {
2378
187
        case Token::Kind::TK_TRUE_LITERAL:
2379
187
            *dest = true;
2380
187
            return true;
2381
3
        case Token::Kind::TK_FALSE_LITERAL:
2382
3
            *dest = false;
2383
3
            return true;
2384
0
        default:
2385
0
            this->error(t, "expected 'true' or 'false', but found '" +
2386
0
                           std::string(this->text(t)) + "'");
2387
0
            return false;
2388
190
    }
2389
190
}
2390
2391
/* IDENTIFIER */
2392
206k
bool Parser::identifier(std::string_view* dest) {
2393
206k
    Token t;
2394
206k
    if (this->expect(Token::Kind::TK_IDENTIFIER, "identifier", &t)) {
2395
193k
        *dest = this->text(t);
2396
193k
        return true;
2397
193k
    }
2398
12.6k
    return false;
2399
206k
}
2400
2401
}  // namespace SkSL