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