• 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 "SkSLParser.h"
10 #include "SkSLToken.h"
11 
12 #define register
13 #include "disable_flex_warnings.h"
14 #include "lex.sksl.c"
15 static_assert(YY_FLEX_MAJOR_VERSION * 10000 + YY_FLEX_MINOR_VERSION * 100 +
16               YY_FLEX_SUBMINOR_VERSION >= 20601,
17               "we require Flex 2.6.1 or better for security reasons");
18 #undef register
19 #ifdef __clang__
20 #pragma clang diagnostic pop
21 #endif
22 #ifdef __GNUC__
23 #pragma GCC diagnostic pop
24 #endif
25 #ifdef _MSC_VER
26 #pragma warning(pop)
27 #endif
28 
29 #include "lex.layout.h"
30 #include "ast/SkSLASTBinaryExpression.h"
31 #include "ast/SkSLASTBlock.h"
32 #include "ast/SkSLASTBoolLiteral.h"
33 #include "ast/SkSLASTBreakStatement.h"
34 #include "ast/SkSLASTCallSuffix.h"
35 #include "ast/SkSLASTContinueStatement.h"
36 #include "ast/SkSLASTDiscardStatement.h"
37 #include "ast/SkSLASTDoStatement.h"
38 #include "ast/SkSLASTExpression.h"
39 #include "ast/SkSLASTExpressionStatement.h"
40 #include "ast/SkSLASTExtension.h"
41 #include "ast/SkSLASTFieldSuffix.h"
42 #include "ast/SkSLASTFloatLiteral.h"
43 #include "ast/SkSLASTForStatement.h"
44 #include "ast/SkSLASTFunction.h"
45 #include "ast/SkSLASTIdentifier.h"
46 #include "ast/SkSLASTIfStatement.h"
47 #include "ast/SkSLASTIndexSuffix.h"
48 #include "ast/SkSLASTInterfaceBlock.h"
49 #include "ast/SkSLASTIntLiteral.h"
50 #include "ast/SkSLASTModifiersDeclaration.h"
51 #include "ast/SkSLASTParameter.h"
52 #include "ast/SkSLASTPrecision.h"
53 #include "ast/SkSLASTPrefixExpression.h"
54 #include "ast/SkSLASTReturnStatement.h"
55 #include "ast/SkSLASTSection.h"
56 #include "ast/SkSLASTStatement.h"
57 #include "ast/SkSLASTSuffixExpression.h"
58 #include "ast/SkSLASTSwitchCase.h"
59 #include "ast/SkSLASTSwitchStatement.h"
60 #include "ast/SkSLASTTernaryExpression.h"
61 #include "ast/SkSLASTType.h"
62 #include "ast/SkSLASTVarDeclaration.h"
63 #include "ast/SkSLASTVarDeclarationStatement.h"
64 #include "ast/SkSLASTWhileStatement.h"
65 #include "ir/SkSLSymbolTable.h"
66 #include "ir/SkSLModifiers.h"
67 #include "ir/SkSLType.h"
68 
69 namespace SkSL {
70 
71 #define MAX_PARSE_DEPTH 50
72 
73 class AutoDepth {
74 public:
AutoDepth(Parser * p)75     AutoDepth(Parser* p)
76     : fParser(p) {
77         fParser->fDepth++;
78     }
79 
~AutoDepth()80     ~AutoDepth() {
81         fParser->fDepth--;
82     }
83 
checkValid()84     bool checkValid() {
85         if (fParser->fDepth > MAX_PARSE_DEPTH) {
86             fParser->error(fParser->peek().fPosition, String("exceeded max parse depth"));
87             return false;
88         }
89         return true;
90     }
91 
92 private:
93     Parser* fParser;
94 };
95 
Parser(String text,SymbolTable & types,ErrorReporter & errors)96 Parser::Parser(String text, SymbolTable& types, ErrorReporter& errors)
97 : fPushback(Position(-1, -1), Token::INVALID_TOKEN, String())
98 , fTypes(types)
99 , fErrors(errors) {
100     sksllex_init(&fScanner);
101     layoutlex_init(&fLayoutScanner);
102     fBuffer = sksl_scan_string(text.c_str(), fScanner);
103     skslset_lineno(1, fScanner);
104 }
105 
~Parser()106 Parser::~Parser() {
107     sksl_delete_buffer(fBuffer, fScanner);
108     sksllex_destroy(fScanner);
109     layoutlex_destroy(fLayoutScanner);
110 }
111 
112 /* (precision | directive | section | declaration)* END_OF_FILE */
file()113 std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
114     std::vector<std::unique_ptr<ASTDeclaration>> result;
115     for (;;) {
116         switch (this->peek().fKind) {
117             case Token::END_OF_FILE:
118                 return result;
119             case Token::PRECISION: {
120                 std::unique_ptr<ASTDeclaration> precision = this->precision();
121                 if (precision) {
122                     result.push_back(std::move(precision));
123                 }
124                 break;
125             }
126             case Token::DIRECTIVE: {
127                 std::unique_ptr<ASTDeclaration> decl = this->directive();
128                 if (decl) {
129                     result.push_back(std::move(decl));
130                 }
131                 break;
132             }
133             case Token::SECTION: {
134                 std::unique_ptr<ASTDeclaration> section = this->section();
135                 if (section) {
136                     result.push_back(std::move(section));
137                 }
138                 break;
139             }
140             default: {
141                 std::unique_ptr<ASTDeclaration> decl = this->declaration();
142                 if (!decl) {
143                     continue;
144                 }
145                 result.push_back(std::move(decl));
146             }
147         }
148     }
149 }
150 
nextRawToken()151 Token Parser::nextRawToken() {
152     if (fPushback.fKind != Token::INVALID_TOKEN) {
153         Token result = fPushback;
154         fPushback.fKind = Token::INVALID_TOKEN;
155         fPushback.fText = "";
156         return result;
157     }
158     int token = sksllex(fScanner);
159     return Token(Position(skslget_lineno(fScanner), -1), (Token::Kind) token,
160                  String(skslget_text(fScanner)));
161 }
162 
nextToken()163 Token Parser::nextToken() {
164     Token token;
165     do {
166         token = this->nextRawToken();
167     } while (token.fKind == Token::WHITESPACE);
168     return token;
169 }
170 
pushback(Token t)171 void Parser::pushback(Token t) {
172     ASSERT(fPushback.fKind == Token::INVALID_TOKEN);
173     fPushback = t;
174 }
175 
peek()176 Token Parser::peek() {
177     fPushback = this->nextToken();
178     return fPushback;
179 }
180 
checkNext(Token::Kind kind,Token * result)181 bool Parser::checkNext(Token::Kind kind, Token* result) {
182     Token next = this->nextToken();
183     if (next.fKind == kind) {
184         if (result) {
185             *result = next;
186         }
187         return true;
188     }
189     this->pushback(next);
190     return false;
191 }
192 
expect(Token::Kind kind,const char * expected,Token * result)193 bool Parser::expect(Token::Kind kind, const char* expected, Token* result) {
194     return this->expect(kind, String(expected), result);
195 }
196 
expect(Token::Kind kind,String expected,Token * result)197 bool Parser::expect(Token::Kind kind, String expected, Token* result) {
198     Token next = this->nextToken();
199     if (next.fKind == kind) {
200         if (result) {
201             *result = next;
202         }
203         return true;
204     } else {
205         if (next.fText.size()) {
206             this->error(next.fPosition, "expected " + expected + ", but found '" + next.fText +
207                                         "'");
208         } else {
209             this->error(next.fPosition, "parse error, recompile in debug mode for details");
210         }
211         return false;
212     }
213 }
214 
error(Position p,const char * msg)215 void Parser::error(Position p, const char* msg) {
216     this->error(p, String(msg));
217 }
218 
error(Position p,String msg)219 void Parser::error(Position p, String msg) {
220     fErrors.error(p, msg);
221 }
222 
isType(String name)223 bool Parser::isType(String name) {
224     return nullptr != fTypes[name];
225 }
226 
227 /* PRECISION (LOWP | MEDIUMP | HIGHP) type SEMICOLON */
precision()228 std::unique_ptr<ASTDeclaration> Parser::precision() {
229     if (!this->expect(Token::PRECISION, "'precision'")) {
230         return nullptr;
231     }
232     Modifiers::Flag result;
233     Token p = this->nextToken();
234     switch (p.fKind) {
235         case Token::LOWP:
236             result = Modifiers::kLowp_Flag;
237             break;
238         case Token::MEDIUMP:
239             result = Modifiers::kMediump_Flag;
240             break;
241         case Token::HIGHP:
242             result = Modifiers::kHighp_Flag;
243             break;
244         default:
245             this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" +
246                                      p.fText + "'");
247             return nullptr;
248     }
249     // FIXME handle the type
250     if (!this->type()) {
251         return nullptr;
252     }
253     this->expect(Token::SEMICOLON, "';'");
254     return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result));
255 }
256 
257 /* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
258    DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
directive()259 std::unique_ptr<ASTDeclaration> Parser::directive() {
260     Token start;
261     if (!this->expect(Token::DIRECTIVE, "a directive", &start)) {
262         return nullptr;
263     }
264     if (start.fText == "#version") {
265         this->expect(Token::INT_LITERAL, "a version number");
266         Token next = this->peek();
267         if (next.fText == "es" || next.fText == "compatibility") {
268             this->nextToken();
269         }
270         // version is ignored for now; it will eventually become an error when we stop pretending
271         // to be GLSL
272         return nullptr;
273     } else if (start.fText == "#extension") {
274         Token name;
275         if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
276             return nullptr;
277         }
278         if (!this->expect(Token::COLON, "':'")) {
279             return nullptr;
280         }
281         // FIXME: need to start paying attention to this token
282         if (!this->expect(Token::IDENTIFIER, "an identifier")) {
283             return nullptr;
284         }
285         return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition,
286                                                                 std::move(name.fText)));
287     } else {
288         this->error(start.fPosition, "unsupported directive '" + start.fText + "'");
289         return nullptr;
290     }
291 }
292 
293 /* SECTION LBRACE (LPAREN IDENTIFIER RPAREN)? <any sequence of tokens with balanced braces>
294    RBRACE */
section()295 std::unique_ptr<ASTDeclaration> Parser::section() {
296     Token start;
297     if (!this->expect(Token::SECTION, "a section token", &start)) {
298         return nullptr;
299     }
300     String argument;
301     if (this->peek().fKind == Token::LPAREN) {
302         this->nextToken();
303         Token argToken;
304         if (!this->expect(Token::IDENTIFIER, "an identifier", &argToken)) {
305             return nullptr;
306         }
307         argument = argToken.fText;
308         if (!this->expect(Token::RPAREN, "')'")) {
309             return nullptr;
310         }
311     }
312     if (!this->expect(Token::LBRACE, "'{'")) {
313         return nullptr;
314     }
315     String text;
316     int level = 1;
317     for (;;) {
318         Token next = this->nextRawToken();
319         switch (next.fKind) {
320             case Token::LBRACE:
321                 ++level;
322                 break;
323             case Token::RBRACE:
324                 --level;
325                 break;
326             case Token::END_OF_FILE:
327                 this->error(start.fPosition, "reached end of file while parsing section");
328                 return nullptr;
329             default:
330                 break;
331         }
332         if (!level) {
333             break;
334         }
335         text += next.fText;
336     }
337     return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fPosition,
338                                                           String(start.fText.c_str() + 1),
339                                                           argument,
340                                                           text));
341 }
342 
343 /* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
344    (COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
declaration()345 std::unique_ptr<ASTDeclaration> Parser::declaration() {
346     Modifiers modifiers = this->modifiers();
347     Token lookahead = this->peek();
348     if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) {
349         // we have an identifier that's not a type, could be the start of an interface block
350         return this->interfaceBlock(modifiers);
351     }
352     if (lookahead.fKind == Token::STRUCT) {
353         return this->structVarDeclaration(modifiers);
354     }
355     if (lookahead.fKind == Token::SEMICOLON) {
356         this->nextToken();
357         return std::unique_ptr<ASTDeclaration>(new ASTModifiersDeclaration(modifiers));
358     }
359     std::unique_ptr<ASTType> type(this->type());
360     if (!type) {
361         return nullptr;
362     }
363     if (type->fKind == ASTType::kStruct_Kind && this->checkNext(Token::SEMICOLON)) {
364         return nullptr;
365     }
366     Token name;
367     if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
368         return nullptr;
369     }
370     if (this->checkNext(Token::LPAREN)) {
371         std::vector<std::unique_ptr<ASTParameter>> parameters;
372         while (this->peek().fKind != Token::RPAREN) {
373             if (parameters.size() > 0) {
374                 if (!this->expect(Token::COMMA, "','")) {
375                     return nullptr;
376                 }
377             }
378             std::unique_ptr<ASTParameter> parameter = this->parameter();
379             if (!parameter) {
380                 return nullptr;
381             }
382             parameters.push_back(std::move(parameter));
383         }
384         this->nextToken();
385         std::unique_ptr<ASTBlock> body;
386         if (!this->checkNext(Token::SEMICOLON)) {
387             body = this->block();
388             if (!body) {
389                 return nullptr;
390             }
391         }
392         return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition,
393                                                                modifiers,
394                                                                std::move(type),
395                                                                std::move(name.fText),
396                                                                std::move(parameters),
397                                                                std::move(body)));
398     } else {
399         return this->varDeclarationEnd(modifiers, std::move(type), name.fText);
400     }
401 }
402 
403 /* modifiers type IDENTIFIER varDeclarationEnd */
varDeclarations()404 std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() {
405     Modifiers modifiers = this->modifiers();
406     std::unique_ptr<ASTType> type(this->type());
407     if (!type) {
408         return nullptr;
409     }
410     Token name;
411     if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
412         return nullptr;
413     }
414     return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText));
415 }
416 
417 /* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
structDeclaration()418 std::unique_ptr<ASTType> Parser::structDeclaration() {
419     if (!this->expect(Token::STRUCT, "'struct'")) {
420         return nullptr;
421     }
422     Token name;
423     if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
424         return nullptr;
425     }
426     if (!this->expect(Token::LBRACE, "'{'")) {
427         return nullptr;
428     }
429     std::vector<Type::Field> fields;
430     while (this->peek().fKind != Token::RBRACE) {
431         std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
432         if (!decl) {
433             return nullptr;
434         }
435         for (const auto& var : decl->fVars) {
436             auto type = (const Type*) fTypes[decl->fType->fName];
437             for (int i = (int) var.fSizes.size() - 1; i >= 0; i--) {
438                 if (!var.fSizes[i] || var.fSizes[i]->fKind != ASTExpression::kInt_Kind) {
439                     this->error(decl->fPosition, "array size in struct field must be a constant");
440                     return nullptr;
441                 }
442                 uint64_t columns = ((ASTIntLiteral&) *var.fSizes[i]).fValue;
443                 String name = type->name() + "[" + to_string(columns) + "]";
444                 type = new Type(name, Type::kArray_Kind, *type, (int) columns);
445                 fTypes.takeOwnership((Type*) type);
446             }
447             fields.push_back(Type::Field(decl->fModifiers, var.fName, type));
448             if (var.fValue) {
449                 this->error(decl->fPosition, "initializers are not permitted on struct fields");
450             }
451         }
452     }
453     if (!this->expect(Token::RBRACE, "'}'")) {
454         return nullptr;
455     }
456     fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fPosition, name.fText, fields)));
457     return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText,
458                                                 ASTType::kStruct_Kind, std::vector<int>()));
459 }
460 
461 /* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
structVarDeclaration(Modifiers modifiers)462 std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(Modifiers modifiers) {
463     std::unique_ptr<ASTType> type = this->structDeclaration();
464     if (!type) {
465         return nullptr;
466     }
467     Token name;
468     if (this->checkNext(Token::IDENTIFIER, &name)) {
469         std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers,
470                                                                              std::move(type),
471                                                                              std::move(name.fText));
472         if (result) {
473             for (const auto& var : result->fVars) {
474                 if (var.fValue) {
475                     this->error(var.fValue->fPosition,
476                                 "struct variables cannot be initialized");
477                 }
478             }
479         }
480         return result;
481     }
482     this->expect(Token::SEMICOLON, "';'");
483     return nullptr;
484 }
485 
486 /* (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)? (COMMA IDENTIFER
487    (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
varDeclarationEnd(Modifiers mods,std::unique_ptr<ASTType> type,String name)488 std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods,
489                                                               std::unique_ptr<ASTType> type,
490                                                               String name) {
491     std::vector<ASTVarDeclaration> vars;
492     std::vector<std::unique_ptr<ASTExpression>> currentVarSizes;
493     while (this->checkNext(Token::LBRACKET)) {
494         if (this->checkNext(Token::RBRACKET)) {
495             currentVarSizes.push_back(nullptr);
496         } else {
497             std::unique_ptr<ASTExpression> size(this->expression());
498             if (!size) {
499                 return nullptr;
500             }
501             currentVarSizes.push_back(std::move(size));
502             if (!this->expect(Token::RBRACKET, "']'")) {
503                 return nullptr;
504             }
505         }
506     }
507     std::unique_ptr<ASTExpression> value;
508     if (this->checkNext(Token::EQ)) {
509         value = this->assignmentExpression();
510         if (!value) {
511             return nullptr;
512         }
513     }
514     vars.emplace_back(std::move(name), std::move(currentVarSizes), std::move(value));
515     while (this->checkNext(Token::COMMA)) {
516         Token name;
517         if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
518             return nullptr;
519         }
520         currentVarSizes.clear();
521         value.reset();
522         while (this->checkNext(Token::LBRACKET)) {
523             if (this->checkNext(Token::RBRACKET)) {
524                 currentVarSizes.push_back(nullptr);
525             } else {
526                 std::unique_ptr<ASTExpression> size(this->expression());
527                 if (!size) {
528                     return nullptr;
529                 }
530                 currentVarSizes.push_back(std::move(size));
531                 if (!this->expect(Token::RBRACKET, "']'")) {
532                     return nullptr;
533                 }
534             }
535         }
536         if (this->checkNext(Token::EQ)) {
537             value = this->assignmentExpression();
538             if (!value) {
539                 return nullptr;
540             }
541         }
542         vars.emplace_back(std::move(name.fText), std::move(currentVarSizes), std::move(value));
543     }
544     if (!this->expect(Token::SEMICOLON, "';'")) {
545         return nullptr;
546     }
547     return std::unique_ptr<ASTVarDeclarations>(new ASTVarDeclarations(std::move(mods),
548                                                                       std::move(type),
549                                                                       std::move(vars)));
550 }
551 
552 /* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
parameter()553 std::unique_ptr<ASTParameter> Parser::parameter() {
554     Modifiers modifiers = this->modifiersWithDefaults(0);
555     std::unique_ptr<ASTType> type = this->type();
556     if (!type) {
557         return nullptr;
558     }
559     Token name;
560     if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
561         return nullptr;
562     }
563     std::vector<int> sizes;
564     while (this->checkNext(Token::LBRACKET)) {
565         Token sizeToken;
566         if (!this->expect(Token::INT_LITERAL, "a positive integer", &sizeToken)) {
567             return nullptr;
568         }
569         sizes.push_back(SkSL::stoi(sizeToken.fText));
570         if (!this->expect(Token::RBRACKET, "']'")) {
571             return nullptr;
572         }
573     }
574     return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers,
575                                                           std::move(type), name.fText,
576                                                           std::move(sizes)));
577 }
578 
579 /** (EQ INT_LITERAL)? */
layoutInt()580 int Parser::layoutInt() {
581     if (!this->expect(Token::EQ, "'='")) {
582         return -1;
583     }
584     Token resultToken;
585     if (this->expect(Token::INT_LITERAL, "a non-negative integer", &resultToken)) {
586         return SkSL::stoi(resultToken.fText);
587     }
588     return -1;
589 }
590 
591 /** EQ <any sequence of tokens with balanced parentheses and no top-level comma> */
layoutCode()592 String Parser::layoutCode() {
593     if (!this->expect(Token::EQ, "'='")) {
594         return "";
595     }
596     Token start = this->peek();
597     String code;
598     int level = 1;
599     bool done = false;
600     while (!done) {
601         Token next = this->peek();
602         switch (next.fKind) {
603             case Token::LPAREN:
604                 ++level;
605                 break;
606             case Token::RPAREN:
607                 --level;
608                 break;
609             case Token::COMMA:
610                 if (level == 1) {
611                     done = true;
612                 }
613                 break;
614             case Token::END_OF_FILE:
615                 this->error(start.fPosition, "reached end of file while parsing layout");
616                 return nullptr;
617             default:
618                 break;
619         }
620         if (!level) {
621             done = true;
622         }
623         if (!done) {
624             code += this->nextRawToken().fText;
625         }
626     }
627     return code;
628 }
629 
630 /** (EQ IDENTIFIER('identity'))? */
layoutKey()631 Layout::Key Parser::layoutKey() {
632     if (this->peek().fKind == Token::EQ) {
633         this->expect(Token::EQ, "'='");
634         Token key;
635         if (this->expect(Token::IDENTIFIER, "an identifer", &key)) {
636             if (key.fText == "identity") {
637                 return Layout::kIdentity_Key;
638             } else {
639                 this->error(key.fPosition, "unsupported layout key");
640             }
641         }
642     }
643     return Layout::kKey_Key;
644 }
645 
646 /* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
layout()647 Layout Parser::layout() {
648     int location = -1;
649     int offset = -1;
650     int binding = -1;
651     int index = -1;
652     int set = -1;
653     int builtin = -1;
654     int inputAttachmentIndex = -1;
655     bool originUpperLeft = false;
656     bool overrideCoverage = false;
657     bool blendSupportAllEquations = false;
658     Layout::Format format = Layout::Format::kUnspecified;
659     bool pushConstant = false;
660     Layout::Primitive primitive = Layout::kUnspecified_Primitive;
661     int maxVertices = -1;
662     int invocations = -1;
663     String when;
664     Layout::Key key = Layout::kNo_Key;
665     if (this->checkNext(Token::LAYOUT)) {
666         if (!this->expect(Token::LPAREN, "'('")) {
667             return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
668                           originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
669                           pushConstant, primitive, maxVertices, invocations, when, key);
670         }
671         for (;;) {
672             Token t = this->nextToken();
673             YY_BUFFER_STATE buffer;
674             buffer = layout_scan_string(t.fText.c_str(), fLayoutScanner);
675             int token = layoutlex(fLayoutScanner);
676             layout_delete_buffer(buffer, fLayoutScanner);
677             if (token != Token::INVALID_TOKEN) {
678                 switch (token) {
679                     case Token::LOCATION:
680                         location = this->layoutInt();
681                         break;
682                     case Token::OFFSET:
683                         offset = this->layoutInt();
684                         break;
685                     case Token::BINDING:
686                         binding = this->layoutInt();
687                         break;
688                     case Token::INDEX:
689                         index = this->layoutInt();
690                         break;
691                     case Token::SET:
692                         set = this->layoutInt();
693                         break;
694                     case Token::BUILTIN:
695                         builtin = this->layoutInt();
696                         break;
697                     case Token::INPUT_ATTACHMENT_INDEX:
698                         inputAttachmentIndex = this->layoutInt();
699                         break;
700                     case Token::ORIGIN_UPPER_LEFT:
701                         originUpperLeft = true;
702                         break;
703                     case Token::OVERRIDE_COVERAGE:
704                         overrideCoverage = true;
705                         break;
706                     case Token::BLEND_SUPPORT_ALL_EQUATIONS:
707                         blendSupportAllEquations = true;
708                         break;
709                     case Token::PUSH_CONSTANT:
710                         pushConstant = true;
711                         break;
712                     case Token::POINTS:
713                         primitive = Layout::kPoints_Primitive;
714                         break;
715                     case Token::LINES:
716                         primitive = Layout::kLines_Primitive;
717                         break;
718                     case Token::LINE_STRIP:
719                         primitive = Layout::kLineStrip_Primitive;
720                         break;
721                     case Token::LINES_ADJACENCY:
722                         primitive = Layout::kLinesAdjacency_Primitive;
723                         break;
724                     case Token::TRIANGLES:
725                         primitive = Layout::kTriangles_Primitive;
726                         break;
727                     case Token::TRIANGLE_STRIP:
728                         primitive = Layout::kTriangleStrip_Primitive;
729                         break;
730                     case Token::TRIANGLES_ADJACENCY:
731                         primitive = Layout::kTrianglesAdjacency_Primitive;
732                         break;
733                     case Token::MAX_VERTICES:
734                         maxVertices = this->layoutInt();
735                         break;
736                     case Token::INVOCATIONS:
737                         invocations = this->layoutInt();
738                         break;
739                     case Token::WHEN:
740                         when = this->layoutCode();
741                         break;
742                     case Token::KEY:
743                         key = this->layoutKey();
744                         break;
745                 }
746             } else if (Layout::ReadFormat(t.fText, &format)) {
747                // AST::ReadFormat stored the result in 'format'.
748             } else {
749                 this->error(t.fPosition, ("'" + t.fText +
750                                           "' is not a valid layout qualifier").c_str());
751             }
752             if (this->checkNext(Token::RPAREN)) {
753                 break;
754             }
755             if (!this->expect(Token::COMMA, "','")) {
756                 break;
757             }
758         }
759     }
760     return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
761                   originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
762                   pushConstant, primitive, maxVertices, invocations, when, key);
763 }
764 
765 /* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE |
766             READONLY | WRITEONLY | COHERENT | VOLATILE | RESTRICT | BUFFER)* */
modifiers()767 Modifiers Parser::modifiers() {
768     Layout layout = this->layout();
769     int flags = 0;
770     for (;;) {
771         // TODO: handle duplicate / incompatible flags
772         switch (peek().fKind) {
773             case Token::UNIFORM:
774                 this->nextToken();
775                 flags |= Modifiers::kUniform_Flag;
776                 break;
777             case Token::CONST:
778                 this->nextToken();
779                 flags |= Modifiers::kConst_Flag;
780                 break;
781             case Token::IN:
782                 this->nextToken();
783                 flags |= Modifiers::kIn_Flag;
784                 break;
785             case Token::OUT:
786                 this->nextToken();
787                 flags |= Modifiers::kOut_Flag;
788                 break;
789             case Token::INOUT:
790                 this->nextToken();
791                 flags |= Modifiers::kIn_Flag;
792                 flags |= Modifiers::kOut_Flag;
793                 break;
794             case Token::LOWP:
795                 this->nextToken();
796                 flags |= Modifiers::kLowp_Flag;
797                 break;
798             case Token::MEDIUMP:
799                 this->nextToken();
800                 flags |= Modifiers::kMediump_Flag;
801                 break;
802             case Token::HIGHP:
803                 this->nextToken();
804                 flags |= Modifiers::kHighp_Flag;
805                 break;
806             case Token::FLAT:
807                 this->nextToken();
808                 flags |= Modifiers::kFlat_Flag;
809                 break;
810             case Token::NOPERSPECTIVE:
811                 this->nextToken();
812                 flags |= Modifiers::kNoPerspective_Flag;
813                 break;
814             case Token::READONLY:
815                 this->nextToken();
816                 flags |= Modifiers::kReadOnly_Flag;
817                 break;
818             case Token::WRITEONLY:
819                 this->nextToken();
820                 flags |= Modifiers::kWriteOnly_Flag;
821                 break;
822             case Token::COHERENT:
823                 this->nextToken();
824                 flags |= Modifiers::kCoherent_Flag;
825                 break;
826             case Token::VOLATILE:
827                 this->nextToken();
828                 flags |= Modifiers::kVolatile_Flag;
829                 break;
830             case Token::RESTRICT:
831                 this->nextToken();
832                 flags |= Modifiers::kRestrict_Flag;
833                 break;
834             case Token::BUFFER:
835                 this->nextToken();
836                 flags |= Modifiers::kBuffer_Flag;
837                 break;
838             case Token::HASSIDEEFFECTS:
839                 this->nextToken();
840                 flags |= Modifiers::kHasSideEffects_Flag;
841                 break;
842             default:
843                 return Modifiers(layout, flags);
844         }
845     }
846 }
847 
modifiersWithDefaults(int defaultFlags)848 Modifiers Parser::modifiersWithDefaults(int defaultFlags) {
849     Modifiers result = this->modifiers();
850     if (!result.fFlags) {
851         return Modifiers(result.fLayout, defaultFlags);
852     }
853     return result;
854 }
855 
856 /* ifStatement | forStatement | doStatement | whileStatement | block | expression */
statement()857 std::unique_ptr<ASTStatement> Parser::statement() {
858     Token start = this->peek();
859     switch (start.fKind) {
860         case Token::IF: // fall through
861         case Token::STATIC_IF:
862             return this->ifStatement();
863         case Token::FOR:
864             return this->forStatement();
865         case Token::DO:
866             return this->doStatement();
867         case Token::WHILE:
868             return this->whileStatement();
869         case Token::SWITCH: // fall through
870         case Token::STATIC_SWITCH:
871             return this->switchStatement();
872         case Token::RETURN:
873             return this->returnStatement();
874         case Token::BREAK:
875             return this->breakStatement();
876         case Token::CONTINUE:
877             return this->continueStatement();
878         case Token::DISCARD:
879             return this->discardStatement();
880         case Token::LBRACE:
881             return this->block();
882         case Token::SEMICOLON:
883             this->nextToken();
884             return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition,
885                                                      std::vector<std::unique_ptr<ASTStatement>>()));
886         case Token::CONST:   // fall through
887         case Token::HIGHP:   // fall through
888         case Token::MEDIUMP: // fall through
889         case Token::LOWP: {
890             auto decl = this->varDeclarations();
891             if (!decl) {
892                 return nullptr;
893             }
894             return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(std::move(decl)));
895         }
896         case Token::IDENTIFIER:
897             if (this->isType(start.fText)) {
898                 auto decl = this->varDeclarations();
899                 if (!decl) {
900                     return nullptr;
901                 }
902                 return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
903                                                                                   std::move(decl)));
904             }
905             // fall through
906         default:
907             return this->expressionStatement();
908     }
909 }
910 
911 /* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* */
type()912 std::unique_ptr<ASTType> Parser::type() {
913     Token type;
914     if (!this->expect(Token::IDENTIFIER, "a type", &type)) {
915         return nullptr;
916     }
917     if (!this->isType(type.fText)) {
918         this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str());
919         return nullptr;
920     }
921     std::vector<int> sizes;
922     while (this->checkNext(Token::LBRACKET)) {
923         if (this->peek().fKind != Token::RBRACKET) {
924             int64_t i;
925             if (this->intLiteral(&i)) {
926                 sizes.push_back(i);
927             } else {
928                 return nullptr;
929             }
930         } else {
931             sizes.push_back(-1);
932         }
933         this->expect(Token::RBRACKET, "']'");
934     }
935     return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText),
936                                                 ASTType::kIdentifier_Kind, sizes));
937 }
938 
939 /* IDENTIFIER LBRACE varDeclaration* RBRACE (IDENTIFIER (LBRACKET expression? RBRACKET)*)? */
interfaceBlock(Modifiers mods)940 std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) {
941     Token name;
942     if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
943         return nullptr;
944     }
945     if (peek().fKind != Token::LBRACE) {
946         // we only get into interfaceBlock if we found a top-level identifier which was not a type.
947         // 99% of the time, the user was not actually intending to create an interface block, so
948         // it's better to report it as an unknown type
949         this->error(name.fPosition, "no type named '" + name.fText + "'");
950         return nullptr;
951     }
952     this->nextToken();
953     std::vector<std::unique_ptr<ASTVarDeclarations>> decls;
954     while (this->peek().fKind != Token::RBRACE) {
955         std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
956         if (!decl) {
957             return nullptr;
958         }
959         decls.push_back(std::move(decl));
960     }
961     this->nextToken();
962     std::vector<std::unique_ptr<ASTExpression>> sizes;
963     Token instanceName;
964     if (this->checkNext(Token::IDENTIFIER, &instanceName)) {
965         while (this->checkNext(Token::LBRACKET)) {
966             if (this->peek().fKind != Token::RBRACKET) {
967                 std::unique_ptr<ASTExpression> size = this->expression();
968                 if (!size) {
969                     return nullptr;
970                 }
971                 sizes.push_back(std::move(size));
972             } else {
973                 sizes.push_back(nullptr);
974             }
975             this->expect(Token::RBRACKET, "']'");
976         }
977     }
978     this->expect(Token::SEMICOLON, "';'");
979     return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods,
980                                                                  name.fText, std::move(decls),
981                                                                  std::move(instanceName.fText),
982                                                                  std::move(sizes)));
983 }
984 
985 /* IF LPAREN expression RPAREN statement (ELSE statement)? */
ifStatement()986 std::unique_ptr<ASTIfStatement> Parser::ifStatement() {
987     Token start;
988     bool isStatic = this->checkNext(Token::STATIC_IF, &start);
989     if (!isStatic && !this->expect(Token::IF, "'if'", &start)) {
990         return nullptr;
991     }
992     if (!this->expect(Token::LPAREN, "'('")) {
993         return nullptr;
994     }
995     std::unique_ptr<ASTExpression> test(this->expression());
996     if (!test) {
997         return nullptr;
998     }
999     if (!this->expect(Token::RPAREN, "')'")) {
1000         return nullptr;
1001     }
1002     std::unique_ptr<ASTStatement> ifTrue(this->statement());
1003     if (!ifTrue) {
1004         return nullptr;
1005     }
1006     std::unique_ptr<ASTStatement> ifFalse;
1007     if (this->checkNext(Token::ELSE)) {
1008         ifFalse = this->statement();
1009         if (!ifFalse) {
1010             return nullptr;
1011         }
1012     }
1013     return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition,
1014                                                               isStatic,
1015                                                               std::move(test),
1016                                                               std::move(ifTrue),
1017                                                               std::move(ifFalse)));
1018 }
1019 
1020 /* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
doStatement()1021 std::unique_ptr<ASTDoStatement> Parser::doStatement() {
1022     Token start;
1023     if (!this->expect(Token::DO, "'do'", &start)) {
1024         return nullptr;
1025     }
1026     std::unique_ptr<ASTStatement> statement(this->statement());
1027     if (!statement) {
1028         return nullptr;
1029     }
1030     if (!this->expect(Token::WHILE, "'while'")) {
1031         return nullptr;
1032     }
1033     if (!this->expect(Token::LPAREN, "'('")) {
1034         return nullptr;
1035     }
1036     std::unique_ptr<ASTExpression> test(this->expression());
1037     if (!test) {
1038         return nullptr;
1039     }
1040     if (!this->expect(Token::RPAREN, "')'")) {
1041         return nullptr;
1042     }
1043     if (!this->expect(Token::SEMICOLON, "';'")) {
1044         return nullptr;
1045     }
1046     return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition,
1047                                                               std::move(statement),
1048                                                               std::move(test)));
1049 }
1050 
1051 /* WHILE LPAREN expression RPAREN STATEMENT */
whileStatement()1052 std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
1053     Token start;
1054     if (!this->expect(Token::WHILE, "'while'", &start)) {
1055         return nullptr;
1056     }
1057     if (!this->expect(Token::LPAREN, "'('")) {
1058         return nullptr;
1059     }
1060     std::unique_ptr<ASTExpression> test(this->expression());
1061     if (!test) {
1062         return nullptr;
1063     }
1064     if (!this->expect(Token::RPAREN, "')'")) {
1065         return nullptr;
1066     }
1067     std::unique_ptr<ASTStatement> statement(this->statement());
1068     if (!statement) {
1069         return nullptr;
1070     }
1071     return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition,
1072                                                                     std::move(test),
1073                                                                     std::move(statement)));
1074 }
1075 
1076 /* CASE expression COLON statement* */
switchCase()1077 std::unique_ptr<ASTSwitchCase> Parser::switchCase() {
1078     Token start;
1079     if (!this->expect(Token::CASE, "'case'", &start)) {
1080         return nullptr;
1081     }
1082     std::unique_ptr<ASTExpression> value = this->expression();
1083     if (!value) {
1084         return nullptr;
1085     }
1086     if (!this->expect(Token::COLON, "':'")) {
1087         return nullptr;
1088     }
1089     std::vector<std::unique_ptr<ASTStatement>> statements;
1090     while (this->peek().fKind != Token::RBRACE && this->peek().fKind != Token::CASE &&
1091            this->peek().fKind != Token::DEFAULT) {
1092         std::unique_ptr<ASTStatement> s = this->statement();
1093         if (!s) {
1094             return nullptr;
1095         }
1096         statements.push_back(std::move(s));
1097     }
1098     return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fPosition, std::move(value),
1099                                                             std::move(statements)));
1100 }
1101 
1102 /* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
switchStatement()1103 std::unique_ptr<ASTStatement> Parser::switchStatement() {
1104     Token start;
1105     bool isStatic = this->checkNext(Token::STATIC_SWITCH, &start);
1106     if (!isStatic && !this->expect(Token::SWITCH, "'switch'", &start)) {
1107         return nullptr;
1108     }
1109     if (!this->expect(Token::LPAREN, "'('")) {
1110         return nullptr;
1111     }
1112     std::unique_ptr<ASTExpression> value(this->expression());
1113     if (!value) {
1114         return nullptr;
1115     }
1116     if (!this->expect(Token::RPAREN, "')'")) {
1117         return nullptr;
1118     }
1119     if (!this->expect(Token::LBRACE, "'{'")) {
1120         return nullptr;
1121     }
1122     std::vector<std::unique_ptr<ASTSwitchCase>> cases;
1123     while (this->peek().fKind == Token::CASE) {
1124         std::unique_ptr<ASTSwitchCase> c = this->switchCase();
1125         if (!c) {
1126             return nullptr;
1127         }
1128         cases.push_back(std::move(c));
1129     }
1130     // Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
1131     // parts of the compiler may rely upon this assumption.
1132     if (this->peek().fKind == Token::DEFAULT) {
1133         Token defaultStart;
1134         ASSERT_RESULT(this->expect(Token::DEFAULT, "'default'", &defaultStart));
1135         if (!this->expect(Token::COLON, "':'")) {
1136             return nullptr;
1137         }
1138         std::vector<std::unique_ptr<ASTStatement>> statements;
1139         while (this->peek().fKind != Token::RBRACE) {
1140             std::unique_ptr<ASTStatement> s = this->statement();
1141             if (!s) {
1142                 return nullptr;
1143             }
1144             statements.push_back(std::move(s));
1145         }
1146         cases.emplace_back(new ASTSwitchCase(defaultStart.fPosition, nullptr,
1147                                              std::move(statements)));
1148     }
1149     if (!this->expect(Token::RBRACE, "'}'")) {
1150         return nullptr;
1151     }
1152     return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fPosition,
1153                                                                 isStatic,
1154                                                                 std::move(value),
1155                                                                 std::move(cases)));
1156 }
1157 
1158 /* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
1159    STATEMENT */
forStatement()1160 std::unique_ptr<ASTForStatement> Parser::forStatement() {
1161     Token start;
1162     if (!this->expect(Token::FOR, "'for'", &start)) {
1163         return nullptr;
1164     }
1165     if (!this->expect(Token::LPAREN, "'('")) {
1166         return nullptr;
1167     }
1168     std::unique_ptr<ASTStatement> initializer;
1169     Token nextToken = this->peek();
1170     switch (nextToken.fKind) {
1171         case Token::SEMICOLON:
1172             this->nextToken();
1173             break;
1174         case Token::CONST: {
1175             std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
1176             if (!vd) {
1177                 return nullptr;
1178             }
1179             initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
1180                                                                                     std::move(vd)));
1181             break;
1182         }
1183         case Token::IDENTIFIER: {
1184             if (this->isType(nextToken.fText)) {
1185                 std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
1186                 if (!vd) {
1187                     return nullptr;
1188                 }
1189                 initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
1190                                                                                     std::move(vd)));
1191                 break;
1192             }
1193         } // fall through
1194         default:
1195             initializer = this->expressionStatement();
1196     }
1197     std::unique_ptr<ASTExpression> test;
1198     if (this->peek().fKind != Token::SEMICOLON) {
1199         test = this->expression();
1200         if (!test) {
1201             return nullptr;
1202         }
1203     }
1204     if (!this->expect(Token::SEMICOLON, "';'")) {
1205         return nullptr;
1206     }
1207     std::unique_ptr<ASTExpression> next;
1208     if (this->peek().fKind != Token::RPAREN) {
1209         next = this->expression();
1210         if (!next) {
1211             return nullptr;
1212         }
1213     }
1214     if (!this->expect(Token::RPAREN, "')'")) {
1215         return nullptr;
1216     }
1217     std::unique_ptr<ASTStatement> statement(this->statement());
1218     if (!statement) {
1219         return nullptr;
1220     }
1221     return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition,
1222                                                                 std::move(initializer),
1223                                                                 std::move(test), std::move(next),
1224                                                                 std::move(statement)));
1225 }
1226 
1227 /* RETURN expression? SEMICOLON */
returnStatement()1228 std::unique_ptr<ASTReturnStatement> Parser::returnStatement() {
1229     Token start;
1230     if (!this->expect(Token::RETURN, "'return'", &start)) {
1231         return nullptr;
1232     }
1233     std::unique_ptr<ASTExpression> expression;
1234     if (this->peek().fKind != Token::SEMICOLON) {
1235         expression = this->expression();
1236         if (!expression) {
1237             return nullptr;
1238         }
1239     }
1240     if (!this->expect(Token::SEMICOLON, "';'")) {
1241         return nullptr;
1242     }
1243     return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition,
1244                                                                       std::move(expression)));
1245 }
1246 
1247 /* BREAK SEMICOLON */
breakStatement()1248 std::unique_ptr<ASTBreakStatement> Parser::breakStatement() {
1249     Token start;
1250     if (!this->expect(Token::BREAK, "'break'", &start)) {
1251         return nullptr;
1252     }
1253     if (!this->expect(Token::SEMICOLON, "';'")) {
1254         return nullptr;
1255     }
1256     return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fPosition));
1257 }
1258 
1259 /* CONTINUE SEMICOLON */
continueStatement()1260 std::unique_ptr<ASTContinueStatement> Parser::continueStatement() {
1261     Token start;
1262     if (!this->expect(Token::CONTINUE, "'continue'", &start)) {
1263         return nullptr;
1264     }
1265     if (!this->expect(Token::SEMICOLON, "';'")) {
1266         return nullptr;
1267     }
1268     return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fPosition));
1269 }
1270 
1271 /* DISCARD SEMICOLON */
discardStatement()1272 std::unique_ptr<ASTDiscardStatement> Parser::discardStatement() {
1273     Token start;
1274     if (!this->expect(Token::DISCARD, "'continue'", &start)) {
1275         return nullptr;
1276     }
1277     if (!this->expect(Token::SEMICOLON, "';'")) {
1278         return nullptr;
1279     }
1280     return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fPosition));
1281 }
1282 
1283 /* LBRACE statement* RBRACE */
block()1284 std::unique_ptr<ASTBlock> Parser::block() {
1285     AutoDepth depth(this);
1286     if (!depth.checkValid()) {
1287         return nullptr;
1288     }
1289     Token start;
1290     if (!this->expect(Token::LBRACE, "'{'", &start)) {
1291         return nullptr;
1292     }
1293     std::vector<std::unique_ptr<ASTStatement>> statements;
1294     for (;;) {
1295         switch (this->peek().fKind) {
1296             case Token::RBRACE:
1297                 this->nextToken();
1298                 return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition,
1299                                                               std::move(statements)));
1300             case Token::END_OF_FILE:
1301                 this->error(this->peek().fPosition, "expected '}', but found end of file");
1302                 return nullptr;
1303             default: {
1304                 std::unique_ptr<ASTStatement> statement = this->statement();
1305                 if (!statement) {
1306                     return nullptr;
1307                 }
1308                 statements.push_back(std::move(statement));
1309             }
1310         }
1311     }
1312 }
1313 
1314 /* expression SEMICOLON */
expressionStatement()1315 std::unique_ptr<ASTExpressionStatement> Parser::expressionStatement() {
1316     std::unique_ptr<ASTExpression> expr = this->expression();
1317     if (expr) {
1318         if (this->expect(Token::SEMICOLON, "';'")) {
1319             ASTExpressionStatement* result = new ASTExpressionStatement(std::move(expr));
1320             return std::unique_ptr<ASTExpressionStatement>(result);
1321         }
1322     }
1323     return nullptr;
1324 }
1325 
1326 /* assignmentExpression */
expression()1327 std::unique_ptr<ASTExpression> Parser::expression() {
1328     AutoDepth depth(this);
1329     if (!depth.checkValid()) {
1330         return nullptr;
1331     }
1332     return this->commaExpression();
1333 }
1334 
1335 /* assignmentExpression (COMMA assignmentExpression)* */
commaExpression()1336 std::unique_ptr<ASTExpression> Parser::commaExpression() {
1337     std::unique_ptr<ASTExpression> result = this->assignmentExpression();
1338     if (!result) {
1339         return nullptr;
1340     }
1341     Token t;
1342     while (this->checkNext(Token::COMMA, &t)) {
1343         std::unique_ptr<ASTExpression> right = this->commaExpression();
1344         if (!right) {
1345             return nullptr;
1346         }
1347         result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1348     }
1349     return result;
1350 }
1351 
1352 /* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1353    BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1354    assignmentExpression)*
1355  */
assignmentExpression()1356 std::unique_ptr<ASTExpression> Parser::assignmentExpression() {
1357     std::unique_ptr<ASTExpression> result = this->ternaryExpression();
1358     if (!result) {
1359         return nullptr;
1360     }
1361     for (;;) {
1362         switch (this->peek().fKind) {
1363             case Token::EQ:           // fall through
1364             case Token::STAREQ:       // fall through
1365             case Token::SLASHEQ:      // fall through
1366             case Token::PERCENTEQ:    // fall through
1367             case Token::PLUSEQ:       // fall through
1368             case Token::MINUSEQ:      // fall through
1369             case Token::SHLEQ:        // fall through
1370             case Token::SHREQ:        // fall through
1371             case Token::BITWISEANDEQ: // fall through
1372             case Token::BITWISEXOREQ: // fall through
1373             case Token::BITWISEOREQ:  // fall through
1374             case Token::LOGICALANDEQ: // fall through
1375             case Token::LOGICALXOREQ: // fall through
1376             case Token::LOGICALOREQ: {
1377                 Token t = this->nextToken();
1378                 std::unique_ptr<ASTExpression> right = this->assignmentExpression();
1379                 if (!right) {
1380                     return nullptr;
1381                 }
1382                 result = std::unique_ptr<ASTExpression>(new ASTBinaryExpression(std::move(result),
1383                                                                                 t,
1384                                                                                 std::move(right)));
1385             }
1386             default:
1387                 return result;
1388         }
1389     }
1390 }
1391 
1392 /* logicalOrExpression ('?' expression ':' assignmentExpression)? */
ternaryExpression()1393 std::unique_ptr<ASTExpression> Parser::ternaryExpression() {
1394     std::unique_ptr<ASTExpression> result = this->logicalOrExpression();
1395     if (!result) {
1396         return nullptr;
1397     }
1398     if (this->checkNext(Token::QUESTION)) {
1399         std::unique_ptr<ASTExpression> trueExpr = this->expression();
1400         if (!trueExpr) {
1401             return nullptr;
1402         }
1403         if (this->expect(Token::COLON, "':'")) {
1404             std::unique_ptr<ASTExpression> falseExpr = this->assignmentExpression();
1405             return std::unique_ptr<ASTExpression>(new ASTTernaryExpression(std::move(result),
1406                                                                            std::move(trueExpr),
1407                                                                            std::move(falseExpr)));
1408         }
1409         return nullptr;
1410     }
1411     return result;
1412 }
1413 
1414 /* logicalXorExpression (LOGICALOR logicalXorExpression)* */
logicalOrExpression()1415 std::unique_ptr<ASTExpression> Parser::logicalOrExpression() {
1416     std::unique_ptr<ASTExpression> result = this->logicalXorExpression();
1417     if (!result) {
1418         return nullptr;
1419     }
1420     Token t;
1421     while (this->checkNext(Token::LOGICALOR, &t)) {
1422         std::unique_ptr<ASTExpression> right = this->logicalXorExpression();
1423         if (!right) {
1424             return nullptr;
1425         }
1426         result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1427     }
1428     return result;
1429 }
1430 
1431 /* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
logicalXorExpression()1432 std::unique_ptr<ASTExpression> Parser::logicalXorExpression() {
1433     std::unique_ptr<ASTExpression> result = this->logicalAndExpression();
1434     if (!result) {
1435         return nullptr;
1436     }
1437     Token t;
1438     while (this->checkNext(Token::LOGICALXOR, &t)) {
1439         std::unique_ptr<ASTExpression> right = this->logicalAndExpression();
1440         if (!right) {
1441             return nullptr;
1442         }
1443         result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1444     }
1445     return result;
1446 }
1447 
1448 /* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
logicalAndExpression()1449 std::unique_ptr<ASTExpression> Parser::logicalAndExpression() {
1450     std::unique_ptr<ASTExpression> result = this->bitwiseOrExpression();
1451     if (!result) {
1452         return nullptr;
1453     }
1454     Token t;
1455     while (this->checkNext(Token::LOGICALAND, &t)) {
1456         std::unique_ptr<ASTExpression> right = this->bitwiseOrExpression();
1457         if (!right) {
1458             return nullptr;
1459         }
1460         result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1461     }
1462     return result;
1463 }
1464 
1465 /* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
bitwiseOrExpression()1466 std::unique_ptr<ASTExpression> Parser::bitwiseOrExpression() {
1467     std::unique_ptr<ASTExpression> result = this->bitwiseXorExpression();
1468     if (!result) {
1469         return nullptr;
1470     }
1471     Token t;
1472     while (this->checkNext(Token::BITWISEOR, &t)) {
1473         std::unique_ptr<ASTExpression> right = this->bitwiseXorExpression();
1474         if (!right) {
1475             return nullptr;
1476         }
1477         result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1478     }
1479     return result;
1480 }
1481 
1482 /* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
bitwiseXorExpression()1483 std::unique_ptr<ASTExpression> Parser::bitwiseXorExpression() {
1484     std::unique_ptr<ASTExpression> result = this->bitwiseAndExpression();
1485     if (!result) {
1486         return nullptr;
1487     }
1488     Token t;
1489     while (this->checkNext(Token::BITWISEXOR, &t)) {
1490         std::unique_ptr<ASTExpression> right = this->bitwiseAndExpression();
1491         if (!right) {
1492             return nullptr;
1493         }
1494         result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1495     }
1496     return result;
1497 }
1498 
1499 /* equalityExpression (BITWISEAND equalityExpression)* */
bitwiseAndExpression()1500 std::unique_ptr<ASTExpression> Parser::bitwiseAndExpression() {
1501     std::unique_ptr<ASTExpression> result = this->equalityExpression();
1502     if (!result) {
1503         return nullptr;
1504     }
1505     Token t;
1506     while (this->checkNext(Token::BITWISEAND, &t)) {
1507         std::unique_ptr<ASTExpression> right = this->equalityExpression();
1508         if (!right) {
1509             return nullptr;
1510         }
1511         result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1512     }
1513     return result;
1514 }
1515 
1516 /* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
equalityExpression()1517 std::unique_ptr<ASTExpression> Parser::equalityExpression() {
1518     std::unique_ptr<ASTExpression> result = this->relationalExpression();
1519     if (!result) {
1520         return nullptr;
1521     }
1522     for (;;) {
1523         switch (this->peek().fKind) {
1524             case Token::EQEQ:   // fall through
1525             case Token::NEQ: {
1526                 Token t = this->nextToken();
1527                 std::unique_ptr<ASTExpression> right = this->relationalExpression();
1528                 if (!right) {
1529                     return nullptr;
1530                 }
1531                 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1532                 break;
1533             }
1534             default:
1535                 return result;
1536         }
1537     }
1538 }
1539 
1540 /* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
relationalExpression()1541 std::unique_ptr<ASTExpression> Parser::relationalExpression() {
1542     std::unique_ptr<ASTExpression> result = this->shiftExpression();
1543     if (!result) {
1544         return nullptr;
1545     }
1546     for (;;) {
1547         switch (this->peek().fKind) {
1548             case Token::LT:   // fall through
1549             case Token::GT:   // fall through
1550             case Token::LTEQ: // fall through
1551             case Token::GTEQ: {
1552                 Token t = this->nextToken();
1553                 std::unique_ptr<ASTExpression> right = this->shiftExpression();
1554                 if (!right) {
1555                     return nullptr;
1556                 }
1557                 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1558                 break;
1559             }
1560             default:
1561                 return result;
1562         }
1563     }
1564 }
1565 
1566 /* additiveExpression ((SHL | SHR) additiveExpression)* */
shiftExpression()1567 std::unique_ptr<ASTExpression> Parser::shiftExpression() {
1568     std::unique_ptr<ASTExpression> result = this->additiveExpression();
1569     if (!result) {
1570         return nullptr;
1571     }
1572     for (;;) {
1573         switch (this->peek().fKind) {
1574             case Token::SHL: // fall through
1575             case Token::SHR: {
1576                 Token t = this->nextToken();
1577                 std::unique_ptr<ASTExpression> right = this->additiveExpression();
1578                 if (!right) {
1579                     return nullptr;
1580                 }
1581                 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1582                 break;
1583             }
1584             default:
1585                 return result;
1586         }
1587     }
1588 }
1589 
1590 /* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
additiveExpression()1591 std::unique_ptr<ASTExpression> Parser::additiveExpression() {
1592     std::unique_ptr<ASTExpression> result = this->multiplicativeExpression();
1593     if (!result) {
1594         return nullptr;
1595     }
1596     for (;;) {
1597         switch (this->peek().fKind) {
1598             case Token::PLUS: // fall through
1599             case Token::MINUS: {
1600                 Token t = this->nextToken();
1601                 std::unique_ptr<ASTExpression> right = this->multiplicativeExpression();
1602                 if (!right) {
1603                     return nullptr;
1604                 }
1605                 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1606                 break;
1607             }
1608             default:
1609                 return result;
1610         }
1611     }
1612 }
1613 
1614 /* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
multiplicativeExpression()1615 std::unique_ptr<ASTExpression> Parser::multiplicativeExpression() {
1616     std::unique_ptr<ASTExpression> result = this->unaryExpression();
1617     if (!result) {
1618         return nullptr;
1619     }
1620     for (;;) {
1621         switch (this->peek().fKind) {
1622             case Token::STAR: // fall through
1623             case Token::SLASH: // fall through
1624             case Token::PERCENT: {
1625                 Token t = this->nextToken();
1626                 std::unique_ptr<ASTExpression> right = this->unaryExpression();
1627                 if (!right) {
1628                     return nullptr;
1629                 }
1630                 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1631                 break;
1632             }
1633             default:
1634                 return result;
1635         }
1636     }
1637 }
1638 
1639 /* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
unaryExpression()1640 std::unique_ptr<ASTExpression> Parser::unaryExpression() {
1641     switch (this->peek().fKind) {
1642         case Token::PLUS:       // fall through
1643         case Token::MINUS:      // fall through
1644         case Token::LOGICALNOT: // fall through
1645         case Token::BITWISENOT: // fall through
1646         case Token::PLUSPLUS:   // fall through
1647         case Token::MINUSMINUS: {
1648             Token t = this->nextToken();
1649             std::unique_ptr<ASTExpression> expr = this->unaryExpression();
1650             if (!expr) {
1651                 return nullptr;
1652             }
1653             return std::unique_ptr<ASTExpression>(new ASTPrefixExpression(t, std::move(expr)));
1654         }
1655         default:
1656             return this->postfixExpression();
1657     }
1658 }
1659 
1660 /* term suffix* */
postfixExpression()1661 std::unique_ptr<ASTExpression> Parser::postfixExpression() {
1662     std::unique_ptr<ASTExpression> result = this->term();
1663     if (!result) {
1664         return nullptr;
1665     }
1666     for (;;) {
1667         switch (this->peek().fKind) {
1668             case Token::LBRACKET: // fall through
1669             case Token::DOT:      // fall through
1670             case Token::LPAREN:   // fall through
1671             case Token::PLUSPLUS: // fall through
1672             case Token::MINUSMINUS: {
1673                 std::unique_ptr<ASTSuffix> s = this->suffix();
1674                 if (!s) {
1675                     return nullptr;
1676                 }
1677                 result.reset(new ASTSuffixExpression(std::move(result), std::move(s)));
1678                 break;
1679             }
1680             default:
1681                 return result;
1682         }
1683     }
1684 }
1685 
1686 /* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
1687    PLUSPLUS | MINUSMINUS */
suffix()1688 std::unique_ptr<ASTSuffix> Parser::suffix() {
1689     Token next = this->nextToken();
1690     switch (next.fKind) {
1691         case Token::LBRACKET: {
1692             if (this->checkNext(Token::RBRACKET)) {
1693                 return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fPosition));
1694             }
1695             std::unique_ptr<ASTExpression> e = this->expression();
1696             if (!e) {
1697                 return nullptr;
1698             }
1699             this->expect(Token::RBRACKET, "']' to complete array access expression");
1700             return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e)));
1701         }
1702         case Token::DOT: {
1703             Position pos = this->peek().fPosition;
1704             String text;
1705             if (this->identifier(&text)) {
1706                 return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(pos, std::move(text)));
1707             }
1708             return nullptr;
1709         }
1710         case Token::LPAREN: {
1711             std::vector<std::unique_ptr<ASTExpression>> parameters;
1712             if (this->peek().fKind != Token::RPAREN) {
1713                 for (;;) {
1714                     std::unique_ptr<ASTExpression> expr = this->assignmentExpression();
1715                     if (!expr) {
1716                         return nullptr;
1717                     }
1718                     parameters.push_back(std::move(expr));
1719                     if (!this->checkNext(Token::COMMA)) {
1720                         break;
1721                     }
1722                 }
1723             }
1724             this->expect(Token::RPAREN, "')' to complete function parameters");
1725             return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition,
1726                                                                 std::move(parameters)));
1727         }
1728         case Token::PLUSPLUS:
1729             return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
1730                                                             ASTSuffix::kPostIncrement_Kind));
1731         case Token::MINUSMINUS:
1732             return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
1733                                                             ASTSuffix::kPostDecrement_Kind));
1734         default: {
1735             this->error(next.fPosition,  "expected expression suffix, but found '" + next.fText +
1736                                          "'\n");
1737             return nullptr;
1738         }
1739     }
1740 }
1741 
1742 /* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */
term()1743 std::unique_ptr<ASTExpression> Parser::term() {
1744     std::unique_ptr<ASTExpression> result;
1745     Token t = this->peek();
1746     switch (t.fKind) {
1747         case Token::IDENTIFIER: {
1748             String text;
1749             if (this->identifier(&text)) {
1750                 result.reset(new ASTIdentifier(t.fPosition, std::move(text)));
1751             }
1752             break;
1753         }
1754         case Token::INT_LITERAL: {
1755             int64_t i;
1756             if (this->intLiteral(&i)) {
1757                 result.reset(new ASTIntLiteral(t.fPosition, i));
1758             }
1759             break;
1760         }
1761         case Token::FLOAT_LITERAL: {
1762             double f;
1763             if (this->floatLiteral(&f)) {
1764                 result.reset(new ASTFloatLiteral(t.fPosition, f));
1765             }
1766             break;
1767         }
1768         case Token::TRUE_LITERAL: // fall through
1769         case Token::FALSE_LITERAL: {
1770             bool b;
1771             if (this->boolLiteral(&b)) {
1772                 result.reset(new ASTBoolLiteral(t.fPosition, b));
1773             }
1774             break;
1775         }
1776         case Token::LPAREN: {
1777             this->nextToken();
1778             result = this->expression();
1779             if (result) {
1780                 this->expect(Token::RPAREN, "')' to complete expression");
1781             }
1782             break;
1783         }
1784         default:
1785             this->nextToken();
1786             this->error(t.fPosition,  "expected expression, but found '" + t.fText + "'\n");
1787             result = nullptr;
1788     }
1789     return result;
1790 }
1791 
1792 /* INT_LITERAL */
intLiteral(int64_t * dest)1793 bool Parser::intLiteral(int64_t* dest) {
1794     Token t;
1795     if (this->expect(Token::INT_LITERAL, "integer literal", &t)) {
1796         *dest = SkSL::stol(t.fText);
1797         return true;
1798     }
1799     return false;
1800 }
1801 
1802 /* FLOAT_LITERAL */
floatLiteral(double * dest)1803 bool Parser::floatLiteral(double* dest) {
1804     Token t;
1805     if (this->expect(Token::FLOAT_LITERAL, "float literal", &t)) {
1806         *dest = SkSL::stod(t.fText);
1807         return true;
1808     }
1809     return false;
1810 }
1811 
1812 /* TRUE_LITERAL | FALSE_LITERAL */
boolLiteral(bool * dest)1813 bool Parser::boolLiteral(bool* dest) {
1814     Token t = this->nextToken();
1815     switch (t.fKind) {
1816         case Token::TRUE_LITERAL:
1817             *dest = true;
1818             return true;
1819         case Token::FALSE_LITERAL:
1820             *dest = false;
1821             return true;
1822         default:
1823             this->error(t.fPosition, "expected 'true' or 'false', but found '" + t.fText + "'\n");
1824             return false;
1825     }
1826 }
1827 
1828 /* IDENTIFIER */
identifier(String * dest)1829 bool Parser::identifier(String* dest) {
1830     Token t;
1831     if (this->expect(Token::IDENTIFIER, "identifier", &t)) {
1832         *dest = t.fText;
1833         return true;
1834     }
1835     return false;
1836 }
1837 
1838 } // namespace
1839