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