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