1/*
2 * Copyright 2016 Google Inc.
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 <memory>
11#include "stdio.h"
12
13#include "src/sksl/SkSLASTNode.h"
14#include "src/sksl/ir/SkSLModifiers.h"
15#include "src/sksl/ir/SkSLSymbolTable.h"
16#include "src/sksl/ir/SkSLType.h"
17
18#ifndef SKSL_STANDALONE
19#include "include/private/SkOnce.h"
20#endif
21
22namespace SkSL {
23
24#define MAX_PARSE_DEPTH 50
25
26class AutoDepth {
27public:
28 AutoDepth(Parser* p)
29 : fParser(p)
30 , fDepth(0) {}
31
32 ~AutoDepth() {
33 fParser->fDepth -= fDepth;
34 }
35
36 bool increase() {
37 ++fDepth;
38 ++fParser->fDepth;
39 if (fParser->fDepth > MAX_PARSE_DEPTH) {
40 fParser->error(fParser->peek(), String("exceeded max parse depth"));
41 return false;
42 }
43 return true;
44 }
45
46private:
47 Parser* fParser;
48 int fDepth;
49};
50
51std::unordered_map<String, Parser::LayoutToken>* Parser::layoutTokens;
52
53void Parser::InitLayoutMap() {
54 layoutTokens = new std::unordered_map<String, LayoutToken>;
55 #define TOKEN(name, text) (*layoutTokens)[text] = LayoutToken::name
56 TOKEN(LOCATION, "location");
57 TOKEN(OFFSET, "offset");
58 TOKEN(BINDING, "binding");
59 TOKEN(INDEX, "index");
60 TOKEN(SET, "set");
61 TOKEN(BUILTIN, "builtin");
62 TOKEN(INPUT_ATTACHMENT_INDEX, "input_attachment_index");
63 TOKEN(ORIGIN_UPPER_LEFT, "origin_upper_left");
64 TOKEN(OVERRIDE_COVERAGE, "override_coverage");
65 TOKEN(BLEND_SUPPORT_ALL_EQUATIONS, "blend_support_all_equations");
66 TOKEN(BLEND_SUPPORT_MULTIPLY, "blend_support_multiply");
67 TOKEN(BLEND_SUPPORT_SCREEN, "blend_support_screen");
68 TOKEN(BLEND_SUPPORT_OVERLAY, "blend_support_overlay");
69 TOKEN(BLEND_SUPPORT_DARKEN, "blend_support_darken");
70 TOKEN(BLEND_SUPPORT_LIGHTEN, "blend_support_lighten");
71 TOKEN(BLEND_SUPPORT_COLORDODGE, "blend_support_colordodge");
72 TOKEN(BLEND_SUPPORT_COLORBURN, "blend_support_colorburn");
73 TOKEN(BLEND_SUPPORT_HARDLIGHT, "blend_support_hardlight");
74 TOKEN(BLEND_SUPPORT_SOFTLIGHT, "blend_support_softlight");
75 TOKEN(BLEND_SUPPORT_DIFFERENCE, "blend_support_difference");
76 TOKEN(BLEND_SUPPORT_EXCLUSION, "blend_support_exclusion");
77 TOKEN(BLEND_SUPPORT_HSL_HUE, "blend_support_hsl_hue");
78 TOKEN(BLEND_SUPPORT_HSL_SATURATION, "blend_support_hsl_saturation");
79 TOKEN(BLEND_SUPPORT_HSL_COLOR, "blend_support_hsl_color");
80 TOKEN(BLEND_SUPPORT_HSL_LUMINOSITY, "blend_support_hsl_luminosity");
81 TOKEN(PUSH_CONSTANT, "push_constant");
82 TOKEN(POINTS, "points");
83 TOKEN(LINES, "lines");
84 TOKEN(LINE_STRIP, "line_strip");
85 TOKEN(LINES_ADJACENCY, "lines_adjacency");
86 TOKEN(TRIANGLES, "triangles");
87 TOKEN(TRIANGLE_STRIP, "triangle_strip");
88 TOKEN(TRIANGLES_ADJACENCY, "triangles_adjacency");
89 TOKEN(MAX_VERTICES, "max_vertices");
90 TOKEN(INVOCATIONS, "invocations");
91 TOKEN(MARKER, "marker");
92 TOKEN(WHEN, "when");
93 TOKEN(KEY, "key");
94 TOKEN(TRACKED, "tracked");
95 TOKEN(SRGB_UNPREMUL, "srgb_unpremul");
96 TOKEN(CTYPE, "ctype");
97 TOKEN(SKPMCOLOR4F, "SkPMColor4f");
98 TOKEN(SKV4, "SkV4");
99 TOKEN(SKRECT, "SkRect");
100 TOKEN(SKIRECT, "SkIRect");
101 TOKEN(SKPMCOLOR, "SkPMColor");
102 TOKEN(SKM44, "SkM44");
103 TOKEN(BOOL, "bool");
104 TOKEN(INT, "int");
105 TOKEN(FLOAT, "float");
106 #undef TOKEN
107}
108
109Parser::Parser(const char* text, size_t length, SymbolTable& symbols, ErrorReporter& errors)
110: fText(text)
111, fPushback(Token::Kind::TK_INVALID, -1, -1)
112, fSymbols(symbols)
113, fErrors(errors) {
114 fLexer.start(text, length);
115 static const bool layoutMapInitialized = []{ return (void)InitLayoutMap(), true; }();
116 (void) layoutMapInitialized;
117}
118
119#define CREATE_NODE(result, ...) \
120 ASTNode::ID result(fFile->fNodes.size()); \
121 fFile->fNodes.emplace_back(&fFile->fNodes, __VA_ARGS__)
122
123#define RETURN_NODE(...) \
124 do { \
125 CREATE_NODE(result, __VA_ARGS__); \
126 return result; \
127 } while (false)
128
129#define CREATE_CHILD(child, target, ...) \
130 CREATE_NODE(child, __VA_ARGS__); \
131 fFile->fNodes[target.fValue].addChild(child)
132
133#define CREATE_EMPTY_CHILD(target) \
134 do { \
135 ASTNode::ID child(fFile->fNodes.size()); \
136 fFile->fNodes.emplace_back(); \
137 fFile->fNodes[target.fValue].addChild(child); \
138 } while (false)
139
140/* (directive | section | declaration)* END_OF_FILE */
141std::unique_ptr<ASTFile> Parser::file() {
142 fFile = std::make_unique<ASTFile>();
143 CREATE_NODE(result, 0, ASTNode::Kind::kFile);
144 fFile->fRoot = result;
145 for (;;) {
146 switch (this->peek().fKind) {
147 case Token::Kind::TK_END_OF_FILE:
148 return std::move(fFile);
149 case Token::Kind::TK_DIRECTIVE: {
150 ASTNode::ID dir = this->directive();
151 if (fErrors.errorCount()) {
152 return nullptr;
153 }
154 if (dir) {
155 getNode(result).addChild(dir);
156 }
157 break;
158 }
159 case Token::Kind::TK_SECTION: {
160 ASTNode::ID section = this->section();
161 if (fErrors.errorCount()) {
162 return nullptr;
163 }
164 if (section) {
165 getNode(result).addChild(section);
166 }
167 break;
168 }
169 default: {
170 ASTNode::ID decl = this->declaration();
171 if (fErrors.errorCount()) {
172 return nullptr;
173 }
174 if (decl) {
175 getNode(result).addChild(decl);
176 }
177 }
178 }
179 }
180 return std::move(fFile);
181}
182
183Token Parser::nextRawToken() {
184 if (fPushback.fKind != Token::Kind::TK_INVALID) {
185 Token result = fPushback;
186 fPushback.fKind = Token::Kind::TK_INVALID;
187 return result;
188 }
189 Token result = fLexer.next();
190 return result;
191}
192
193Token Parser::nextToken() {
194 Token token = this->nextRawToken();
195 while (token.fKind == Token::Kind::TK_WHITESPACE ||
196 token.fKind == Token::Kind::TK_LINE_COMMENT ||
197 token.fKind == Token::Kind::TK_BLOCK_COMMENT) {
198 token = this->nextRawToken();
199 }
200 return token;
201}
202
203void Parser::pushback(Token t) {
204 SkASSERT(fPushback.fKind == Token::Kind::TK_INVALID);
205 fPushback = std::move(t);
206}
207
208Token Parser::peek() {
209 if (fPushback.fKind == Token::Kind::TK_INVALID) {
210 fPushback = this->nextToken();
211 }
212 return fPushback;
213}
214
215bool Parser::checkNext(Token::Kind kind, Token* result) {
216 if (fPushback.fKind != Token::Kind::TK_INVALID && fPushback.fKind != kind) {
217 return false;
218 }
219 Token next = this->nextToken();
220 if (next.fKind == kind) {
221 if (result) {
222 *result = next;
223 }
224 return true;
225 }
226 this->pushback(std::move(next));
227 return false;
228}
229
230bool Parser::expect(Token::Kind kind, const char* expected, Token* result) {
231 Token next = this->nextToken();
232 if (next.fKind == kind) {
233 if (result) {
234 *result = std::move(next);
235 }
236 return true;
237 } else {
238 this->error(next, "expected " + String(expected) + ", but found '" +
239 this->text(next) + "'");
240 return false;
241 }
242}
243
244StringFragment Parser::text(Token token) {
245 return StringFragment(fText + token.fOffset, token.fLength);
246}
247
248void Parser::error(Token token, String msg) {
249 this->error(token.fOffset, msg);
250}
251
252void Parser::error(int offset, String msg) {
253 fErrors.error(offset, msg);
254}
255
256bool Parser::isType(StringFragment name) {
257 const Symbol* s = fSymbols[name];
258 return s && s->fKind == Symbol::kType_Kind;
259}
260
261/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
262 DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
263ASTNode::ID Parser::directive() {
264 Token start;
265 if (!this->expect(Token::Kind::TK_DIRECTIVE, "a directive", &start)) {
266 return ASTNode::ID::Invalid();
267 }
268 StringFragment text = this->text(start);
269 if (text == "#extension") {
270 Token name;
271 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
272 return ASTNode::ID::Invalid();
273 }
274 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
275 return ASTNode::ID::Invalid();
276 }
277 // FIXME: need to start paying attention to this token
278 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier")) {
279 return ASTNode::ID::Invalid();
280 }
281 RETURN_NODE(start.fOffset, ASTNode::Kind::kExtension, this->text(name));
282 } else {
283 this->error(start, "unsupported directive '" + this->text(start) + "'");
284 return ASTNode::ID::Invalid();
285 }
286}
287
288/* SECTION LBRACE (LPAREN IDENTIFIER RPAREN)? <any sequence of tokens with balanced braces>
289 RBRACE */
290ASTNode::ID Parser::section() {
291 Token start;
292 if (!this->expect(Token::Kind::TK_SECTION, "a section token", &start)) {
293 return ASTNode::ID::Invalid();
294 }
295 StringFragment argument;
296 if (this->peek().fKind == Token::Kind::TK_LPAREN) {
297 this->nextToken();
298 Token argToken;
299 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &argToken)) {
300 return ASTNode::ID::Invalid();
301 }
302 argument = this->text(argToken);
303 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
304 return ASTNode::ID::Invalid();
305 }
306 }
307 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
308 return ASTNode::ID::Invalid();
309 }
310 StringFragment text;
311 Token codeStart = this->nextRawToken();
312 size_t startOffset = codeStart.fOffset;
313 this->pushback(codeStart);
314 text.fChars = fText + startOffset;
315 int level = 1;
316 for (;;) {
317 Token next = this->nextRawToken();
318 switch (next.fKind) {
319 case Token::Kind::TK_LBRACE:
320 ++level;
321 break;
322 case Token::Kind::TK_RBRACE:
323 --level;
324 break;
325 case Token::Kind::TK_END_OF_FILE:
326 this->error(start, "reached end of file while parsing section");
327 return ASTNode::ID::Invalid();
328 default:
329 break;
330 }
331 if (!level) {
332 text.fLength = next.fOffset - startOffset;
333 break;
334 }
335 }
336 StringFragment name = this->text(start);
337 ++name.fChars;
338 --name.fLength;
339 RETURN_NODE(start.fOffset, ASTNode::Kind::kSection,
340 ASTNode::SectionData(name, argument, text));
341}
342
343/* ENUM CLASS IDENTIFIER LBRACE (IDENTIFIER (EQ expression)? (COMMA IDENTIFIER (EQ expression))*)?
344 RBRACE */
345ASTNode::ID Parser::enumDeclaration() {
346 Token start;
347 if (!this->expect(Token::Kind::TK_ENUM, "'enum'", &start)) {
348 return ASTNode::ID::Invalid();
349 }
350 if (!this->expect(Token::Kind::TK_CLASS, "'class'")) {
351 return ASTNode::ID::Invalid();
352 }
353 Token name;
354 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
355 return ASTNode::ID::Invalid();
356 }
357 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
358 return ASTNode::ID::Invalid();
359 }
360 fSymbols.add(this->text(name), std::make_unique<Type>(this->text(name), Type::kEnum_Kind));
361 CREATE_NODE(result, name.fOffset, ASTNode::Kind::kEnum, this->text(name));
362 if (!this->checkNext(Token::Kind::TK_RBRACE)) {
363 Token id;
364 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &id)) {
365 return ASTNode::ID::Invalid();
366 }
367 if (this->checkNext(Token::Kind::TK_EQ)) {
368 ASTNode::ID value = this->assignmentExpression();
369 if (!value) {
370 return ASTNode::ID::Invalid();
371 }
372 CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
373 getNode(child).addChild(value);
374 } else {
375 CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
376 }
377 while (!this->checkNext(Token::Kind::TK_RBRACE)) {
378 if (!this->expect(Token::Kind::TK_COMMA, "','")) {
379 return ASTNode::ID::Invalid();
380 }
381 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &id)) {
382 return ASTNode::ID::Invalid();
383 }
384 if (this->checkNext(Token::Kind::TK_EQ)) {
385 ASTNode::ID value = this->assignmentExpression();
386 if (!value) {
387 return ASTNode::ID::Invalid();
388 }
389 CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
390 getNode(child).addChild(value);
391 } else {
392 CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
393 }
394 }
395 }
396 this->expect(Token::Kind::TK_SEMICOLON, "';'");
397 return result;
398}
399
400/* enumDeclaration | modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
401 (COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
402ASTNode::ID Parser::declaration() {
403 Token lookahead = this->peek();
404 if (lookahead.fKind == Token::Kind::TK_ENUM) {
405 return this->enumDeclaration();
406 }
407 Modifiers modifiers = this->modifiers();
408 lookahead = this->peek();
409 if (lookahead.fKind == Token::Kind::TK_IDENTIFIER && !this->isType(this->text(lookahead))) {
410 // we have an identifier that's not a type, could be the start of an interface block
411 return this->interfaceBlock(modifiers);
412 }
413 if (lookahead.fKind == Token::Kind::TK_STRUCT) {
414 return this->structVarDeclaration(modifiers);
415 }
416 if (lookahead.fKind == Token::Kind::TK_SEMICOLON) {
417 this->nextToken();
418 RETURN_NODE(lookahead.fOffset, ASTNode::Kind::kModifiers, modifiers);
419 }
420 ASTNode::ID type = this->type();
421 if (!type) {
422 return ASTNode::ID::Invalid();
423 }
424 if (getNode(type).getTypeData().fIsStructDeclaration &&
425 this->checkNext(Token::Kind::TK_SEMICOLON)) {
426 return ASTNode::ID::Invalid();
427 }
428 Token name;
429 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
430 return ASTNode::ID::Invalid();
431 }
432 if (this->checkNext(Token::Kind::TK_LPAREN)) {
433 CREATE_NODE(result, name.fOffset, ASTNode::Kind::kFunction);
434 ASTNode::FunctionData fd(modifiers, this->text(name), 0);
435 getNode(result).addChild(type);
436 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
437 for (;;) {
438 ASTNode::ID parameter = this->parameter();
439 if (!parameter) {
440 return ASTNode::ID::Invalid();
441 }
442 ++fd.fParameterCount;
443 getNode(result).addChild(parameter);
444 if (!this->checkNext(Token::Kind::TK_COMMA)) {
445 break;
446 }
447 }
448 }
449 getNode(result).setFunctionData(fd);
450 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
451 return ASTNode::ID::Invalid();
452 }
453 ASTNode::ID body;
454 if (!this->checkNext(Token::Kind::TK_SEMICOLON)) {
455 body = this->block();
456 if (!body) {
457 return ASTNode::ID::Invalid();
458 }
459 getNode(result).addChild(body);
460 }
461 return result;
462 } else {
463 return this->varDeclarationEnd(modifiers, type, this->text(name));
464 }
465}
466
467/* modifiers type IDENTIFIER varDeclarationEnd */
468ASTNode::ID Parser::varDeclarations() {
469 Modifiers modifiers = this->modifiers();
470 ASTNode::ID type = this->type();
471 if (!type) {
472 return ASTNode::ID::Invalid();
473 }
474 Token name;
475 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
476 return ASTNode::ID::Invalid();
477 }
478 return this->varDeclarationEnd(modifiers, type, this->text(name));
479}
480
481/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
482ASTNode::ID Parser::structDeclaration() {
483 if (!this->expect(Token::Kind::TK_STRUCT, "'struct'")) {
484 return ASTNode::ID::Invalid();
485 }
486 Token name;
487 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
488 return ASTNode::ID::Invalid();
489 }
490 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
491 return ASTNode::ID::Invalid();
492 }
493 std::vector<Type::Field> fields;
494 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
495 ASTNode::ID decls = this->varDeclarations();
496 if (!decls) {
497 return ASTNode::ID::Invalid();
498 }
499 ASTNode& declsNode = getNode(decls);
500 const Symbol* symbol = fSymbols[(declsNode.begin() + 1)->getTypeData().fName];
501 SkASSERT(symbol && symbol->fKind == Symbol::kType_Kind);
502 const Type* type = (const Type*) symbol;
503 for (auto iter = declsNode.begin() + 2; iter != declsNode.end(); ++iter) {
504 ASTNode& var = *iter;
505 ASTNode::VarData vd = var.getVarData();
506 for (int j = vd.fSizeCount - 1; j >= 0; j--) {
507 const ASTNode& size = *(var.begin() + j);
508 if (!size || size.fKind != ASTNode::Kind::kInt) {
509 this->error(declsNode.fOffset, "array size in struct field must be a constant");
510 return ASTNode::ID::Invalid();
511 }
512 uint64_t columns = size.getInt();
513 String name = type->name() + "[" + to_string(columns) + "]";
514 type = fSymbols.takeOwnershipOfSymbol(
515 std::make_unique<Type>(name, Type::kArray_Kind, *type, (int)columns));
516 }
517 fields.push_back(Type::Field(declsNode.begin()->getModifiers(), vd.fName, type));
518 if (vd.fSizeCount ? (var.begin() + (vd.fSizeCount - 1))->fNext : var.fFirstChild) {
519 this->error(declsNode.fOffset, "initializers are not permitted on struct fields");
520 }
521 }
522 }
523 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
524 return ASTNode::ID::Invalid();
525 }
526 fSymbols.add(this->text(name), std::make_unique<Type>(name.fOffset, this->text(name), fields));
527 RETURN_NODE(name.fOffset, ASTNode::Kind::kType,
528 ASTNode::TypeData(this->text(name), true, false));
529}
530
531/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
532ASTNode::ID Parser::structVarDeclaration(Modifiers modifiers) {
533 ASTNode::ID type = this->structDeclaration();
534 if (!type) {
535 return ASTNode::ID::Invalid();
536 }
537 Token name;
538 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &name)) {
539 return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
540 }
541 this->expect(Token::Kind::TK_SEMICOLON, "';'");
542 return ASTNode::ID::Invalid();
543}
544
545/* (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)? (COMMA IDENTIFER
546 (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
547ASTNode::ID Parser::varDeclarationEnd(Modifiers mods, ASTNode::ID type, StringFragment name) {
548 CREATE_NODE(result, -1, ASTNode::Kind::kVarDeclarations);
549 CREATE_CHILD(modifiers, result, -1, ASTNode::Kind::kModifiers, mods);
550 getNode(result).addChild(type);
551 CREATE_NODE(currentVar, -1, ASTNode::Kind::kVarDeclaration);
552 ASTNode::VarData vd(name, 0);
553 getNode(result).addChild(currentVar);
554 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
555 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
556 CREATE_EMPTY_CHILD(currentVar);
557 } else {
558 ASTNode::ID size = this->expression();
559 if (!size) {
560 return ASTNode::ID::Invalid();
561 }
562 getNode(currentVar).addChild(size);
563 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
564 return ASTNode::ID::Invalid();
565 }
566 }
567 ++vd.fSizeCount;
568 }
569 getNode(currentVar).setVarData(vd);
570 if (this->checkNext(Token::Kind::TK_EQ)) {
571 ASTNode::ID value = this->assignmentExpression();
572 if (!value) {
573 return ASTNode::ID::Invalid();
574 }
575 getNode(currentVar).addChild(value);
576 }
577 while (this->checkNext(Token::Kind::TK_COMMA)) {
578 Token name;
579 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
580 return ASTNode::ID::Invalid();
581 }
582 currentVar = ASTNode::ID(fFile->fNodes.size());
583 vd = ASTNode::VarData(this->text(name), 0);
584 fFile->fNodes.emplace_back(&fFile->fNodes, -1, ASTNode::Kind::kVarDeclaration);
585 getNode(result).addChild(currentVar);
586 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
587 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
588 CREATE_EMPTY_CHILD(currentVar);
589 } else {
590 ASTNode::ID size = this->expression();
591 if (!size) {
592 return ASTNode::ID::Invalid();
593 }
594 getNode(currentVar).addChild(size);
595 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
596 return ASTNode::ID::Invalid();
597 }
598 }
599 ++vd.fSizeCount;
600 }
601 getNode(currentVar).setVarData(vd);
602 if (this->checkNext(Token::Kind::TK_EQ)) {
603 ASTNode::ID value = this->assignmentExpression();
604 if (!value) {
605 return ASTNode::ID::Invalid();
606 }
607 getNode(currentVar).addChild(value);
608 }
609 }
610 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
611 return ASTNode::ID::Invalid();
612 }
613 return result;
614}
615
616/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
617ASTNode::ID Parser::parameter() {
618 Modifiers modifiers = this->modifiersWithDefaults(0);
619 ASTNode::ID type = this->type();
620 if (!type) {
621 return ASTNode::ID::Invalid();
622 }
623 Token name;
624 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
625 return ASTNode::ID::Invalid();
626 }
627 CREATE_NODE(result, name.fOffset, ASTNode::Kind::kParameter);
628 ASTNode::ParameterData pd(modifiers, this->text(name), 0);
629 getNode(result).addChild(type);
630 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
631 Token sizeToken;
632 if (!this->expect(Token::Kind::TK_INT_LITERAL, "a positive integer", &sizeToken)) {
633 return ASTNode::ID::Invalid();
634 }
635 CREATE_CHILD(child, result, sizeToken.fOffset, ASTNode::Kind::kInt,
636 SkSL::stoi(this->text(sizeToken)));
637 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
638 return ASTNode::ID::Invalid();
639 }
640 ++pd.fSizeCount;
641 }
642 getNode(result).setParameterData(pd);
643 return result;
644}
645
646/** EQ INT_LITERAL */
647int Parser::layoutInt() {
648 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
649 return -1;
650 }
651 Token resultToken;
652 if (this->expect(Token::Kind::TK_INT_LITERAL, "a non-negative integer", &resultToken)) {
653 return SkSL::stoi(this->text(resultToken));
654 }
655 return -1;
656}
657
658/** EQ IDENTIFIER */
659StringFragment Parser::layoutIdentifier() {
660 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
661 return StringFragment();
662 }
663 Token resultToken;
664 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &resultToken)) {
665 return StringFragment();
666 }
667 return this->text(resultToken);
668}
669
670
671/** EQ <any sequence of tokens with balanced parentheses and no top-level comma> */
672StringFragment Parser::layoutCode() {
673 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
674 return "";
675 }
676 Token start = this->nextRawToken();
677 this->pushback(start);
678 StringFragment code;
679 code.fChars = fText + start.fOffset;
680 int level = 1;
681 bool done = false;
682 while (!done) {
683 Token next = this->nextRawToken();
684 switch (next.fKind) {
685 case Token::Kind::TK_LPAREN:
686 ++level;
687 break;
688 case Token::Kind::TK_RPAREN:
689 --level;
690 break;
691 case Token::Kind::TK_COMMA:
692 if (level == 1) {
693 done = true;
694 }
695 break;
696 case Token::Kind::TK_END_OF_FILE:
697 this->error(start, "reached end of file while parsing layout");
698 return "";
699 default:
700 break;
701 }
702 if (!level) {
703 done = true;
704 }
705 if (done) {
706 code.fLength = next.fOffset - start.fOffset;
707 this->pushback(std::move(next));
708 }
709 }
710 return code;
711}
712
713/** (EQ IDENTIFIER('identity'))? */
714Layout::Key Parser::layoutKey() {
715 if (this->peek().fKind == Token::Kind::TK_EQ) {
716 this->expect(Token::Kind::TK_EQ, "'='");
717 Token key;
718 if (this->expect(Token::Kind::TK_IDENTIFIER, "an identifer", &key)) {
719 if (this->text(key) == "identity") {
720 return Layout::kIdentity_Key;
721 } else {
722 this->error(key, "unsupported layout key");
723 }
724 }
725 }
726 return Layout::kKey_Key;
727}
728
729Layout::CType Parser::layoutCType() {
730 if (this->expect(Token::Kind::TK_EQ, "'='")) {
731 Token t = this->nextToken();
732 String text = this->text(t);
733 auto found = layoutTokens->find(text);
734 if (found != layoutTokens->end()) {
735 switch (found->second) {
736 case LayoutToken::SKPMCOLOR4F:
737 return Layout::CType::kSkPMColor4f;
738 case LayoutToken::SKV4:
739 return Layout::CType::kSkV4;
740 case LayoutToken::SKRECT:
741 return Layout::CType::kSkRect;
742 case LayoutToken::SKIRECT:
743 return Layout::CType::kSkIRect;
744 case LayoutToken::SKPMCOLOR:
745 return Layout::CType::kSkPMColor;
746 case LayoutToken::BOOL:
747 return Layout::CType::kBool;
748 case LayoutToken::INT:
749 return Layout::CType::kInt32;
750 case LayoutToken::FLOAT:
751 return Layout::CType::kFloat;
752 case LayoutToken::SKM44:
753 return Layout::CType::kSkM44;
754 default:
755 break;
756 }
757 }
758 this->error(t, "unsupported ctype");
759 }
760 return Layout::CType::kDefault;
761}
762
763/* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
764Layout Parser::layout() {
765 int flags = 0;
766 int location = -1;
767 int offset = -1;
768 int binding = -1;
769 int index = -1;
770 int set = -1;
771 int builtin = -1;
772 int inputAttachmentIndex = -1;
773 Layout::Format format = Layout::Format::kUnspecified;
774 Layout::Primitive primitive = Layout::kUnspecified_Primitive;
775 int maxVertices = -1;
776 int invocations = -1;
777 StringFragment marker;
778 StringFragment when;
779 Layout::Key key = Layout::kNo_Key;
780 Layout::CType ctype = Layout::CType::kDefault;
781 if (this->checkNext(Token::Kind::TK_LAYOUT)) {
782 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
783 return Layout(flags, location, offset, binding, index, set, builtin,
784 inputAttachmentIndex, format, primitive, maxVertices, invocations, marker,
785 when, key, ctype);
786 }
787 for (;;) {
788 Token t = this->nextToken();
789 String text = this->text(t);
790 auto found = layoutTokens->find(text);
791 if (found != layoutTokens->end()) {
792 switch (found->second) {
793 case LayoutToken::LOCATION:
794 location = this->layoutInt();
795 break;
796 case LayoutToken::OFFSET:
797 offset = this->layoutInt();
798 break;
799 case LayoutToken::BINDING:
800 binding = this->layoutInt();
801 break;
802 case LayoutToken::INDEX:
803 index = this->layoutInt();
804 break;
805 case LayoutToken::SET:
806 set = this->layoutInt();
807 break;
808 case LayoutToken::BUILTIN:
809 builtin = this->layoutInt();
810 break;
811 case LayoutToken::INPUT_ATTACHMENT_INDEX:
812 inputAttachmentIndex = this->layoutInt();
813 break;
814 case LayoutToken::ORIGIN_UPPER_LEFT:
815 flags |= Layout::kOriginUpperLeft_Flag;
816 break;
817 case LayoutToken::OVERRIDE_COVERAGE:
818 flags |= Layout::kOverrideCoverage_Flag;
819 break;
820 case LayoutToken::BLEND_SUPPORT_ALL_EQUATIONS:
821 flags |= Layout::kBlendSupportAllEquations_Flag;
822 break;
823 case LayoutToken::BLEND_SUPPORT_MULTIPLY:
824 flags |= Layout::kBlendSupportMultiply_Flag;
825 break;
826 case LayoutToken::BLEND_SUPPORT_SCREEN:
827 flags |= Layout::kBlendSupportScreen_Flag;
828 break;
829 case LayoutToken::BLEND_SUPPORT_OVERLAY:
830 flags |= Layout::kBlendSupportOverlay_Flag;
831 break;
832 case LayoutToken::BLEND_SUPPORT_DARKEN:
833 flags |= Layout::kBlendSupportDarken_Flag;
834 break;
835 case LayoutToken::BLEND_SUPPORT_LIGHTEN:
836 flags |= Layout::kBlendSupportLighten_Flag;
837 break;
838 case LayoutToken::BLEND_SUPPORT_COLORDODGE:
839 flags |= Layout::kBlendSupportColorDodge_Flag;
840 break;
841 case LayoutToken::BLEND_SUPPORT_COLORBURN:
842 flags |= Layout::kBlendSupportColorBurn_Flag;
843 break;
844 case LayoutToken::BLEND_SUPPORT_HARDLIGHT:
845 flags |= Layout::kBlendSupportHardLight_Flag;
846 break;
847 case LayoutToken::BLEND_SUPPORT_SOFTLIGHT:
848 flags |= Layout::kBlendSupportSoftLight_Flag;
849 break;
850 case LayoutToken::BLEND_SUPPORT_DIFFERENCE:
851 flags |= Layout::kBlendSupportDifference_Flag;
852 break;
853 case LayoutToken::BLEND_SUPPORT_EXCLUSION:
854 flags |= Layout::kBlendSupportExclusion_Flag;
855 break;
856 case LayoutToken::BLEND_SUPPORT_HSL_HUE:
857 flags |= Layout::kBlendSupportHSLHue_Flag;
858 break;
859 case LayoutToken::BLEND_SUPPORT_HSL_SATURATION:
860 flags |= Layout::kBlendSupportHSLSaturation_Flag;
861 break;
862 case LayoutToken::BLEND_SUPPORT_HSL_COLOR:
863 flags |= Layout::kBlendSupportHSLColor_Flag;
864 break;
865 case LayoutToken::BLEND_SUPPORT_HSL_LUMINOSITY:
866 flags |= Layout::kBlendSupportHSLLuminosity_Flag;
867 break;
868 case LayoutToken::PUSH_CONSTANT:
869 flags |= Layout::kPushConstant_Flag;
870 break;
871 case LayoutToken::TRACKED:
872 flags |= Layout::kTracked_Flag;
873 break;
874 case LayoutToken::SRGB_UNPREMUL:
875 flags |= Layout::kSRGBUnpremul_Flag;
876 break;
877 case LayoutToken::POINTS:
878 primitive = Layout::kPoints_Primitive;
879 break;
880 case LayoutToken::LINES:
881 primitive = Layout::kLines_Primitive;
882 break;
883 case LayoutToken::LINE_STRIP:
884 primitive = Layout::kLineStrip_Primitive;
885 break;
886 case LayoutToken::LINES_ADJACENCY:
887 primitive = Layout::kLinesAdjacency_Primitive;
888 break;
889 case LayoutToken::TRIANGLES:
890 primitive = Layout::kTriangles_Primitive;
891 break;
892 case LayoutToken::TRIANGLE_STRIP:
893 primitive = Layout::kTriangleStrip_Primitive;
894 break;
895 case LayoutToken::TRIANGLES_ADJACENCY:
896 primitive = Layout::kTrianglesAdjacency_Primitive;
897 break;
898 case LayoutToken::MAX_VERTICES:
899 maxVertices = this->layoutInt();
900 break;
901 case LayoutToken::INVOCATIONS:
902 invocations = this->layoutInt();
903 break;
904 case LayoutToken::MARKER:
905 marker = this->layoutCode();
906 break;
907 case LayoutToken::WHEN:
908 when = this->layoutCode();
909 break;
910 case LayoutToken::KEY:
911 key = this->layoutKey();
912 break;
913 case LayoutToken::CTYPE:
914 ctype = this->layoutCType();
915 break;
916 default:
917 this->error(t, ("'" + text + "' is not a valid layout qualifier").c_str());
918 break;
919 }
920 } else if (Layout::ReadFormat(text, &format)) {
921 // AST::ReadFormat stored the result in 'format'.
922 } else {
923 this->error(t, ("'" + text + "' is not a valid layout qualifier").c_str());
924 }
925 if (this->checkNext(Token::Kind::TK_RPAREN)) {
926 break;
927 }
928 if (!this->expect(Token::Kind::TK_COMMA, "','")) {
929 break;
930 }
931 }
932 }
933 return Layout(flags, location, offset, binding, index, set, builtin, inputAttachmentIndex,
934 format, primitive, maxVertices, invocations, marker, when, key, ctype);
935}
936
937/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE |
938 READONLY | WRITEONLY | COHERENT | VOLATILE | RESTRICT | BUFFER | PLS | PLSIN |
939 PLSOUT | VARYING)* */
940Modifiers Parser::modifiers() {
941 Layout layout = this->layout();
942 int flags = 0;
943 for (;;) {
944 // TODO: handle duplicate / incompatible flags
945 switch (peek().fKind) {
946 case Token::Kind::TK_UNIFORM:
947 this->nextToken();
948 flags |= Modifiers::kUniform_Flag;
949 break;
950 case Token::Kind::TK_CONST:
951 this->nextToken();
952 flags |= Modifiers::kConst_Flag;
953 break;
954 case Token::Kind::TK_IN:
955 this->nextToken();
956 flags |= Modifiers::kIn_Flag;
957 break;
958 case Token::Kind::TK_OUT:
959 this->nextToken();
960 flags |= Modifiers::kOut_Flag;
961 break;
962 case Token::Kind::TK_INOUT:
963 this->nextToken();
964 flags |= Modifiers::kIn_Flag;
965 flags |= Modifiers::kOut_Flag;
966 break;
967 case Token::Kind::TK_FLAT:
968 this->nextToken();
969 flags |= Modifiers::kFlat_Flag;
970 break;
971 case Token::Kind::TK_NOPERSPECTIVE:
972 this->nextToken();
973 flags |= Modifiers::kNoPerspective_Flag;
974 break;
975 case Token::Kind::TK_READONLY:
976 this->nextToken();
977 flags |= Modifiers::kReadOnly_Flag;
978 break;
979 case Token::Kind::TK_WRITEONLY:
980 this->nextToken();
981 flags |= Modifiers::kWriteOnly_Flag;
982 break;
983 case Token::Kind::TK_COHERENT:
984 this->nextToken();
985 flags |= Modifiers::kCoherent_Flag;
986 break;
987 case Token::Kind::TK_VOLATILE:
988 this->nextToken();
989 flags |= Modifiers::kVolatile_Flag;
990 break;
991 case Token::Kind::TK_RESTRICT:
992 this->nextToken();
993 flags |= Modifiers::kRestrict_Flag;
994 break;
995 case Token::Kind::TK_BUFFER:
996 this->nextToken();
997 flags |= Modifiers::kBuffer_Flag;
998 break;
999 case Token::Kind::TK_HASSIDEEFFECTS:
1000 this->nextToken();
1001 flags |= Modifiers::kHasSideEffects_Flag;
1002 break;
1003 case Token::Kind::TK_PLS:
1004 this->nextToken();
1005 flags |= Modifiers::kPLS_Flag;
1006 break;
1007 case Token::Kind::TK_PLSIN:
1008 this->nextToken();
1009 flags |= Modifiers::kPLSIn_Flag;
1010 break;
1011 case Token::Kind::TK_PLSOUT:
1012 this->nextToken();
1013 flags |= Modifiers::kPLSOut_Flag;
1014 break;
1015 case Token::Kind::TK_VARYING:
1016 this->nextToken();
1017 flags |= Modifiers::kVarying_Flag;
1018 break;
1019 default:
1020 return Modifiers(layout, flags);
1021 }
1022 }
1023}
1024
1025Modifiers Parser::modifiersWithDefaults(int defaultFlags) {
1026 Modifiers result = this->modifiers();
1027 if (!result.fFlags) {
1028 return Modifiers(result.fLayout, defaultFlags);
1029 }
1030 return result;
1031}
1032
1033/* ifStatement | forStatement | doStatement | whileStatement | block | expression */
1034ASTNode::ID Parser::statement() {
1035 Token start = this->nextToken();
1036 AutoDepth depth(this);
1037 if (!depth.increase()) {
1038 return ASTNode::ID::Invalid();
1039 }
1040 this->pushback(start);
1041 switch (start.fKind) {
1042 case Token::Kind::TK_IF: // fall through
1043 case Token::Kind::TK_STATIC_IF:
1044 return this->ifStatement();
1045 case Token::Kind::TK_FOR:
1046 return this->forStatement();
1047 case Token::Kind::TK_DO:
1048 return this->doStatement();
1049 case Token::Kind::TK_WHILE:
1050 return this->whileStatement();
1051 case Token::Kind::TK_SWITCH: // fall through
1052 case Token::Kind::TK_STATIC_SWITCH:
1053 return this->switchStatement();
1054 case Token::Kind::TK_RETURN:
1055 return this->returnStatement();
1056 case Token::Kind::TK_BREAK:
1057 return this->breakStatement();
1058 case Token::Kind::TK_CONTINUE:
1059 return this->continueStatement();
1060 case Token::Kind::TK_DISCARD:
1061 return this->discardStatement();
1062 case Token::Kind::TK_LBRACE:
1063 return this->block();
1064 case Token::Kind::TK_SEMICOLON:
1065 this->nextToken();
1066 RETURN_NODE(start.fOffset, ASTNode::Kind::kBlock);
1067 case Token::Kind::TK_CONST:
1068 return this->varDeclarations();
1069 case Token::Kind::TK_IDENTIFIER:
1070 if (this->isType(this->text(start))) {
1071 return this->varDeclarations();
1072 }
1073 [[fallthrough]];
1074 default:
1075 return this->expressionStatement();
1076 }
1077}
1078
1079/* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* QUESTION? */
1080ASTNode::ID Parser::type() {
1081 Token type;
1082 if (!this->expect(Token::Kind::TK_IDENTIFIER, "a type", &type)) {
1083 return ASTNode::ID::Invalid();
1084 }
1085 if (!this->isType(this->text(type))) {
1086 this->error(type, ("no type named '" + this->text(type) + "'").c_str());
1087 return ASTNode::ID::Invalid();
1088 }
1089 CREATE_NODE(result, type.fOffset, ASTNode::Kind::kType);
1090 ASTNode::TypeData td(this->text(type), false, false);
1091 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
1092 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
1093 SKSL_INT i;
1094 if (this->intLiteral(&i)) {
1095 CREATE_CHILD(child, result, -1, ASTNode::Kind::kInt, i);
1096 } else {
1097 return ASTNode::ID::Invalid();
1098 }
1099 } else {
1100 CREATE_EMPTY_CHILD(result);
1101 }
1102 this->expect(Token::Kind::TK_RBRACKET, "']'");
1103 }
1104 td.fIsNullable = this->checkNext(Token::Kind::TK_QUESTION);
1105 getNode(result).setTypeData(td);
1106 return result;
1107}
1108
1109/* IDENTIFIER LBRACE
1110 varDeclaration+
1111 RBRACE (IDENTIFIER (LBRACKET expression? RBRACKET)*)? SEMICOLON */
1112ASTNode::ID Parser::interfaceBlock(Modifiers mods) {
1113 Token name;
1114 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
1115 return ASTNode::ID::Invalid();
1116 }
1117 if (peek().fKind != Token::Kind::TK_LBRACE) {
1118 // we only get into interfaceBlock if we found a top-level identifier which was not a type.
1119 // 99% of the time, the user was not actually intending to create an interface block, so
1120 // it's better to report it as an unknown type
1121 this->error(name, "no type named '" + this->text(name) + "'");
1122 return ASTNode::ID::Invalid();
1123 }
1124 CREATE_NODE(result, name.fOffset, ASTNode::Kind::kInterfaceBlock);
1125 ASTNode::InterfaceBlockData id(mods, this->text(name), 0, "", 0);
1126 this->nextToken();
1127 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
1128 ASTNode::ID decl = this->varDeclarations();
1129 if (!decl) {
1130 return ASTNode::ID::Invalid();
1131 }
1132 getNode(result).addChild(decl);
1133 ++id.fDeclarationCount;
1134 }
1135 if (id.fDeclarationCount == 0) {
1136 this->error(name, "interface block '" + this->text(name) +
1137 "' must contain at least one member");
1138 return ASTNode::ID::Invalid();
1139 }
1140 this->nextToken();
1141 std::vector<ASTNode> sizes;
1142 StringFragment instanceName;
1143 Token instanceNameToken;
1144 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &instanceNameToken)) {
1145 id.fInstanceName = this->text(instanceNameToken);
1146 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
1147 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
1148 ASTNode::ID size = this->expression();
1149 if (!size) {
1150 return ASTNode::ID::Invalid();
1151 }
1152 getNode(result).addChild(size);
1153 } else {
1154 CREATE_EMPTY_CHILD(result);
1155 }
1156 ++id.fSizeCount;
1157 this->expect(Token::Kind::TK_RBRACKET, "']'");
1158 }
1159 instanceName = this->text(instanceNameToken);
1160 }
1161 getNode(result).setInterfaceBlockData(id);
1162 this->expect(Token::Kind::TK_SEMICOLON, "';'");
1163 return result;
1164}
1165
1166/* IF LPAREN expression RPAREN statement (ELSE statement)? */
1167ASTNode::ID Parser::ifStatement() {
1168 Token start;
1169 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_IF, &start);
1170 if (!isStatic && !this->expect(Token::Kind::TK_IF, "'if'", &start)) {
1171 return ASTNode::ID::Invalid();
1172 }
1173 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kIf, isStatic);
1174 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1175 return ASTNode::ID::Invalid();
1176 }
1177 ASTNode::ID test = this->expression();
1178 if (!test) {
1179 return ASTNode::ID::Invalid();
1180 }
1181 getNode(result).addChild(test);
1182 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1183 return ASTNode::ID::Invalid();
1184 }
1185 ASTNode::ID ifTrue = this->statement();
1186 if (!ifTrue) {
1187 return ASTNode::ID::Invalid();
1188 }
1189 getNode(result).addChild(ifTrue);
1190 ASTNode::ID ifFalse;
1191 if (this->checkNext(Token::Kind::TK_ELSE)) {
1192 ifFalse = this->statement();
1193 if (!ifFalse) {
1194 return ASTNode::ID::Invalid();
1195 }
1196 getNode(result).addChild(ifFalse);
1197 }
1198 return result;
1199}
1200
1201/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
1202ASTNode::ID Parser::doStatement() {
1203 Token start;
1204 if (!this->expect(Token::Kind::TK_DO, "'do'", &start)) {
1205 return ASTNode::ID::Invalid();
1206 }
1207 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kDo);
1208 ASTNode::ID statement = this->statement();
1209 if (!statement) {
1210 return ASTNode::ID::Invalid();
1211 }
1212 getNode(result).addChild(statement);
1213 if (!this->expect(Token::Kind::TK_WHILE, "'while'")) {
1214 return ASTNode::ID::Invalid();
1215 }
1216 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1217 return ASTNode::ID::Invalid();
1218 }
1219 ASTNode::ID test = this->expression();
1220 if (!test) {
1221 return ASTNode::ID::Invalid();
1222 }
1223 getNode(result).addChild(test);
1224 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1225 return ASTNode::ID::Invalid();
1226 }
1227 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1228 return ASTNode::ID::Invalid();
1229 }
1230 return result;
1231}
1232
1233/* WHILE LPAREN expression RPAREN STATEMENT */
1234ASTNode::ID Parser::whileStatement() {
1235 Token start;
1236 if (!this->expect(Token::Kind::TK_WHILE, "'while'", &start)) {
1237 return ASTNode::ID::Invalid();
1238 }
1239 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1240 return ASTNode::ID::Invalid();
1241 }
1242 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kWhile);
1243 ASTNode::ID test = this->expression();
1244 if (!test) {
1245 return ASTNode::ID::Invalid();
1246 }
1247 getNode(result).addChild(test);
1248 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1249 return ASTNode::ID::Invalid();
1250 }
1251 ASTNode::ID statement = this->statement();
1252 if (!statement) {
1253 return ASTNode::ID::Invalid();
1254 }
1255 getNode(result).addChild(statement);
1256 return result;
1257}
1258
1259/* CASE expression COLON statement* */
1260ASTNode::ID Parser::switchCase() {
1261 Token start;
1262 if (!this->expect(Token::Kind::TK_CASE, "'case'", &start)) {
1263 return ASTNode::ID::Invalid();
1264 }
1265 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kSwitchCase);
1266 ASTNode::ID value = this->expression();
1267 if (!value) {
1268 return ASTNode::ID::Invalid();
1269 }
1270 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
1271 return ASTNode::ID::Invalid();
1272 }
1273 getNode(result).addChild(value);
1274 while (this->peek().fKind != Token::Kind::TK_RBRACE &&
1275 this->peek().fKind != Token::Kind::TK_CASE &&
1276 this->peek().fKind != Token::Kind::TK_DEFAULT) {
1277 ASTNode::ID s = this->statement();
1278 if (!s) {
1279 return ASTNode::ID::Invalid();
1280 }
1281 getNode(result).addChild(s);
1282 }
1283 return result;
1284}
1285
1286/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
1287ASTNode::ID Parser::switchStatement() {
1288 Token start;
1289 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_SWITCH, &start);
1290 if (!isStatic && !this->expect(Token::Kind::TK_SWITCH, "'switch'", &start)) {
1291 return ASTNode::ID::Invalid();
1292 }
1293 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1294 return ASTNode::ID::Invalid();
1295 }
1296 ASTNode::ID value = this->expression();
1297 if (!value) {
1298 return ASTNode::ID::Invalid();
1299 }
1300 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1301 return ASTNode::ID::Invalid();
1302 }
1303 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
1304 return ASTNode::ID::Invalid();
1305 }
1306 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kSwitch, isStatic);
1307 getNode(result).addChild(value);
1308 while (this->peek().fKind == Token::Kind::TK_CASE) {
1309 ASTNode::ID c = this->switchCase();
1310 if (!c) {
1311 return ASTNode::ID::Invalid();
1312 }
1313 getNode(result).addChild(c);
1314 }
1315 // Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
1316 // parts of the compiler may rely upon this assumption.
1317 if (this->peek().fKind == Token::Kind::TK_DEFAULT) {
1318 Token defaultStart;
1319 SkAssertResult(this->expect(Token::Kind::TK_DEFAULT, "'default'", &defaultStart));
1320 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
1321 return ASTNode::ID::Invalid();
1322 }
1323 CREATE_CHILD(defaultCase, result, defaultStart.fOffset, ASTNode::Kind::kSwitchCase);
1324 CREATE_EMPTY_CHILD(defaultCase); // empty test to signify default case
1325 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
1326 ASTNode::ID s = this->statement();
1327 if (!s) {
1328 return ASTNode::ID::Invalid();
1329 }
1330 getNode(defaultCase).addChild(s);
1331 }
1332 }
1333 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
1334 return ASTNode::ID::Invalid();
1335 }
1336 return result;
1337}
1338
1339/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
1340 STATEMENT */
1341ASTNode::ID Parser::forStatement() {
1342 Token start;
1343 if (!this->expect(Token::Kind::TK_FOR, "'for'", &start)) {
1344 return ASTNode::ID::Invalid();
1345 }
1346 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
1347 return ASTNode::ID::Invalid();
1348 }
1349 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kFor);
1350 ASTNode::ID initializer;
1351 Token nextToken = this->peek();
1352 switch (nextToken.fKind) {
1353 case Token::Kind::TK_SEMICOLON:
1354 this->nextToken();
1355 CREATE_EMPTY_CHILD(result);
1356 break;
1357 case Token::Kind::TK_CONST: {
1358 initializer = this->varDeclarations();
1359 if (!initializer) {
1360 return ASTNode::ID::Invalid();
1361 }
1362 getNode(result).addChild(initializer);
1363 break;
1364 }
1365 case Token::Kind::TK_IDENTIFIER: {
1366 if (this->isType(this->text(nextToken))) {
1367 initializer = this->varDeclarations();
1368 if (!initializer) {
1369 return ASTNode::ID::Invalid();
1370 }
1371 getNode(result).addChild(initializer);
1372 break;
1373 }
1374 [[fallthrough]];
1375 }
1376 default:
1377 initializer = this->expressionStatement();
1378 if (!initializer) {
1379 return ASTNode::ID::Invalid();
1380 }
1381 getNode(result).addChild(initializer);
1382 }
1383 ASTNode::ID test;
1384 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
1385 test = this->expression();
1386 if (!test) {
1387 return ASTNode::ID::Invalid();
1388 }
1389 getNode(result).addChild(test);
1390 } else {
1391 CREATE_EMPTY_CHILD(result);
1392 }
1393 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1394 return ASTNode::ID::Invalid();
1395 }
1396 ASTNode::ID next;
1397 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
1398 next = this->expression();
1399 if (!next) {
1400 return ASTNode::ID::Invalid();
1401 }
1402 getNode(result).addChild(next);
1403 } else {
1404 CREATE_EMPTY_CHILD(result);
1405 }
1406 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
1407 return ASTNode::ID::Invalid();
1408 }
1409 ASTNode::ID statement = this->statement();
1410 if (!statement) {
1411 return ASTNode::ID::Invalid();
1412 }
1413 getNode(result).addChild(statement);
1414 return result;
1415}
1416
1417/* RETURN expression? SEMICOLON */
1418ASTNode::ID Parser::returnStatement() {
1419 Token start;
1420 if (!this->expect(Token::Kind::TK_RETURN, "'return'", &start)) {
1421 return ASTNode::ID::Invalid();
1422 }
1423 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kReturn);
1424 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
1425 ASTNode::ID expression = this->expression();
1426 if (!expression) {
1427 return ASTNode::ID::Invalid();
1428 }
1429 getNode(result).addChild(expression);
1430 }
1431 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1432 return ASTNode::ID::Invalid();
1433 }
1434 return result;
1435}
1436
1437/* BREAK SEMICOLON */
1438ASTNode::ID Parser::breakStatement() {
1439 Token start;
1440 if (!this->expect(Token::Kind::TK_BREAK, "'break'", &start)) {
1441 return ASTNode::ID::Invalid();
1442 }
1443 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1444 return ASTNode::ID::Invalid();
1445 }
1446 RETURN_NODE(start.fOffset, ASTNode::Kind::kBreak);
1447}
1448
1449/* CONTINUE SEMICOLON */
1450ASTNode::ID Parser::continueStatement() {
1451 Token start;
1452 if (!this->expect(Token::Kind::TK_CONTINUE, "'continue'", &start)) {
1453 return ASTNode::ID::Invalid();
1454 }
1455 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1456 return ASTNode::ID::Invalid();
1457 }
1458 RETURN_NODE(start.fOffset, ASTNode::Kind::kContinue);
1459}
1460
1461/* DISCARD SEMICOLON */
1462ASTNode::ID Parser::discardStatement() {
1463 Token start;
1464 if (!this->expect(Token::Kind::TK_DISCARD, "'continue'", &start)) {
1465 return ASTNode::ID::Invalid();
1466 }
1467 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1468 return ASTNode::ID::Invalid();
1469 }
1470 RETURN_NODE(start.fOffset, ASTNode::Kind::kDiscard);
1471}
1472
1473/* LBRACE statement* RBRACE */
1474ASTNode::ID Parser::block() {
1475 Token start;
1476 if (!this->expect(Token::Kind::TK_LBRACE, "'{'", &start)) {
1477 return ASTNode::ID::Invalid();
1478 }
1479 AutoDepth depth(this);
1480 if (!depth.increase()) {
1481 return ASTNode::ID::Invalid();
1482 }
1483 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kBlock);
1484 for (;;) {
1485 switch (this->peek().fKind) {
1486 case Token::Kind::TK_RBRACE:
1487 this->nextToken();
1488 return result;
1489 case Token::Kind::TK_END_OF_FILE:
1490 this->error(this->peek(), "expected '}', but found end of file");
1491 return ASTNode::ID::Invalid();
1492 default: {
1493 ASTNode::ID statement = this->statement();
1494 if (!statement) {
1495 return ASTNode::ID::Invalid();
1496 }
1497 getNode(result).addChild(statement);
1498 }
1499 }
1500 }
1501 return result;
1502}
1503
1504/* expression SEMICOLON */
1505ASTNode::ID Parser::expressionStatement() {
1506 ASTNode::ID expr = this->expression();
1507 if (expr) {
1508 if (this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
1509 return expr;
1510 }
1511 }
1512 return ASTNode::ID::Invalid();
1513}
1514
1515/* assignmentExpression (COMMA assignmentExpression)* */
1516ASTNode::ID Parser::expression() {
1517 ASTNode::ID result = this->assignmentExpression();
1518 if (!result) {
1519 return ASTNode::ID::Invalid();
1520 }
1521 Token t;
1522 AutoDepth depth(this);
1523 while (this->checkNext(Token::Kind::TK_COMMA, &t)) {
1524 if (!depth.increase()) {
1525 return ASTNode::ID::Invalid();
1526 }
1527 ASTNode::ID right = this->assignmentExpression();
1528 if (!right) {
1529 return ASTNode::ID::Invalid();
1530 }
1531 CREATE_NODE(newResult, t.fOffset, ASTNode::Kind::kBinary, std::move(t));
1532 getNode(newResult).addChild(result);
1533 getNode(newResult).addChild(right);
1534 result = newResult;
1535 }
1536 return result;
1537}
1538
1539/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1540 BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1541 assignmentExpression)*
1542 */
1543ASTNode::ID Parser::assignmentExpression() {
1544 AutoDepth depth(this);
1545 ASTNode::ID result = this->ternaryExpression();
1546 if (!result) {
1547 return ASTNode::ID::Invalid();
1548 }
1549 for (;;) {
1550 switch (this->peek().fKind) {
1551 case Token::Kind::TK_EQ: // fall through
1552 case Token::Kind::TK_STAREQ: // fall through
1553 case Token::Kind::TK_SLASHEQ: // fall through
1554 case Token::Kind::TK_PERCENTEQ: // fall through
1555 case Token::Kind::TK_PLUSEQ: // fall through
1556 case Token::Kind::TK_MINUSEQ: // fall through
1557 case Token::Kind::TK_SHLEQ: // fall through
1558 case Token::Kind::TK_SHREQ: // fall through
1559 case Token::Kind::TK_BITWISEANDEQ: // fall through
1560 case Token::Kind::TK_BITWISEXOREQ: // fall through
1561 case Token::Kind::TK_BITWISEOREQ: // fall through
1562 case Token::Kind::TK_LOGICALANDEQ: // fall through
1563 case Token::Kind::TK_LOGICALXOREQ: // fall through
1564 case Token::Kind::TK_LOGICALOREQ: {
1565 if (!depth.increase()) {
1566 return ASTNode::ID::Invalid();
1567 }
1568 Token t = this->nextToken();
1569 ASTNode::ID right = this->assignmentExpression();
1570 if (!right) {
1571 return ASTNode::ID::Invalid();
1572 }
1573 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1574 std::move(t));
1575 getNode(newResult).addChild(result);
1576 getNode(newResult).addChild(right);
1577 result = newResult;
1578 break;
1579 }
1580 default:
1581 return result;
1582 }
1583 }
1584}
1585
1586/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
1587ASTNode::ID Parser::ternaryExpression() {
1588 AutoDepth depth(this);
1589 ASTNode::ID base = this->logicalOrExpression();
1590 if (!base) {
1591 return ASTNode::ID::Invalid();
1592 }
1593 if (this->checkNext(Token::Kind::TK_QUESTION)) {
1594 if (!depth.increase()) {
1595 return ASTNode::ID::Invalid();
1596 }
1597 ASTNode::ID trueExpr = this->expression();
1598 if (!trueExpr) {
1599 return ASTNode::ID::Invalid();
1600 }
1601 if (this->expect(Token::Kind::TK_COLON, "':'")) {
1602 ASTNode::ID falseExpr = this->assignmentExpression();
1603 if (!falseExpr) {
1604 return ASTNode::ID::Invalid();
1605 }
1606 CREATE_NODE(ternary, getNode(base).fOffset, ASTNode::Kind::kTernary);
1607 getNode(ternary).addChild(base);
1608 getNode(ternary).addChild(trueExpr);
1609 getNode(ternary).addChild(falseExpr);
1610 return ternary;
1611 }
1612 return ASTNode::ID::Invalid();
1613 }
1614 return base;
1615}
1616
1617/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
1618ASTNode::ID Parser::logicalOrExpression() {
1619 AutoDepth depth(this);
1620 ASTNode::ID result = this->logicalXorExpression();
1621 if (!result) {
1622 return ASTNode::ID::Invalid();
1623 }
1624 Token t;
1625 while (this->checkNext(Token::Kind::TK_LOGICALOR, &t)) {
1626 if (!depth.increase()) {
1627 return ASTNode::ID::Invalid();
1628 }
1629 ASTNode::ID right = this->logicalXorExpression();
1630 if (!right) {
1631 return ASTNode::ID::Invalid();
1632 }
1633 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1634 getNode(newResult).addChild(result);
1635 getNode(newResult).addChild(right);
1636 result = newResult;
1637 }
1638 return result;
1639}
1640
1641/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
1642ASTNode::ID Parser::logicalXorExpression() {
1643 AutoDepth depth(this);
1644 ASTNode::ID result = this->logicalAndExpression();
1645 if (!result) {
1646 return ASTNode::ID::Invalid();
1647 }
1648 Token t;
1649 while (this->checkNext(Token::Kind::TK_LOGICALXOR, &t)) {
1650 if (!depth.increase()) {
1651 return ASTNode::ID::Invalid();
1652 }
1653 ASTNode::ID right = this->logicalAndExpression();
1654 if (!right) {
1655 return ASTNode::ID::Invalid();
1656 }
1657 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1658 getNode(newResult).addChild(result);
1659 getNode(newResult).addChild(right);
1660 result = newResult;
1661 }
1662 return result;
1663}
1664
1665/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
1666ASTNode::ID Parser::logicalAndExpression() {
1667 AutoDepth depth(this);
1668 ASTNode::ID result = this->bitwiseOrExpression();
1669 if (!result) {
1670 return ASTNode::ID::Invalid();
1671 }
1672 Token t;
1673 while (this->checkNext(Token::Kind::TK_LOGICALAND, &t)) {
1674 if (!depth.increase()) {
1675 return ASTNode::ID::Invalid();
1676 }
1677 ASTNode::ID right = this->bitwiseOrExpression();
1678 if (!right) {
1679 return ASTNode::ID::Invalid();
1680 }
1681 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1682 getNode(newResult).addChild(result);
1683 getNode(newResult).addChild(right);
1684 result = newResult;
1685 }
1686 return result;
1687}
1688
1689/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
1690ASTNode::ID Parser::bitwiseOrExpression() {
1691 AutoDepth depth(this);
1692 ASTNode::ID result = this->bitwiseXorExpression();
1693 if (!result) {
1694 return ASTNode::ID::Invalid();
1695 }
1696 Token t;
1697 while (this->checkNext(Token::Kind::TK_BITWISEOR, &t)) {
1698 if (!depth.increase()) {
1699 return ASTNode::ID::Invalid();
1700 }
1701 ASTNode::ID right = this->bitwiseXorExpression();
1702 if (!right) {
1703 return ASTNode::ID::Invalid();
1704 }
1705 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1706 getNode(newResult).addChild(result);
1707 getNode(newResult).addChild(right);
1708 result = newResult;
1709 }
1710 return result;
1711}
1712
1713/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
1714ASTNode::ID Parser::bitwiseXorExpression() {
1715 AutoDepth depth(this);
1716 ASTNode::ID result = this->bitwiseAndExpression();
1717 if (!result) {
1718 return ASTNode::ID::Invalid();
1719 }
1720 Token t;
1721 while (this->checkNext(Token::Kind::TK_BITWISEXOR, &t)) {
1722 if (!depth.increase()) {
1723 return ASTNode::ID::Invalid();
1724 }
1725 ASTNode::ID right = this->bitwiseAndExpression();
1726 if (!right) {
1727 return ASTNode::ID::Invalid();
1728 }
1729 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1730 getNode(newResult).addChild(result);
1731 getNode(newResult).addChild(right);
1732 result = newResult;
1733 }
1734 return result;
1735}
1736
1737/* equalityExpression (BITWISEAND equalityExpression)* */
1738ASTNode::ID Parser::bitwiseAndExpression() {
1739 AutoDepth depth(this);
1740 ASTNode::ID result = this->equalityExpression();
1741 if (!result) {
1742 return ASTNode::ID::Invalid();
1743 }
1744 Token t;
1745 while (this->checkNext(Token::Kind::TK_BITWISEAND, &t)) {
1746 if (!depth.increase()) {
1747 return ASTNode::ID::Invalid();
1748 }
1749 ASTNode::ID right = this->equalityExpression();
1750 if (!right) {
1751 return ASTNode::ID::Invalid();
1752 }
1753 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1754 getNode(newResult).addChild(result);
1755 getNode(newResult).addChild(right);
1756 result = newResult;
1757 }
1758 return result;
1759}
1760
1761/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
1762ASTNode::ID Parser::equalityExpression() {
1763 AutoDepth depth(this);
1764 ASTNode::ID result = this->relationalExpression();
1765 if (!result) {
1766 return ASTNode::ID::Invalid();
1767 }
1768 for (;;) {
1769 switch (this->peek().fKind) {
1770 case Token::Kind::TK_EQEQ: // fall through
1771 case Token::Kind::TK_NEQ: {
1772 if (!depth.increase()) {
1773 return ASTNode::ID::Invalid();
1774 }
1775 Token t = this->nextToken();
1776 ASTNode::ID right = this->relationalExpression();
1777 if (!right) {
1778 return ASTNode::ID::Invalid();
1779 }
1780 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1781 std::move(t));
1782 getNode(newResult).addChild(result);
1783 getNode(newResult).addChild(right);
1784 result = newResult;
1785 break;
1786 }
1787 default:
1788 return result;
1789 }
1790 }
1791}
1792
1793/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
1794ASTNode::ID Parser::relationalExpression() {
1795 AutoDepth depth(this);
1796 ASTNode::ID result = this->shiftExpression();
1797 if (!result) {
1798 return ASTNode::ID::Invalid();
1799 }
1800 for (;;) {
1801 switch (this->peek().fKind) {
1802 case Token::Kind::TK_LT: // fall through
1803 case Token::Kind::TK_GT: // fall through
1804 case Token::Kind::TK_LTEQ: // fall through
1805 case Token::Kind::TK_GTEQ: {
1806 if (!depth.increase()) {
1807 return ASTNode::ID::Invalid();
1808 }
1809 Token t = this->nextToken();
1810 ASTNode::ID right = this->shiftExpression();
1811 if (!right) {
1812 return ASTNode::ID::Invalid();
1813 }
1814 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1815 std::move(t));
1816 getNode(newResult).addChild(result);
1817 getNode(newResult).addChild(right);
1818 result = newResult;
1819 break;
1820 }
1821 default:
1822 return result;
1823 }
1824 }
1825}
1826
1827/* additiveExpression ((SHL | SHR) additiveExpression)* */
1828ASTNode::ID Parser::shiftExpression() {
1829 AutoDepth depth(this);
1830 ASTNode::ID result = this->additiveExpression();
1831 if (!result) {
1832 return ASTNode::ID::Invalid();
1833 }
1834 for (;;) {
1835 switch (this->peek().fKind) {
1836 case Token::Kind::TK_SHL: // fall through
1837 case Token::Kind::TK_SHR: {
1838 if (!depth.increase()) {
1839 return ASTNode::ID::Invalid();
1840 }
1841 Token t = this->nextToken();
1842 ASTNode::ID right = this->additiveExpression();
1843 if (!right) {
1844 return ASTNode::ID::Invalid();
1845 }
1846 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1847 std::move(t));
1848 getNode(newResult).addChild(result);
1849 getNode(newResult).addChild(right);
1850 result = newResult;
1851 break;
1852 }
1853 default:
1854 return result;
1855 }
1856 }
1857}
1858
1859/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
1860ASTNode::ID Parser::additiveExpression() {
1861 AutoDepth depth(this);
1862 ASTNode::ID result = this->multiplicativeExpression();
1863 if (!result) {
1864 return ASTNode::ID::Invalid();
1865 }
1866 for (;;) {
1867 switch (this->peek().fKind) {
1868 case Token::Kind::TK_PLUS: // fall through
1869 case Token::Kind::TK_MINUS: {
1870 if (!depth.increase()) {
1871 return ASTNode::ID::Invalid();
1872 }
1873 Token t = this->nextToken();
1874 ASTNode::ID right = this->multiplicativeExpression();
1875 if (!right) {
1876 return ASTNode::ID::Invalid();
1877 }
1878 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1879 std::move(t));
1880 getNode(newResult).addChild(result);
1881 getNode(newResult).addChild(right);
1882 result = newResult;
1883 break;
1884 }
1885 default:
1886 return result;
1887 }
1888 }
1889}
1890
1891/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
1892ASTNode::ID Parser::multiplicativeExpression() {
1893 AutoDepth depth(this);
1894 ASTNode::ID result = this->unaryExpression();
1895 if (!result) {
1896 return ASTNode::ID::Invalid();
1897 }
1898 for (;;) {
1899 switch (this->peek().fKind) {
1900 case Token::Kind::TK_STAR: // fall through
1901 case Token::Kind::TK_SLASH: // fall through
1902 case Token::Kind::TK_PERCENT: {
1903 if (!depth.increase()) {
1904 return ASTNode::ID::Invalid();
1905 }
1906 Token t = this->nextToken();
1907 ASTNode::ID right = this->unaryExpression();
1908 if (!right) {
1909 return ASTNode::ID::Invalid();
1910 }
1911 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1912 std::move(t));
1913 getNode(newResult).addChild(result);
1914 getNode(newResult).addChild(right);
1915 result = newResult;
1916 break;
1917 }
1918 default:
1919 return result;
1920 }
1921 }
1922}
1923
1924/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
1925ASTNode::ID Parser::unaryExpression() {
1926 AutoDepth depth(this);
1927 switch (this->peek().fKind) {
1928 case Token::Kind::TK_PLUS: // fall through
1929 case Token::Kind::TK_MINUS: // fall through
1930 case Token::Kind::TK_LOGICALNOT: // fall through
1931 case Token::Kind::TK_BITWISENOT: // fall through
1932 case Token::Kind::TK_PLUSPLUS: // fall through
1933 case Token::Kind::TK_MINUSMINUS: {
1934 if (!depth.increase()) {
1935 return ASTNode::ID::Invalid();
1936 }
1937 Token t = this->nextToken();
1938 ASTNode::ID expr = this->unaryExpression();
1939 if (!expr) {
1940 return ASTNode::ID::Invalid();
1941 }
1942 CREATE_NODE(result, t.fOffset, ASTNode::Kind::kPrefix, std::move(t));
1943 getNode(result).addChild(expr);
1944 return result;
1945 }
1946 default:
1947 return this->postfixExpression();
1948 }
1949}
1950
1951/* term suffix* */
1952ASTNode::ID Parser::postfixExpression() {
1953 AutoDepth depth(this);
1954 ASTNode::ID result = this->term();
1955 if (!result) {
1956 return ASTNode::ID::Invalid();
1957 }
1958 for (;;) {
1959 Token t = this->peek();
1960 switch (t.fKind) {
1961 case Token::Kind::TK_FLOAT_LITERAL:
1962 if (this->text(t)[0] != '.') {
1963 return result;
1964 }
1965 [[fallthrough]];
1966 case Token::Kind::TK_LBRACKET:
1967 case Token::Kind::TK_DOT:
1968 case Token::Kind::TK_LPAREN:
1969 case Token::Kind::TK_PLUSPLUS:
1970 case Token::Kind::TK_MINUSMINUS:
1971 case Token::Kind::TK_COLONCOLON:
1972 if (!depth.increase()) {
1973 return ASTNode::ID::Invalid();
1974 }
1975 result = this->suffix(result);
1976 if (!result) {
1977 return ASTNode::ID::Invalid();
1978 }
1979 break;
1980 default:
1981 return result;
1982 }
1983 }
1984}
1985
1986/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
1987 PLUSPLUS | MINUSMINUS | COLONCOLON IDENTIFIER | FLOAT_LITERAL [IDENTIFIER] */
1988ASTNode::ID Parser::suffix(ASTNode::ID base) {
1989 SkASSERT(base);
1990 Token next = this->nextToken();
1991 AutoDepth depth(this);
1992 if (!depth.increase()) {
1993 return ASTNode::ID::Invalid();
1994 }
1995 switch (next.fKind) {
1996 case Token::Kind::TK_LBRACKET: {
1997 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
1998 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kIndex);
1999 getNode(result).addChild(base);
2000 return result;
2001 }
2002 ASTNode::ID e = this->expression();
2003 if (!e) {
2004 return ASTNode::ID::Invalid();
2005 }
2006 this->expect(Token::Kind::TK_RBRACKET, "']' to complete array access expression");
2007 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kIndex);
2008 getNode(result).addChild(base);
2009 getNode(result).addChild(e);
2010 return result;
2011 }
2012 case Token::Kind::TK_DOT: // fall through
2013 case Token::Kind::TK_COLONCOLON: {
2014 int offset = this->peek().fOffset;
2015 StringFragment text;
2016 if (this->identifier(&text)) {
2017 CREATE_NODE(result, offset, ASTNode::Kind::kField, std::move(text));
2018 getNode(result).addChild(base);
2019 return result;
2020 }
2021 [[fallthrough]]; // FIXME(ethannicholas)
2022 }
2023 case Token::Kind::TK_FLOAT_LITERAL: {
2024 // Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
2025 // floating point literals, possibly followed by an identifier. Handle that here.
2026 StringFragment field = this->text(next);
2027 SkASSERT(field.fChars[0] == '.');
2028 ++field.fChars;
2029 --field.fLength;
2030 for (size_t i = 0; i < field.fLength; ++i) {
2031 if (field.fChars[i] != '0' && field.fChars[i] != '1') {
2032 this->error(next, "invalid swizzle");
2033 return ASTNode::ID::Invalid();
2034 }
2035 }
2036 // use the next *raw* token so we don't ignore whitespace - we only care about
2037 // identifiers that directly follow the float
2038 Token id = this->nextRawToken();
2039 if (id.fKind == Token::Kind::TK_IDENTIFIER) {
2040 field.fLength += id.fLength;
2041 } else {
2042 this->pushback(id);
2043 }
2044 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kField, field);
2045 getNode(result).addChild(base);
2046 return result;
2047 }
2048 case Token::Kind::TK_LPAREN: {
2049 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kCall);
2050 getNode(result).addChild(base);
2051 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
2052 for (;;) {
2053 ASTNode::ID expr = this->assignmentExpression();
2054 if (!expr) {
2055 return ASTNode::ID::Invalid();
2056 }
2057 getNode(result).addChild(expr);
2058 if (!this->checkNext(Token::Kind::TK_COMMA)) {
2059 break;
2060 }
2061 }
2062 }
2063 this->expect(Token::Kind::TK_RPAREN, "')' to complete function parameters");
2064 return result;
2065 }
2066 case Token::Kind::TK_PLUSPLUS: // fall through
2067 case Token::Kind::TK_MINUSMINUS: {
2068 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kPostfix, next);
2069 getNode(result).addChild(base);
2070 return result;
2071 }
2072 default: {
2073 this->error(next, "expected expression suffix, but found '" + this->text(next) + "'");
2074 return ASTNode::ID::Invalid();
2075 }
2076 }
2077}
2078
2079/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | NULL_LITERAL | '(' expression ')' */
2080ASTNode::ID Parser::term() {
2081 Token t = this->peek();
2082 switch (t.fKind) {
2083 case Token::Kind::TK_IDENTIFIER: {
2084 StringFragment text;
2085 if (this->identifier(&text)) {
2086 RETURN_NODE(t.fOffset, ASTNode::Kind::kIdentifier, std::move(text));
2087 }
2088 break;
2089 }
2090 case Token::Kind::TK_INT_LITERAL: {
2091 SKSL_INT i;
2092 if (this->intLiteral(&i)) {
2093 RETURN_NODE(t.fOffset, ASTNode::Kind::kInt, i);
2094 }
2095 break;
2096 }
2097 case Token::Kind::TK_FLOAT_LITERAL: {
2098 SKSL_FLOAT f;
2099 if (this->floatLiteral(&f)) {
2100 RETURN_NODE(t.fOffset, ASTNode::Kind::kFloat, f);
2101 }
2102 break;
2103 }
2104 case Token::Kind::TK_TRUE_LITERAL: // fall through
2105 case Token::Kind::TK_FALSE_LITERAL: {
2106 bool b;
2107 if (this->boolLiteral(&b)) {
2108 RETURN_NODE(t.fOffset, ASTNode::Kind::kBool, b);
2109 }
2110 break;
2111 }
2112 case Token::Kind::TK_NULL_LITERAL:
2113 this->nextToken();
2114 RETURN_NODE(t.fOffset, ASTNode::Kind::kNull);
2115 case Token::Kind::TK_LPAREN: {
2116 this->nextToken();
2117 AutoDepth depth(this);
2118 if (!depth.increase()) {
2119 return ASTNode::ID::Invalid();
2120 }
2121 ASTNode::ID result = this->expression();
2122 if (result) {
2123 this->expect(Token::Kind::TK_RPAREN, "')' to complete expression");
2124 return result;
2125 }
2126 break;
2127 }
2128 default:
2129 this->nextToken();
2130 this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'");
2131 }
2132 return ASTNode::ID::Invalid();
2133}
2134
2135/* INT_LITERAL */
2136bool Parser::intLiteral(SKSL_INT* dest) {
2137 Token t;
2138 if (this->expect(Token::Kind::TK_INT_LITERAL, "integer literal", &t)) {
2139 *dest = SkSL::stol(this->text(t));
2140 return true;
2141 }
2142 return false;
2143}
2144
2145/* FLOAT_LITERAL */
2146bool Parser::floatLiteral(SKSL_FLOAT* dest) {
2147 Token t;
2148 if (this->expect(Token::Kind::TK_FLOAT_LITERAL, "float literal", &t)) {
2149 *dest = SkSL::stod(this->text(t));
2150 return true;
2151 }
2152 return false;
2153}
2154
2155/* TRUE_LITERAL | FALSE_LITERAL */
2156bool Parser::boolLiteral(bool* dest) {
2157 Token t = this->nextToken();
2158 switch (t.fKind) {
2159 case Token::Kind::TK_TRUE_LITERAL:
2160 *dest = true;
2161 return true;
2162 case Token::Kind::TK_FALSE_LITERAL:
2163 *dest = false;
2164 return true;
2165 default:
2166 this->error(t, "expected 'true' or 'false', but found '" + this->text(t) + "'");
2167 return false;
2168 }
2169}
2170
2171/* IDENTIFIER */
2172bool Parser::identifier(StringFragment* dest) {
2173 Token t;
2174 if (this->expect(Token::Kind::TK_IDENTIFIER, "identifier", &t)) {
2175 *dest = this->text(t);
2176 return true;
2177 }
2178 return false;
2179}
2180
2181} // namespace SkSL
2182