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(¶m)) {
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