• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifdef SKSL_EXT
1100             {"constant_id",                 SkSL::LayoutFlag::kConstantId},
1101 #endif
1102     });
1103 
1104     Layout result;
1105     if (this->checkNext(Token::Kind::TK_LAYOUT) &&
1106         this->expect(Token::Kind::TK_LPAREN, "'('")) {
1107 
1108         for (;;) {
1109             Token t = this->nextToken();
1110             std::string_view text = this->text(t);
1111             SkSL::LayoutFlag* found = sLayoutTokens->find(text);
1112 
1113             if (!found) {
1114                 this->error(t, "'" + std::string(text) + "' is not a valid layout qualifier");
1115             } else {
1116                 if (result.fFlags & *found) {
1117                     this->error(t, "layout qualifier '" + std::string(text) +
1118                                    "' appears more than once");
1119                 }
1120 
1121                 result.fFlags |= *found;
1122 
1123                 switch (*found) {
1124                     case SkSL::LayoutFlag::kLocation:
1125                         result.fLocation = this->layoutInt();
1126                         break;
1127                     case SkSL::LayoutFlag::kOffset:
1128                         result.fOffset = this->layoutInt();
1129                         break;
1130                     case SkSL::LayoutFlag::kBinding:
1131                         result.fBinding = this->layoutInt();
1132                         break;
1133                     case SkSL::LayoutFlag::kIndex:
1134                         result.fIndex = this->layoutInt();
1135                         break;
1136                     case SkSL::LayoutFlag::kSet:
1137                         result.fSet = this->layoutInt();
1138                         break;
1139                     case SkSL::LayoutFlag::kTexture:
1140                         result.fTexture = this->layoutInt();
1141                         break;
1142                     case SkSL::LayoutFlag::kSampler:
1143                         result.fSampler = this->layoutInt();
1144                         break;
1145                     case SkSL::LayoutFlag::kBuiltin:
1146                         result.fBuiltin = this->layoutInt();
1147                         break;
1148                     case SkSL::LayoutFlag::kInputAttachmentIndex:
1149                         result.fInputAttachmentIndex = this->layoutInt();
1150                         break;
1151                     case SkSL::LayoutFlag::kLocalSizeX:
1152                         result.fLocalSizeX = this->layoutInt();
1153                         break;
1154                     case SkSL::LayoutFlag::kLocalSizeY:
1155                         result.fLocalSizeY = this->layoutInt();
1156                         break;
1157                     case SkSL::LayoutFlag::kLocalSizeZ:
1158                         result.fLocalSizeZ = this->layoutInt();
1159                         break;
1160 #ifdef SKSL_EXT
1161                     case SkSL::LayoutFlag::kConstantId:
1162                         result.fConstantId = this->layoutInt();
1163                         break;
1164 #endif
1165                     default:
1166                         break;
1167                 }
1168             }
1169             if (this->checkNext(Token::Kind::TK_RPAREN)) {
1170                 break;
1171             }
1172             if (!this->expect(Token::Kind::TK_COMMA, "','")) {
1173                 break;
1174             }
1175         }
1176     }
1177     return result;
1178 }
1179 
1180 /* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE |
1181             VARYING | INLINE | WORKGROUP | READONLY | WRITEONLY | BUFFER)* */
modifiers()1182 Modifiers Parser::modifiers() {
1183     int start = this->peek().fOffset;
1184     SkSL::Layout layout = this->layout();
1185     Token raw = this->nextRawToken();
1186     int end = raw.fOffset;
1187     if (!is_whitespace(raw.fKind)) {
1188         this->pushback(raw);
1189     }
1190     ModifierFlags flags = ModifierFlag::kNone;
1191     for (;;) {
1192         ModifierFlags tokenFlag = parse_modifier_token(peek().fKind);
1193         if (tokenFlag == ModifierFlag::kNone) {
1194             break;
1195         }
1196         Token modifier = this->nextToken();
1197         if (ModifierFlags duplicateFlags = (tokenFlag & flags)) {
1198             this->error(modifier, "'" + duplicateFlags.description() + "' appears more than once");
1199         }
1200         flags |= tokenFlag;
1201         end = this->position(modifier).endOffset();
1202     }
1203     return Modifiers{Position::Range(start, end), layout, flags};
1204 }
1205 
statementOrNop(Position pos,std::unique_ptr<Statement> stmt)1206 std::unique_ptr<Statement> Parser::statementOrNop(Position pos, std::unique_ptr<Statement> stmt) {
1207     if (!stmt) {
1208         stmt = Nop::Make();
1209     }
1210     if (pos.valid() && !stmt->position().valid()) {
1211         stmt->setPosition(pos);
1212     }
1213     return stmt;
1214 }
1215 
1216 /* ifStatement | forStatement | doStatement | whileStatement | block | expression */
statement(bool bracesIntroduceNewScope)1217 std::unique_ptr<Statement> Parser::statement(bool bracesIntroduceNewScope) {
1218     AutoDepth depth(this);
1219     if (!depth.increase()) {
1220         return nullptr;
1221     }
1222     switch (this->peek().fKind) {
1223         case Token::Kind::TK_IF:
1224             return this->ifStatement();
1225         case Token::Kind::TK_FOR:
1226             return this->forStatement();
1227         case Token::Kind::TK_DO:
1228             return this->doStatement();
1229         case Token::Kind::TK_WHILE:
1230             return this->whileStatement();
1231         case Token::Kind::TK_SWITCH:
1232             return this->switchStatement();
1233         case Token::Kind::TK_RETURN:
1234             return this->returnStatement();
1235         case Token::Kind::TK_BREAK:
1236             return this->breakStatement();
1237         case Token::Kind::TK_CONTINUE:
1238             return this->continueStatement();
1239         case Token::Kind::TK_DISCARD:
1240             return this->discardStatement();
1241         case Token::Kind::TK_LBRACE:
1242             return this->block(bracesIntroduceNewScope, /*adoptExistingSymbolTable=*/nullptr);
1243         case Token::Kind::TK_SEMICOLON:
1244             this->nextToken();
1245             return Nop::Make();
1246         case Token::Kind::TK_CONST:
1247             return this->varDeclarations();
1248         case Token::Kind::TK_HIGHP:
1249         case Token::Kind::TK_MEDIUMP:
1250         case Token::Kind::TK_LOWP:
1251         case Token::Kind::TK_IDENTIFIER:
1252             return this->varDeclarationsOrExpressionStatement();
1253         default:
1254             return this->expressionStatement();
1255     }
1256 }
1257 
findType(Position pos,Modifiers * modifiers,std::string_view name)1258 const Type* Parser::findType(Position pos,
1259                              Modifiers* modifiers,
1260                              std::string_view name) {
1261     const Context& context = fCompiler.context();
1262     const Symbol* symbol = this->symbolTable()->find(name);
1263     if (!symbol) {
1264         this->error(pos, "no symbol named '" + std::string(name) + "'");
1265         return context.fTypes.fPoison.get();
1266     }
1267     if (!symbol->is<Type>()) {
1268         this->error(pos, "symbol '" + std::string(name) + "' is not a type");
1269         return context.fTypes.fPoison.get();
1270     }
1271     const SkSL::Type* type = &symbol->as<Type>();
1272     if (!context.fConfig->isBuiltinCode()) {
1273         if (!TypeReference::VerifyType(context, type, pos)) {
1274             return context.fTypes.fPoison.get();
1275         }
1276     }
1277     Position qualifierRange = modifiers->fPosition;
1278     if (qualifierRange.startOffset() == qualifierRange.endOffset()) {
1279         qualifierRange = this->rangeFrom(qualifierRange);
1280     }
1281     return modifiers ? type->applyQualifiers(context, &modifiers->fFlags, qualifierRange)
1282                      : type;
1283 }
1284 
1285 /* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* QUESTION? */
type(Modifiers * modifiers)1286 const Type* Parser::type(Modifiers* modifiers) {
1287     Token type;
1288     if (!this->expect(Token::Kind::TK_IDENTIFIER, "a type", &type)) {
1289         return nullptr;
1290     }
1291     if (!this->symbolTable()->isType(this->text(type))) {
1292         this->error(type, "no type named '" + std::string(this->text(type)) + "'");
1293         return fCompiler.context().fTypes.fInvalid.get();
1294     }
1295     const Type* result = this->findType(this->position(type), modifiers, this->text(type));
1296     if (result->isInterfaceBlock()) {
1297         // SkSL puts interface blocks into the symbol table, but they aren't general-purpose types;
1298         // you can't use them to declare a variable type or a function return type.
1299         this->error(type, "expected a type, found '" + std::string(this->text(type)) + "'");
1300         return fCompiler.context().fTypes.fInvalid.get();
1301     }
1302     Token bracket;
1303     while (this->checkNext(Token::Kind::TK_LBRACKET, &bracket)) {
1304         if (this->checkNext(Token::Kind::TK_RBRACKET)) {
1305             if (this->allowUnsizedArrays()) {
1306                 result = this->unsizedArrayType(result, this->rangeFrom(type));
1307             } else {
1308                 this->error(this->rangeFrom(bracket), "unsized arrays are not permitted here");
1309             }
1310         } else {
1311             SKSL_INT size;
1312             if (!this->arraySize(&size)) {
1313                 return nullptr;
1314             }
1315             this->expect(Token::Kind::TK_RBRACKET, "']'");
1316             result = this->arrayType(result, size, this->rangeFrom(type));
1317         }
1318     }
1319     return result;
1320 }
1321 
1322 /* IDENTIFIER LBRACE
1323      varDeclaration+
1324    RBRACE (IDENTIFIER (LBRACKET expression RBRACKET)*)? SEMICOLON */
interfaceBlock(const Modifiers & modifiers)1325 bool Parser::interfaceBlock(const Modifiers& modifiers) {
1326     Token typeName;
1327     if (!this->expectIdentifier(&typeName)) {
1328         return false;
1329     }
1330     if (this->peek().fKind != Token::Kind::TK_LBRACE) {
1331         // we only get into interfaceBlock if we found a top-level identifier which was not a type.
1332         // 99% of the time, the user was not actually intending to create an interface block, so
1333         // it's better to report it as an unknown type
1334         this->error(typeName, "no type named '" + std::string(this->text(typeName)) + "'");
1335         return false;
1336     }
1337     this->nextToken();
1338     TArray<SkSL::Field> fields;
1339     while (!this->checkNext(Token::Kind::TK_RBRACE)) {
1340         Position fieldPos = this->position(this->peek());
1341         Modifiers fieldModifiers = this->modifiers();
1342         const Type* type = this->type(&fieldModifiers);
1343         if (!type) {
1344             return false;
1345         }
1346         do {
1347             Token fieldName;
1348             if (!this->expectIdentifier(&fieldName)) {
1349                 return false;
1350             }
1351             const Type* actualType = type;
1352             if (this->checkNext(Token::Kind::TK_LBRACKET)) {
1353                 Token sizeToken = this->peek();
1354                 if (sizeToken.fKind != Token::Kind::TK_RBRACKET) {
1355                     SKSL_INT size;
1356                     if (!this->arraySize(&size)) {
1357                         return false;
1358                     }
1359                     actualType = this->arrayType(actualType, size, this->position(typeName));
1360                 } else if (this->allowUnsizedArrays()) {
1361                     actualType = this->unsizedArrayType(actualType, this->position(typeName));
1362                 } else {
1363                     this->error(sizeToken, "unsized arrays are not permitted here");
1364                 }
1365                 this->expect(Token::Kind::TK_RBRACKET, "']'");
1366             }
1367             if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1368                 return false;
1369             }
1370 
1371             fields.push_back(SkSL::Field(this->rangeFrom(fieldPos),
1372                                          fieldModifiers.fLayout,
1373                                          fieldModifiers.fFlags,
1374                                          this->text(fieldName),
1375                                          actualType));
1376         } while (this->checkNext(Token::Kind::TK_COMMA));
1377     }
1378     std::string_view instanceName;
1379     Token instanceNameToken;
1380     SKSL_INT size = 0;
1381     if (this->checkIdentifier(&instanceNameToken)) {
1382         instanceName = this->text(instanceNameToken);
1383         if (this->checkNext(Token::Kind::TK_LBRACKET)) {
1384             if (!this->arraySize(&size)) {
1385                 return false;
1386             }
1387             this->expect(Token::Kind::TK_RBRACKET, "']'");
1388         }
1389     }
1390     this->expect(Token::Kind::TK_SEMICOLON, "';'");
1391 
1392     if (std::unique_ptr<SkSL::InterfaceBlock> ib = InterfaceBlock::Convert(fCompiler.context(),
1393                                                                            this->position(typeName),
1394                                                                            modifiers,
1395                                                                            this->text(typeName),
1396                                                                            std::move(fields),
1397                                                                            instanceName,
1398                                                                            size)) {
1399         fProgramElements.push_back(std::move(ib));
1400         return true;
1401     }
1402     return false;
1403 }
1404 
1405 /* IF LPAREN expression RPAREN statement (ELSE statement)? */
ifStatement()1406 std::unique_ptr<Statement> Parser::ifStatement() {
1407     Token start;
1408     if (!this->expect(Token::Kind::TK_IF, "'if'", &start)) {
1409         return nullptr;
1410     }
1411     if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1412         return nullptr;
1413     }
1414     std::unique_ptr<Expression> test = this->expression();
1415     if (!test) {
1416         return nullptr;
1417     }
1418     if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1419         return nullptr;
1420     }
1421     std::unique_ptr<Statement> ifTrue = this->statement();
1422     if (!ifTrue) {
1423         return nullptr;
1424     }
1425     std::unique_ptr<Statement> ifFalse;
1426     if (this->checkNext(Token::Kind::TK_ELSE)) {
1427         ifFalse = this->statement();
1428         if (!ifFalse) {
1429             return nullptr;
1430         }
1431     }
1432     Position pos = this->rangeFrom(start);
1433     return this->statementOrNop(pos, IfStatement::Convert(fCompiler.context(),
1434                                                           pos,
1435                                                           std::move(test),
1436                                                           std::move(ifTrue),
1437                                                           std::move(ifFalse)));
1438 }
1439 
1440 /* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
doStatement()1441 std::unique_ptr<Statement> Parser::doStatement() {
1442     Token start;
1443     if (!this->expect(Token::Kind::TK_DO, "'do'", &start)) {
1444         return nullptr;
1445     }
1446     std::unique_ptr<Statement> statement = this->statement();
1447     if (!statement) {
1448         return nullptr;
1449     }
1450     if (!this->expect(Token::Kind::TK_WHILE, "'while'")) {
1451         return nullptr;
1452     }
1453     if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1454         return nullptr;
1455     }
1456     std::unique_ptr<Expression> test = this->expression();
1457     if (!test) {
1458         return nullptr;
1459     }
1460     if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1461         return nullptr;
1462     }
1463     if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1464         return nullptr;
1465     }
1466     Position pos = this->rangeFrom(start);
1467     return this->statementOrNop(pos, DoStatement::Convert(fCompiler.context(), pos,
1468                                                           std::move(statement), std::move(test)));
1469 }
1470 
1471 /* WHILE LPAREN expression RPAREN STATEMENT */
whileStatement()1472 std::unique_ptr<Statement> Parser::whileStatement() {
1473     Token start;
1474     if (!this->expect(Token::Kind::TK_WHILE, "'while'", &start)) {
1475         return nullptr;
1476     }
1477     if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1478         return nullptr;
1479     }
1480     std::unique_ptr<Expression> test = this->expression();
1481     if (!test) {
1482         return nullptr;
1483     }
1484     if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1485         return nullptr;
1486     }
1487     std::unique_ptr<Statement> statement = this->statement();
1488     if (!statement) {
1489         return nullptr;
1490     }
1491     Position pos = this->rangeFrom(start);
1492     return this->statementOrNop(pos, ForStatement::ConvertWhile(fCompiler.context(), pos,
1493                                                                 std::move(test),
1494                                                                 std::move(statement)));
1495 }
1496 
1497 /* COLON statement* */
switchCaseBody(ExpressionArray * values,StatementArray * caseBlocks,std::unique_ptr<Expression> caseValue)1498 bool Parser::switchCaseBody(ExpressionArray* values,
1499                             StatementArray* caseBlocks,
1500                             std::unique_ptr<Expression> caseValue) {
1501     if (!this->expect(Token::Kind::TK_COLON, "':'")) {
1502         return false;
1503     }
1504     StatementArray statements;
1505     while (this->peek().fKind != Token::Kind::TK_RBRACE &&
1506            this->peek().fKind != Token::Kind::TK_CASE &&
1507            this->peek().fKind != Token::Kind::TK_DEFAULT) {
1508         std::unique_ptr<Statement> s = this->statement();
1509         if (!s) {
1510             return false;
1511         }
1512         statements.push_back(std::move(s));
1513     }
1514     values->push_back(std::move(caseValue));
1515     caseBlocks->push_back(SkSL::Block::Make(Position(), std::move(statements),
1516                                             Block::Kind::kUnbracedBlock));
1517     return true;
1518 }
1519 
1520 /* CASE expression COLON statement* */
switchCase(ExpressionArray * values,StatementArray * caseBlocks)1521 bool Parser::switchCase(ExpressionArray* values, StatementArray* caseBlocks) {
1522     Token start;
1523     if (!this->expect(Token::Kind::TK_CASE, "'case'", &start)) {
1524         return false;
1525     }
1526     std::unique_ptr<Expression> caseValue = this->expression();
1527     if (!caseValue) {
1528         return false;
1529     }
1530     return this->switchCaseBody(values, caseBlocks, std::move(caseValue));
1531 }
1532 
1533 /* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
switchStatement()1534 std::unique_ptr<Statement> Parser::switchStatement() {
1535     Token start;
1536     if (!this->expect(Token::Kind::TK_SWITCH, "'switch'", &start)) {
1537         return nullptr;
1538     }
1539     if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1540         return nullptr;
1541     }
1542     std::unique_ptr<Expression> value = this->expression();
1543     if (!value) {
1544         return nullptr;
1545     }
1546     if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1547         return nullptr;
1548     }
1549     if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
1550         return nullptr;
1551     }
1552 
1553     std::unique_ptr<SymbolTable> symbolTable;
1554     ExpressionArray values;
1555     StatementArray caseBlocks;
1556     {
1557         // Keeping a tight scope around AutoSymbolTable is important here. SwitchStatement::Convert
1558         // may end up creating a new symbol table if the HoistSwitchVarDeclarationsAtTopLevel
1559         // transform is used. We want ~AutoSymbolTable to happen first, so it can restore the
1560         // context's active symbol table to the enclosing block instead of the switch's inner block.
1561         AutoSymbolTable symbols(this, &symbolTable);
1562 
1563         while (this->peek().fKind == Token::Kind::TK_CASE) {
1564             if (!this->switchCase(&values, &caseBlocks)) {
1565                 return nullptr;
1566             }
1567         }
1568         // Requiring `default:` to be last (in defiance of C and GLSL) was a deliberate decision.
1569         // Other parts of the compiler are allowed to rely upon this assumption.
1570         if (this->checkNext(Token::Kind::TK_DEFAULT)) {
1571             if (!this->switchCaseBody(&values, &caseBlocks, /*value=*/nullptr)) {
1572                 return nullptr;
1573             }
1574         }
1575         if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
1576             return nullptr;
1577         }
1578     }
1579 
1580     Position pos = this->rangeFrom(start);
1581     return this->statementOrNop(pos, SwitchStatement::Convert(fCompiler.context(), pos,
1582                                                               std::move(value),
1583                                                               std::move(values),
1584                                                               std::move(caseBlocks),
1585                                                               std::move(symbolTable)));
1586 }
1587 
range_of_at_least_one_char(int start,int end)1588 static Position range_of_at_least_one_char(int start, int end) {
1589     return Position::Range(start, std::max(end, start + 1));
1590 }
1591 
1592 /* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
1593    STATEMENT */
forStatement()1594 std::unique_ptr<Statement> Parser::forStatement() {
1595     Token start;
1596     if (!this->expect(Token::Kind::TK_FOR, "'for'", &start)) {
1597         return nullptr;
1598     }
1599     Token lparen;
1600     if (!this->expect(Token::Kind::TK_LPAREN, "'('", &lparen)) {
1601         return nullptr;
1602     }
1603     std::unique_ptr<SymbolTable> symbolTable;
1604     std::unique_ptr<Statement> initializer;
1605     std::unique_ptr<Expression> test;
1606     std::unique_ptr<Expression> next;
1607     std::unique_ptr<Statement> statement;
1608     int firstSemicolonOffset;
1609     Token secondSemicolon;
1610     Token rparen;
1611     {
1612         AutoSymbolTable symbols(this, &symbolTable);
1613 
1614         Token nextToken = this->peek();
1615         if (nextToken.fKind == Token::Kind::TK_SEMICOLON) {
1616             // An empty init-statement.
1617             firstSemicolonOffset = this->nextToken().fOffset;
1618         } else {
1619             // The init-statement must be an expression or variable declaration.
1620             initializer = this->varDeclarationsOrExpressionStatement();
1621             if (!initializer) {
1622                 return nullptr;
1623             }
1624             firstSemicolonOffset = fLexer.getCheckpoint().fOffset - 1;
1625         }
1626         if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
1627             test = this->expression();
1628             if (!test) {
1629                 return nullptr;
1630             }
1631         }
1632         if (!this->expect(Token::Kind::TK_SEMICOLON, "';'", &secondSemicolon)) {
1633             return nullptr;
1634         }
1635         if (this->peek().fKind != Token::Kind::TK_RPAREN) {
1636             next = this->expression();
1637             if (!next) {
1638                 return nullptr;
1639             }
1640         }
1641         if (!this->expect(Token::Kind::TK_RPAREN, "')'", &rparen)) {
1642             return nullptr;
1643         }
1644         statement = this->statement(/*bracesIntroduceNewScope=*/false);
1645         if (!statement) {
1646             return nullptr;
1647         }
1648     }
1649     Position pos = this->rangeFrom(start);
1650     ForLoopPositions loopPositions{
1651             range_of_at_least_one_char(lparen.fOffset + 1, firstSemicolonOffset),
1652             range_of_at_least_one_char(firstSemicolonOffset + 1, secondSemicolon.fOffset),
1653             range_of_at_least_one_char(secondSemicolon.fOffset + 1, rparen.fOffset),
1654     };
1655     return this->statementOrNop(pos, ForStatement::Convert(fCompiler.context(), pos, loopPositions,
1656                                                            std::move(initializer),
1657                                                            std::move(test),
1658                                                            std::move(next),
1659                                                            std::move(statement),
1660                                                            std::move(symbolTable)));
1661 }
1662 
1663 /* RETURN expression? SEMICOLON */
returnStatement()1664 std::unique_ptr<Statement> Parser::returnStatement() {
1665     Token start;
1666     if (!this->expect(Token::Kind::TK_RETURN, "'return'", &start)) {
1667         return nullptr;
1668     }
1669     std::unique_ptr<Expression> expression;
1670     if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
1671         expression = this->expression();
1672         if (!expression) {
1673             return nullptr;
1674         }
1675     }
1676     if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1677         return nullptr;
1678     }
1679     // We do not check for errors, or coerce the value to the correct type, until the return
1680     // statement is actually added to a function. (This is done in FunctionDefinition::Convert.)
1681     return ReturnStatement::Make(this->rangeFrom(start), std::move(expression));
1682 }
1683 
1684 /* BREAK SEMICOLON */
breakStatement()1685 std::unique_ptr<Statement> Parser::breakStatement() {
1686     Token start;
1687     if (!this->expect(Token::Kind::TK_BREAK, "'break'", &start)) {
1688         return nullptr;
1689     }
1690     if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1691         return nullptr;
1692     }
1693     return SkSL::BreakStatement::Make(this->position(start));
1694 }
1695 
1696 /* CONTINUE SEMICOLON */
continueStatement()1697 std::unique_ptr<Statement> Parser::continueStatement() {
1698     Token start;
1699     if (!this->expect(Token::Kind::TK_CONTINUE, "'continue'", &start)) {
1700         return nullptr;
1701     }
1702     if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1703         return nullptr;
1704     }
1705     return SkSL::ContinueStatement::Make(this->position(start));
1706 }
1707 
1708 /* DISCARD SEMICOLON */
discardStatement()1709 std::unique_ptr<Statement> Parser::discardStatement() {
1710     Token start;
1711     if (!this->expect(Token::Kind::TK_DISCARD, "'continue'", &start)) {
1712         return nullptr;
1713     }
1714     if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1715         return nullptr;
1716     }
1717     Position pos = this->position(start);
1718     return this->statementOrNop(pos, SkSL::DiscardStatement::Convert(fCompiler.context(), pos));
1719 }
1720 
1721 /* LBRACE statement* RBRACE */
block(bool introduceNewScope,std::unique_ptr<SymbolTable> * adoptExistingSymbolTable)1722 std::unique_ptr<Statement> Parser::block(bool introduceNewScope,
1723                                          std::unique_ptr<SymbolTable>* adoptExistingSymbolTable) {
1724     // We can't introduce a new scope _and_ adopt an existing symbol table.
1725     SkASSERT(!(introduceNewScope && adoptExistingSymbolTable));
1726 
1727     AutoDepth depth(this);
1728     Token start;
1729     if (!this->expect(Token::Kind::TK_LBRACE, "'{'", &start)) {
1730         return nullptr;
1731     }
1732     if (!depth.increase()) {
1733         return nullptr;
1734     }
1735 
1736     std::unique_ptr<SymbolTable> newSymbolTable;
1737     std::unique_ptr<SymbolTable>* symbolTableToUse =
1738             adoptExistingSymbolTable ? adoptExistingSymbolTable : &newSymbolTable;
1739 
1740     StatementArray statements;
1741     {
1742         AutoSymbolTable symbols(this, symbolTableToUse, /*enable=*/introduceNewScope);
1743 
1744         // Consume statements until we reach the closing brace.
1745         for (;;) {
1746             Token::Kind tokenKind = this->peek().fKind;
1747             if (tokenKind == Token::Kind::TK_RBRACE) {
1748                 this->nextToken();
1749                 break;
1750             }
1751             if (tokenKind == Token::Kind::TK_END_OF_FILE) {
1752                 this->error(this->peek(), "expected '}', but found end of file");
1753                 return nullptr;
1754             }
1755             if (std::unique_ptr<Statement> statement = this->statement()) {
1756                 statements.push_back(std::move(statement));
1757             }
1758             if (fEncounteredFatalError) {
1759                 return nullptr;
1760             }
1761         }
1762     }
1763     return SkSL::Block::MakeBlock(this->rangeFrom(start),
1764                                   std::move(statements),
1765                                   Block::Kind::kBracedScope,
1766                                   std::move(*symbolTableToUse));
1767 }
1768 
1769 /* expression SEMICOLON */
expressionStatement()1770 std::unique_ptr<Statement> Parser::expressionStatement() {
1771     std::unique_ptr<Expression> expr = this->expression();
1772     if (!expr) {
1773         return nullptr;
1774     }
1775     if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1776         return nullptr;
1777     }
1778     Position pos = expr->position();
1779     return this->statementOrNop(pos, SkSL::ExpressionStatement::Convert(fCompiler.context(),
1780                                                                         std::move(expr)));
1781 }
1782 
poison(Position pos)1783 std::unique_ptr<Expression> Parser::poison(Position pos) {
1784     return Poison::Make(pos, fCompiler.context());
1785 }
1786 
expressionOrPoison(Position pos,std::unique_ptr<Expression> expr)1787 std::unique_ptr<Expression> Parser::expressionOrPoison(Position pos,
1788                                                        std::unique_ptr<Expression> expr) {
1789     if (!expr) {
1790         // If no expression was passed in, create a poison expression.
1791         expr = this->poison(pos);
1792     }
1793     // If a valid position was passed in, it must match the expression's position.
1794     SkASSERTF(!pos.valid() || expr->position() == pos,
1795               "expected expression position (%d-%d), but received (%d-%d)",
1796               pos.startOffset(),
1797               pos.endOffset(),
1798               expr->position().startOffset(),
1799               expr->position().endOffset());
1800     return expr;
1801 }
1802 
operatorRight(Parser::AutoDepth & depth,Operator::Kind op,BinaryParseFn rightFn,std::unique_ptr<Expression> & expr)1803 bool Parser::operatorRight(Parser::AutoDepth& depth,
1804                            Operator::Kind op,
1805                            BinaryParseFn rightFn,
1806                            std::unique_ptr<Expression>& expr) {
1807     this->nextToken();
1808     if (!depth.increase()) {
1809         return false;
1810     }
1811     std::unique_ptr<Expression> right = (this->*rightFn)();
1812     if (!right) {
1813         return false;
1814     }
1815     Position pos = expr->position().rangeThrough(right->position());
1816     expr = this->expressionOrPoison(pos, BinaryExpression::Convert(fCompiler.context(), pos,
1817                                                                    std::move(expr), op,
1818                                                                    std::move(right)));
1819     return true;
1820 }
1821 
1822 /* assignmentExpression (COMMA assignmentExpression)* */
expression()1823 std::unique_ptr<Expression> Parser::expression() {
1824     AutoDepth depth(this);
1825     [[maybe_unused]] Token start = this->peek();
1826     std::unique_ptr<Expression> result = this->assignmentExpression();
1827     if (!result) {
1828         return nullptr;
1829     }
1830     while (this->peek().fKind == Token::Kind::TK_COMMA) {
1831         if (!this->operatorRight(depth, Operator::Kind::COMMA, &Parser::assignmentExpression,
1832                                  result)) {
1833             return nullptr;
1834         }
1835     }
1836     SkASSERTF(result->position().valid(), "Expression %s has invalid position",
1837               result->description().c_str());
1838     SkASSERTF(result->position().startOffset() == this->position(start).startOffset(),
1839               "Expected %s to start at %d (first token: '%.*s'), but it has range %d-%d\n",
1840               result->description().c_str(), this->position(start).startOffset(),
1841               (int)this->text(start).length(), this->text(start).data(),
1842               result->position().startOffset(), result->position().endOffset());
1843     return result;
1844 }
1845 
1846 /* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1847    BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1848    assignmentExpression)*
1849  */
assignmentExpression()1850 std::unique_ptr<Expression> Parser::assignmentExpression() {
1851     AutoDepth depth(this);
1852     std::unique_ptr<Expression> result = this->ternaryExpression();
1853     if (!result) {
1854         return nullptr;
1855     }
1856     for (;;) {
1857         Operator::Kind op;
1858         switch (this->peek().fKind) {
1859             case Token::Kind::TK_EQ:           op = Operator::Kind::EQ;           break;
1860             case Token::Kind::TK_STAREQ:       op = Operator::Kind::STAREQ;       break;
1861             case Token::Kind::TK_SLASHEQ:      op = Operator::Kind::SLASHEQ;      break;
1862             case Token::Kind::TK_PERCENTEQ:    op = Operator::Kind::PERCENTEQ;    break;
1863             case Token::Kind::TK_PLUSEQ:       op = Operator::Kind::PLUSEQ;       break;
1864             case Token::Kind::TK_MINUSEQ:      op = Operator::Kind::MINUSEQ;      break;
1865             case Token::Kind::TK_SHLEQ:        op = Operator::Kind::SHLEQ;        break;
1866             case Token::Kind::TK_SHREQ:        op = Operator::Kind::SHREQ;        break;
1867             case Token::Kind::TK_BITWISEANDEQ: op = Operator::Kind::BITWISEANDEQ; break;
1868             case Token::Kind::TK_BITWISEXOREQ: op = Operator::Kind::BITWISEXOREQ; break;
1869             case Token::Kind::TK_BITWISEOREQ:  op = Operator::Kind::BITWISEOREQ;  break;
1870             default:                           return result;
1871         }
1872         if (!this->operatorRight(depth, op, &Parser::assignmentExpression, result)) {
1873             return nullptr;
1874         }
1875     }
1876 }
1877 
1878 /* logicalOrExpression ('?' expression ':' assignmentExpression)? */
ternaryExpression()1879 std::unique_ptr<Expression> Parser::ternaryExpression() {
1880     AutoDepth depth(this);
1881     std::unique_ptr<Expression> base = this->logicalOrExpression();
1882     if (!base) {
1883         return nullptr;
1884     }
1885     if (!this->checkNext(Token::Kind::TK_QUESTION)) {
1886         return base;
1887     }
1888     if (!depth.increase()) {
1889         return nullptr;
1890     }
1891     std::unique_ptr<Expression> trueExpr = this->expression();
1892     if (!trueExpr) {
1893         return nullptr;
1894     }
1895     if (!this->expect(Token::Kind::TK_COLON, "':'")) {
1896         return nullptr;
1897     }
1898     std::unique_ptr<Expression> falseExpr = this->assignmentExpression();
1899     if (!falseExpr) {
1900         return nullptr;
1901     }
1902     Position pos = base->position().rangeThrough(falseExpr->position());
1903     return this->expressionOrPoison(pos, TernaryExpression::Convert(fCompiler.context(),
1904                                                                     pos, std::move(base),
1905                                                                     std::move(trueExpr),
1906                                                                     std::move(falseExpr)));
1907 }
1908 
1909 /* logicalXorExpression (LOGICALOR logicalXorExpression)* */
logicalOrExpression()1910 std::unique_ptr<Expression> Parser::logicalOrExpression() {
1911     AutoDepth depth(this);
1912     std::unique_ptr<Expression> result = this->logicalXorExpression();
1913     if (!result) {
1914         return nullptr;
1915     }
1916     while (this->peek().fKind == Token::Kind::TK_LOGICALOR) {
1917         if (!this->operatorRight(depth, Operator::Kind::LOGICALOR, &Parser::logicalXorExpression,
1918                                  result)) {
1919             return nullptr;
1920         }
1921     }
1922     return result;
1923 }
1924 
1925 /* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
logicalXorExpression()1926 std::unique_ptr<Expression> Parser::logicalXorExpression() {
1927     AutoDepth depth(this);
1928     std::unique_ptr<Expression> result = this->logicalAndExpression();
1929     if (!result) {
1930         return nullptr;
1931     }
1932     while (this->peek().fKind == Token::Kind::TK_LOGICALXOR) {
1933         if (!this->operatorRight(depth, Operator::Kind::LOGICALXOR, &Parser::logicalAndExpression,
1934                                  result)) {
1935             return nullptr;
1936         }
1937     }
1938     return result;
1939 }
1940 
1941 /* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
logicalAndExpression()1942 std::unique_ptr<Expression> Parser::logicalAndExpression() {
1943     AutoDepth depth(this);
1944     std::unique_ptr<Expression> result = this->bitwiseOrExpression();
1945     if (!result) {
1946         return nullptr;
1947     }
1948     while (this->peek().fKind == Token::Kind::TK_LOGICALAND) {
1949         if (!this->operatorRight(depth, Operator::Kind::LOGICALAND, &Parser::bitwiseOrExpression,
1950                                  result)) {
1951             return nullptr;
1952         }
1953     }
1954     return result;
1955 }
1956 
1957 /* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
bitwiseOrExpression()1958 std::unique_ptr<Expression> Parser::bitwiseOrExpression() {
1959     AutoDepth depth(this);
1960     std::unique_ptr<Expression> result = this->bitwiseXorExpression();
1961     if (!result) {
1962         return nullptr;
1963     }
1964     while (this->peek().fKind == Token::Kind::TK_BITWISEOR) {
1965         if (!this->operatorRight(depth, Operator::Kind::BITWISEOR, &Parser::bitwiseXorExpression,
1966                                  result)) {
1967             return nullptr;
1968         }
1969     }
1970     return result;
1971 }
1972 
1973 /* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
bitwiseXorExpression()1974 std::unique_ptr<Expression> Parser::bitwiseXorExpression() {
1975     AutoDepth depth(this);
1976     std::unique_ptr<Expression> result = this->bitwiseAndExpression();
1977     if (!result) {
1978         return nullptr;
1979     }
1980     while (this->peek().fKind == Token::Kind::TK_BITWISEXOR) {
1981         if (!this->operatorRight(depth, Operator::Kind::BITWISEXOR, &Parser::bitwiseAndExpression,
1982                                  result)) {
1983             return nullptr;
1984         }
1985     }
1986     return result;
1987 }
1988 
1989 /* equalityExpression (BITWISEAND equalityExpression)* */
bitwiseAndExpression()1990 std::unique_ptr<Expression> Parser::bitwiseAndExpression() {
1991     AutoDepth depth(this);
1992     std::unique_ptr<Expression> result = this->equalityExpression();
1993     if (!result) {
1994         return nullptr;
1995     }
1996     while (this->peek().fKind == Token::Kind::TK_BITWISEAND) {
1997         if (!this->operatorRight(depth, Operator::Kind::BITWISEAND, &Parser::equalityExpression,
1998                                  result)) {
1999             return nullptr;
2000         }
2001     }
2002     return result;
2003 }
2004 
2005 /* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
equalityExpression()2006 std::unique_ptr<Expression> Parser::equalityExpression() {
2007     AutoDepth depth(this);
2008     std::unique_ptr<Expression> result = this->relationalExpression();
2009     if (!result) {
2010         return nullptr;
2011     }
2012     for (;;) {
2013         Operator::Kind op;
2014         switch (this->peek().fKind) {
2015             case Token::Kind::TK_EQEQ: op = Operator::Kind::EQEQ; break;
2016             case Token::Kind::TK_NEQ:  op = Operator::Kind::NEQ;  break;
2017             default:                   return result;
2018         }
2019         if (!this->operatorRight(depth, op, &Parser::relationalExpression, result)) {
2020             return nullptr;
2021         }
2022     }
2023 }
2024 
2025 /* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
relationalExpression()2026 std::unique_ptr<Expression> Parser::relationalExpression() {
2027     AutoDepth depth(this);
2028     std::unique_ptr<Expression> result = this->shiftExpression();
2029     if (!result) {
2030         return nullptr;
2031     }
2032     for (;;) {
2033         Operator::Kind op;
2034         switch (this->peek().fKind) {
2035             case Token::Kind::TK_LT:   op = Operator::Kind::LT;   break;
2036             case Token::Kind::TK_GT:   op = Operator::Kind::GT;   break;
2037             case Token::Kind::TK_LTEQ: op = Operator::Kind::LTEQ; break;
2038             case Token::Kind::TK_GTEQ: op = Operator::Kind::GTEQ; break;
2039             default:                   return result;
2040         }
2041         if (!this->operatorRight(depth, op, &Parser::shiftExpression, result)) {
2042             return nullptr;
2043         }
2044     }
2045 }
2046 
2047 /* additiveExpression ((SHL | SHR) additiveExpression)* */
shiftExpression()2048 std::unique_ptr<Expression> Parser::shiftExpression() {
2049     AutoDepth depth(this);
2050     std::unique_ptr<Expression> result = this->additiveExpression();
2051     if (!result) {
2052         return nullptr;
2053     }
2054     for (;;) {
2055         Operator::Kind op;
2056         switch (this->peek().fKind) {
2057             case Token::Kind::TK_SHL: op = Operator::Kind::SHL; break;
2058             case Token::Kind::TK_SHR: op = Operator::Kind::SHR; break;
2059             default:                  return result;
2060         }
2061         if (!this->operatorRight(depth, op, &Parser::additiveExpression, result)) {
2062             return nullptr;
2063         }
2064     }
2065 }
2066 
2067 /* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
additiveExpression()2068 std::unique_ptr<Expression> Parser::additiveExpression() {
2069     AutoDepth depth(this);
2070     std::unique_ptr<Expression> result = this->multiplicativeExpression();
2071     if (!result) {
2072         return nullptr;
2073     }
2074     for (;;) {
2075         Operator::Kind op;
2076         switch (this->peek().fKind) {
2077             case Token::Kind::TK_PLUS:  op = Operator::Kind::PLUS;  break;
2078             case Token::Kind::TK_MINUS: op = Operator::Kind::MINUS; break;
2079             default:                    return result;
2080         }
2081         if (!this->operatorRight(depth, op, &Parser::multiplicativeExpression, result)) {
2082             return nullptr;
2083         }
2084     }
2085 }
2086 
2087 /* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
multiplicativeExpression()2088 std::unique_ptr<Expression> Parser::multiplicativeExpression() {
2089     AutoDepth depth(this);
2090     std::unique_ptr<Expression> result = this->unaryExpression();
2091     if (!result) {
2092         return nullptr;
2093     }
2094     for (;;) {
2095         Operator::Kind op;
2096         switch (this->peek().fKind) {
2097             case Token::Kind::TK_STAR:    op = Operator::Kind::STAR;    break;
2098             case Token::Kind::TK_SLASH:   op = Operator::Kind::SLASH;   break;
2099             case Token::Kind::TK_PERCENT: op = Operator::Kind::PERCENT; break;
2100             default:                      return result;
2101         }
2102         if (!this->operatorRight(depth, op, &Parser::unaryExpression, result)) {
2103             return nullptr;
2104         }
2105     }
2106 }
2107 
2108 /* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
unaryExpression()2109 std::unique_ptr<Expression> Parser::unaryExpression() {
2110     AutoDepth depth(this);
2111     Operator::Kind op;
2112     Token start = this->peek();
2113     switch (start.fKind) {
2114         case Token::Kind::TK_PLUS:       op = Operator::Kind::PLUS;       break;
2115         case Token::Kind::TK_MINUS:      op = Operator::Kind::MINUS;      break;
2116         case Token::Kind::TK_LOGICALNOT: op = Operator::Kind::LOGICALNOT; break;
2117         case Token::Kind::TK_BITWISENOT: op = Operator::Kind::BITWISENOT; break;
2118         case Token::Kind::TK_PLUSPLUS:   op = Operator::Kind::PLUSPLUS;   break;
2119         case Token::Kind::TK_MINUSMINUS: op = Operator::Kind::MINUSMINUS; break;
2120         default:                         return this->postfixExpression();
2121     }
2122     this->nextToken();
2123     if (!depth.increase()) {
2124         return nullptr;
2125     }
2126     std::unique_ptr<Expression> expr = this->unaryExpression();
2127     if (!expr) {
2128         return nullptr;
2129     }
2130     Position pos = Position::Range(start.fOffset, expr->position().endOffset());
2131     return this->expressionOrPoison(pos, PrefixExpression::Convert(fCompiler.context(),
2132                                                                    pos, op, std::move(expr)));
2133 }
2134 
2135 /* term suffix* */
postfixExpression()2136 std::unique_ptr<Expression> Parser::postfixExpression() {
2137     AutoDepth depth(this);
2138     std::unique_ptr<Expression> result = this->term();
2139     if (!result) {
2140         return nullptr;
2141     }
2142     for (;;) {
2143         Token t = this->peek();
2144         switch (t.fKind) {
2145             case Token::Kind::TK_FLOAT_LITERAL:
2146                 if (this->text(t)[0] != '.') {
2147                     return result;
2148                 }
2149                 [[fallthrough]];
2150             case Token::Kind::TK_LBRACKET:
2151             case Token::Kind::TK_DOT:
2152             case Token::Kind::TK_LPAREN:
2153             case Token::Kind::TK_PLUSPLUS:
2154             case Token::Kind::TK_MINUSMINUS: {
2155                 if (!depth.increase()) {
2156                     return nullptr;
2157                 }
2158                 result = this->suffix(std::move(result));
2159                 if (!result) {
2160                     return nullptr;
2161                 }
2162                 break;
2163             }
2164             default:
2165                 return result;
2166         }
2167     }
2168 }
2169 
swizzle(Position pos,std::unique_ptr<Expression> base,std::string_view swizzleMask,Position maskPos)2170 std::unique_ptr<Expression> Parser::swizzle(Position pos,
2171                                             std::unique_ptr<Expression> base,
2172                                             std::string_view swizzleMask,
2173                                             Position maskPos) {
2174     SkASSERT(!swizzleMask.empty());
2175     if (!base->type().isVector() && !base->type().isScalar()) {
2176         return this->expressionOrPoison(pos, FieldAccess::Convert(fCompiler.context(), pos,
2177                                                                   std::move(base), swizzleMask));
2178 
2179     }
2180     return this->expressionOrPoison(pos, Swizzle::Convert(fCompiler.context(), pos, maskPos,
2181                                                           std::move(base), swizzleMask));
2182 }
2183 
call(Position pos,std::unique_ptr<Expression> base,ExpressionArray args)2184 std::unique_ptr<Expression> Parser::call(Position pos,
2185                                          std::unique_ptr<Expression> base,
2186                                          ExpressionArray args) {
2187     return this->expressionOrPoison(pos, SkSL::FunctionCall::Convert(fCompiler.context(), pos,
2188                                                                      std::move(base),
2189                                                                      std::move(args)));
2190 }
2191 
2192 /* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN arguments RPAREN |
2193    PLUSPLUS | MINUSMINUS | COLONCOLON IDENTIFIER | FLOAT_LITERAL [IDENTIFIER] */
suffix(std::unique_ptr<Expression> base)2194 std::unique_ptr<Expression> Parser::suffix(std::unique_ptr<Expression> base) {
2195     AutoDepth depth(this);
2196     Token next = this->nextToken();
2197     if (!depth.increase()) {
2198         return nullptr;
2199     }
2200     switch (next.fKind) {
2201         case Token::Kind::TK_LBRACKET: {
2202             if (this->checkNext(Token::Kind::TK_RBRACKET)) {
2203                 this->error(this->rangeFrom(next), "missing index in '[]'");
2204                 return this->poison(this->rangeFrom(base->position()));
2205             }
2206             std::unique_ptr<Expression> index = this->expression();
2207             if (!index) {
2208                 return nullptr;
2209             }
2210             this->expect(Token::Kind::TK_RBRACKET, "']' to complete array access expression");
2211 
2212             Position pos = this->rangeFrom(base->position());
2213             return this->expressionOrPoison(pos, IndexExpression::Convert(fCompiler.context(), pos,
2214                                                                           std::move(base),
2215                                                                           std::move(index)));
2216         }
2217         case Token::Kind::TK_DOT: {
2218             std::string_view text;
2219             if (this->identifier(&text)) {
2220                 Position pos = this->rangeFrom(base->position());
2221                 return this->swizzle(pos, std::move(base), text,
2222                                      this->rangeFrom(this->position(next).after()));
2223             }
2224             [[fallthrough]];
2225         }
2226         case Token::Kind::TK_FLOAT_LITERAL: {
2227             // Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
2228             // floating point literals, possibly followed by an identifier. Handle that here.
2229             std::string_view field = this->text(next);
2230             SkASSERT(field[0] == '.');
2231             field.remove_prefix(1);
2232             // use the next *raw* token so we don't ignore whitespace - we only care about
2233             // identifiers that directly follow the float
2234             Position pos = this->rangeFrom(base->position());
2235             Position start = this->position(next);
2236             // skip past the "."
2237             start = Position::Range(start.startOffset() + 1, start.endOffset());
2238             Position maskPos = this->rangeFrom(start);
2239             Token id = this->nextRawToken();
2240             if (id.fKind == Token::Kind::TK_IDENTIFIER) {
2241                 pos = this->rangeFrom(base->position());
2242                 maskPos = this->rangeFrom(start);
2243                 return this->swizzle(pos,
2244                                      std::move(base),
2245                                      std::string(field) + std::string(this->text(id)),
2246                                      maskPos);
2247             }
2248             if (field.empty()) {
2249                 this->error(pos, "expected field name or swizzle mask after '.'");
2250                 return this->poison(pos);
2251             }
2252             this->pushback(id);
2253             return this->swizzle(pos, std::move(base), field, maskPos);
2254         }
2255         case Token::Kind::TK_LPAREN: {
2256             ExpressionArray args;
2257             if (this->peek().fKind != Token::Kind::TK_RPAREN) {
2258                 for (;;) {
2259                     std::unique_ptr<Expression> expr = this->assignmentExpression();
2260                     if (!expr) {
2261                         return nullptr;
2262                     }
2263                     args.push_back(std::move(expr));
2264                     if (!this->checkNext(Token::Kind::TK_COMMA)) {
2265                         break;
2266                     }
2267                 }
2268             }
2269             this->expect(Token::Kind::TK_RPAREN, "')' to complete function arguments");
2270             Position pos = this->rangeFrom(base->position());
2271             return this->call(pos, std::move(base), std::move(args));
2272         }
2273         case Token::Kind::TK_PLUSPLUS:
2274         case Token::Kind::TK_MINUSMINUS: {
2275             Operator::Kind op = (next.fKind == Token::Kind::TK_PLUSPLUS)
2276                                         ? Operator::Kind::PLUSPLUS
2277                                         : Operator::Kind::MINUSMINUS;
2278             Position pos = this->rangeFrom(base->position());
2279             return this->expressionOrPoison(pos, PostfixExpression::Convert(fCompiler.context(),
2280                                                                             pos, std::move(base),
2281                                                                             op));
2282         }
2283         default: {
2284             this->error(next, "expected expression suffix, but found '" +
2285                               std::string(this->text(next)) + "'");
2286             return nullptr;
2287         }
2288     }
2289 }
2290 
2291 /* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */
term()2292 std::unique_ptr<Expression> Parser::term() {
2293     AutoDepth depth(this);
2294     Token t = this->peek();
2295     switch (t.fKind) {
2296         case Token::Kind::TK_IDENTIFIER: {
2297             std::string_view text;
2298             if (this->identifier(&text)) {
2299                 Position pos = this->position(t);
2300                 return this->expressionOrPoison(
2301                         pos,
2302                         this->symbolTable()->instantiateSymbolRef(fCompiler.context(), text, pos));
2303             }
2304             break;
2305         }
2306         case Token::Kind::TK_INT_LITERAL: {
2307             SKSL_INT i;
2308             if (!this->intLiteral(&i)) {
2309                 i = 0;
2310             }
2311             Position pos = this->position(t);
2312             return this->expressionOrPoison(pos, SkSL::Literal::MakeInt(fCompiler.context(),
2313                                                                         pos, i));
2314         }
2315         case Token::Kind::TK_FLOAT_LITERAL: {
2316             SKSL_FLOAT f;
2317             if (!this->floatLiteral(&f)) {
2318                 f = 0.0f;
2319             }
2320             Position pos = this->position(t);
2321             return this->expressionOrPoison(pos, SkSL::Literal::MakeFloat(fCompiler.context(),
2322                                                                           pos, f));
2323         }
2324         case Token::Kind::TK_TRUE_LITERAL: // fall through
2325         case Token::Kind::TK_FALSE_LITERAL: {
2326             bool b;
2327             SkAssertResult(this->boolLiteral(&b));
2328             Position pos = this->position(t);
2329             return this->expressionOrPoison(pos, SkSL::Literal::MakeBool(fCompiler.context(),
2330                                                                          pos, b));
2331         }
2332         case Token::Kind::TK_LPAREN: {
2333             this->nextToken();
2334             if (!depth.increase()) {
2335                 return nullptr;
2336             }
2337             std::unique_ptr<Expression> result = this->expression();
2338             if (result != nullptr) {
2339                 this->expect(Token::Kind::TK_RPAREN, "')' to complete expression");
2340                 result->setPosition(this->rangeFrom(this->position(t)));
2341                 return result;
2342             }
2343             break;
2344         }
2345         default:
2346             this->nextToken();
2347             this->error(t, "expected expression, but found '" + std::string(this->text(t)) + "'");
2348             fEncounteredFatalError = true;
2349             break;
2350     }
2351     return nullptr;
2352 }
2353 
2354 /* INT_LITERAL */
intLiteral(SKSL_INT * dest)2355 bool Parser::intLiteral(SKSL_INT* dest) {
2356     Token t;
2357     if (!this->expect(Token::Kind::TK_INT_LITERAL, "integer literal", &t)) {
2358         return false;
2359     }
2360     std::string_view s = this->text(t);
2361     if (!SkSL::stoi(s, dest)) {
2362         this->error(t, "integer is too large: " + std::string(s));
2363         return false;
2364     }
2365     return true;
2366 }
2367 
2368 /* FLOAT_LITERAL */
floatLiteral(SKSL_FLOAT * dest)2369 bool Parser::floatLiteral(SKSL_FLOAT* dest) {
2370     Token t;
2371     if (!this->expect(Token::Kind::TK_FLOAT_LITERAL, "float literal", &t)) {
2372         return false;
2373     }
2374     std::string_view s = this->text(t);
2375     if (!SkSL::stod(s, dest)) {
2376         this->error(t, "floating-point value is too large: " + std::string(s));
2377         return false;
2378     }
2379     return true;
2380 }
2381 
2382 /* TRUE_LITERAL | FALSE_LITERAL */
boolLiteral(bool * dest)2383 bool Parser::boolLiteral(bool* dest) {
2384     Token t = this->nextToken();
2385     switch (t.fKind) {
2386         case Token::Kind::TK_TRUE_LITERAL:
2387             *dest = true;
2388             return true;
2389         case Token::Kind::TK_FALSE_LITERAL:
2390             *dest = false;
2391             return true;
2392         default:
2393             this->error(t, "expected 'true' or 'false', but found '" +
2394                            std::string(this->text(t)) + "'");
2395             return false;
2396     }
2397 }
2398 
2399 /* IDENTIFIER */
identifier(std::string_view * dest)2400 bool Parser::identifier(std::string_view* dest) {
2401     Token t;
2402     if (this->expect(Token::Kind::TK_IDENTIFIER, "identifier", &t)) {
2403         *dest = this->text(t);
2404         return true;
2405     }
2406     return false;
2407 }
2408 
2409 }  // namespace SkSL
2410