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