blob: 316c0fd287db4a2131d916340400834b9892aa4f [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
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 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05007
Mike Klein4b432fa2019-06-06 11:44:05 -05008#include "src/sksl/SkSLParser.h"
John Stilesfbd050b2020-08-03 13:21:46 -04009
10#include <memory>
11#include "stdio.h"
12
Ethan Nicholasdaed2592021-03-04 14:30:25 -050013#include "include/private/SkSLModifiers.h"
John Stilesfbd050b2020-08-03 13:21:46 -040014#include "src/sksl/SkSLASTNode.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/sksl/ir/SkSLSymbolTable.h"
16#include "src/sksl/ir/SkSLType.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070017
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040018#ifndef SKSL_STANDALONE
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "include/private/SkOnce.h"
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040020#endif
21
ethannicholasb3058bd2016-07-01 08:22:01 -070022namespace SkSL {
23
John Stiles8d056592020-11-10 10:03:50 -050024static constexpr int kMaxParseDepth = 50;
John Stilesd39aec92020-12-03 14:37:16 -050025static constexpr int kMaxStructDepth = 8;
John Stilesa695d622020-11-10 10:04:26 -050026
27static bool struct_is_too_deeply_nested(const Type& type, int limit) {
28 if (limit < 0) {
29 return true;
30 }
31
John Stilesc0c51062020-12-03 17:16:29 -050032 if (type.isStruct()) {
John Stilesa695d622020-11-10 10:04:26 -050033 for (const Type::Field& f : type.fields()) {
34 if (struct_is_too_deeply_nested(*f.fType, limit - 1)) {
35 return true;
36 }
37 }
38 }
39
40 return false;
41}
ethannicholascad64162016-10-27 10:54:02 -070042
John Stiles7d5b90a2021-01-21 14:26:51 -050043static int parse_modifier_token(Token::Kind token) {
44 switch (token) {
45 case Token::Kind::TK_UNIFORM: return Modifiers::kUniform_Flag;
46 case Token::Kind::TK_CONST: return Modifiers::kConst_Flag;
47 case Token::Kind::TK_IN: return Modifiers::kIn_Flag;
48 case Token::Kind::TK_OUT: return Modifiers::kOut_Flag;
49 case Token::Kind::TK_INOUT: return Modifiers::kIn_Flag | Modifiers::kOut_Flag;
50 case Token::Kind::TK_FLAT: return Modifiers::kFlat_Flag;
51 case Token::Kind::TK_NOPERSPECTIVE: return Modifiers::kNoPerspective_Flag;
John Stiles7d5b90a2021-01-21 14:26:51 -050052 case Token::Kind::TK_HASSIDEEFFECTS: return Modifiers::kHasSideEffects_Flag;
John Stiles7d5b90a2021-01-21 14:26:51 -050053 case Token::Kind::TK_INLINE: return Modifiers::kInline_Flag;
John Stiles0dd1a772021-03-09 22:14:27 -050054 case Token::Kind::TK_NOINLINE: return Modifiers::kNoInline_Flag;
John Stiles02014312021-08-04 16:03:12 -040055 case Token::Kind::TK_HIGHP: return Modifiers::kHighp_Flag;
56 case Token::Kind::TK_MEDIUMP: return Modifiers::kMediump_Flag;
57 case Token::Kind::TK_LOWP: return Modifiers::kLowp_Flag;
John Stilesefde90d2021-08-12 23:06:24 -040058 case Token::Kind::TK_ES3: return Modifiers::kES3_Flag;
John Stiles7d5b90a2021-01-21 14:26:51 -050059 default: return 0;
60 }
61}
62
ethannicholascad64162016-10-27 10:54:02 -070063class AutoDepth {
64public:
65 AutoDepth(Parser* p)
Ethan Nicholascf4deab2019-09-13 16:28:14 -040066 : fParser(p)
67 , fDepth(0) {}
ethannicholascad64162016-10-27 10:54:02 -070068
69 ~AutoDepth() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -040070 fParser->fDepth -= fDepth;
ethannicholascad64162016-10-27 10:54:02 -070071 }
72
Ethan Nicholascf4deab2019-09-13 16:28:14 -040073 bool increase() {
74 ++fDepth;
75 ++fParser->fDepth;
John Stiles8d056592020-11-10 10:03:50 -050076 if (fParser->fDepth > kMaxParseDepth) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070077 fParser->error(fParser->peek(), String("exceeded max parse depth"));
ethannicholascad64162016-10-27 10:54:02 -070078 return false;
79 }
80 return true;
81 }
82
83private:
84 Parser* fParser;
Ethan Nicholascf4deab2019-09-13 16:28:14 -040085 int fDepth;
ethannicholascad64162016-10-27 10:54:02 -070086};
87
Brian Salomon140f3da2018-08-23 13:51:27 +000088std::unordered_map<String, Parser::LayoutToken>* Parser::layoutTokens;
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040089
90void Parser::InitLayoutMap() {
Brian Salomon140f3da2018-08-23 13:51:27 +000091 layoutTokens = new std::unordered_map<String, LayoutToken>;
Brian Salomon23356442018-11-30 15:33:19 -050092 #define TOKEN(name, text) (*layoutTokens)[text] = LayoutToken::name
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040093 TOKEN(LOCATION, "location");
94 TOKEN(OFFSET, "offset");
95 TOKEN(BINDING, "binding");
96 TOKEN(INDEX, "index");
97 TOKEN(SET, "set");
98 TOKEN(BUILTIN, "builtin");
99 TOKEN(INPUT_ATTACHMENT_INDEX, "input_attachment_index");
100 TOKEN(ORIGIN_UPPER_LEFT, "origin_upper_left");
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400101 TOKEN(BLEND_SUPPORT_ALL_EQUATIONS, "blend_support_all_equations");
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400102 TOKEN(PUSH_CONSTANT, "push_constant");
103 TOKEN(POINTS, "points");
104 TOKEN(LINES, "lines");
105 TOKEN(LINE_STRIP, "line_strip");
106 TOKEN(LINES_ADJACENCY, "lines_adjacency");
107 TOKEN(TRIANGLES, "triangles");
108 TOKEN(TRIANGLE_STRIP, "triangle_strip");
109 TOKEN(TRIANGLES_ADJACENCY, "triangles_adjacency");
110 TOKEN(MAX_VERTICES, "max_vertices");
111 TOKEN(INVOCATIONS, "invocations");
Brian Osmanb32d66b2020-04-30 17:12:03 -0400112 TOKEN(SRGB_UNPREMUL, "srgb_unpremul");
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400113 #undef TOKEN
114}
115
Ethan Nicholas6823b502021-06-15 11:42:07 -0400116Parser::Parser(skstd::string_view text, SymbolTable& symbols, ErrorReporter& errors)
117: fText(text)
John Stiles7cbb09c22021-01-07 16:07:00 -0500118, fPushback(Token::Kind::TK_NONE, -1, -1)
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400119, fSymbols(symbols)
Ethan Nicholas55478662021-08-10 17:14:26 -0400120, fErrors(&errors) {
Ethan Nicholas6823b502021-06-15 11:42:07 -0400121 fLexer.start(text);
Brian Salomon3b83afe2018-08-23 11:04:36 -0400122 static const bool layoutMapInitialized = []{ return (void)InitLayoutMap(), true; }();
123 (void) layoutMapInitialized;
ethannicholasb3058bd2016-07-01 08:22:01 -0700124}
125
John Stiles3b209362020-11-16 17:03:10 -0500126template <typename... Args>
127ASTNode::ID Parser::createNode(Args&&... args) {
128 ASTNode::ID result(fFile->fNodes.size());
129 fFile->fNodes.emplace_back(&fFile->fNodes, std::forward<Args>(args)...);
130 return result;
131}
Ethan Nicholasfc994162019-06-06 10:04:27 -0400132
John Stiles3b209362020-11-16 17:03:10 -0500133ASTNode::ID Parser::addChild(ASTNode::ID target, ASTNode::ID child) {
134 fFile->fNodes[target.fValue].addChild(child);
135 return child;
136}
Ethan Nicholasfc994162019-06-06 10:04:27 -0400137
John Stiles3b209362020-11-16 17:03:10 -0500138void Parser::createEmptyChild(ASTNode::ID target) {
139 ASTNode::ID child(fFile->fNodes.size());
140 fFile->fNodes.emplace_back();
141 fFile->fNodes[target.fValue].addChild(child);
142}
Ethan Nicholasfc994162019-06-06 10:04:27 -0400143
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400144/* (directive | section | declaration)* END_OF_FILE */
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500145std::unique_ptr<ASTFile> Parser::compilationUnit() {
John Stilesfbd050b2020-08-03 13:21:46 -0400146 fFile = std::make_unique<ASTFile>();
John Stiles18a45b32021-03-29 18:07:32 -0400147 fFile->fNodes.reserve(fText.size() / 10); // a typical program is approx 10:1 for chars:nodes
John Stiles3b209362020-11-16 17:03:10 -0500148 ASTNode::ID result = this->createNode(/*offset=*/0, ASTNode::Kind::kFile);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400149 fFile->fRoot = result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700150 for (;;) {
151 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400152 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholasfc994162019-06-06 10:04:27 -0400153 return std::move(fFile);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400154 case Token::Kind::TK_DIRECTIVE: {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400155 ASTNode::ID dir = this->directive();
Ethan Nicholas55478662021-08-10 17:14:26 -0400156 if (fErrors->errorCount()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400157 return nullptr;
158 }
159 if (dir) {
160 getNode(result).addChild(dir);
ethannicholasb3058bd2016-07-01 08:22:01 -0700161 }
162 break;
163 }
John Stiles7cbb09c22021-01-07 16:07:00 -0500164 case Token::Kind::TK_INVALID: {
165 this->error(this->peek(), String("invalid token"));
166 return nullptr;
167 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700168 default: {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400169 ASTNode::ID decl = this->declaration();
Ethan Nicholas55478662021-08-10 17:14:26 -0400170 if (fErrors->errorCount()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400171 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700172 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400173 if (decl) {
174 getNode(result).addChild(decl);
175 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700176 }
177 }
178 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400179 return std::move(fFile);
ethannicholasb3058bd2016-07-01 08:22:01 -0700180}
181
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700182Token Parser::nextRawToken() {
John Stiles7cbb09c22021-01-07 16:07:00 -0500183 if (fPushback.fKind != Token::Kind::TK_NONE) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700184 Token result = fPushback;
John Stiles7cbb09c22021-01-07 16:07:00 -0500185 fPushback.fKind = Token::Kind::TK_NONE;
ethannicholasb3058bd2016-07-01 08:22:01 -0700186 return result;
187 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700188 Token result = fLexer.next();
189 return result;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400190}
191
192Token Parser::nextToken() {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700193 Token token = this->nextRawToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400194 while (token.fKind == Token::Kind::TK_WHITESPACE ||
195 token.fKind == Token::Kind::TK_LINE_COMMENT ||
196 token.fKind == Token::Kind::TK_BLOCK_COMMENT) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700197 token = this->nextRawToken();
198 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400199 return token;
ethannicholasb3058bd2016-07-01 08:22:01 -0700200}
201
202void Parser::pushback(Token t) {
John Stiles7cbb09c22021-01-07 16:07:00 -0500203 SkASSERT(fPushback.fKind == Token::Kind::TK_NONE);
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400204 fPushback = std::move(t);
ethannicholasb3058bd2016-07-01 08:22:01 -0700205}
206
207Token Parser::peek() {
John Stiles7cbb09c22021-01-07 16:07:00 -0500208 if (fPushback.fKind == Token::Kind::TK_NONE) {
Brian Osman634624a2017-08-15 11:14:30 -0400209 fPushback = this->nextToken();
210 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700211 return fPushback;
212}
213
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400214bool Parser::checkNext(Token::Kind kind, Token* result) {
John Stiles7cbb09c22021-01-07 16:07:00 -0500215 if (fPushback.fKind != Token::Kind::TK_NONE && fPushback.fKind != kind) {
Brian Osman634624a2017-08-15 11:14:30 -0400216 return false;
217 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400218 Token next = this->nextToken();
219 if (next.fKind == kind) {
220 if (result) {
221 *result = next;
222 }
223 return true;
224 }
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400225 this->pushback(std::move(next));
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400226 return false;
227}
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500228
229bool Parser::expect(Token::Kind kind, const char* expected, Token* result) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700230 Token next = this->nextToken();
231 if (next.fKind == kind) {
232 if (result) {
Brian Osman634624a2017-08-15 11:14:30 -0400233 *result = std::move(next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700234 }
235 return true;
236 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700237 this->error(next, "expected " + String(expected) + ", but found '" +
238 this->text(next) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700239 return false;
240 }
241}
242
John Stiles2630ea32020-12-04 10:51:21 -0500243bool Parser::expectIdentifier(Token* result) {
244 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", result)) {
245 return false;
246 }
247 if (this->isType(this->text(*result))) {
248 this->error(*result, "expected an identifier, but found type '" +
249 this->text(*result) + "'");
250 return false;
251 }
252 return true;
253}
254
Ethan Nicholas962dec42021-06-10 13:06:39 -0400255skstd::string_view Parser::text(Token token) {
256 return skstd::string_view(fText.begin() + token.fOffset, token.fLength);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500257}
258
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700259void Parser::error(Token token, String msg) {
260 this->error(token.fOffset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -0700261}
262
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700263void Parser::error(int offset, String msg) {
Ethan Nicholas55478662021-08-10 17:14:26 -0400264 fErrors->error(offset, msg);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700265}
266
Ethan Nicholas962dec42021-06-10 13:06:39 -0400267bool Parser::isType(skstd::string_view name) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400268 const Symbol* s = fSymbols[name];
John Stiles2630ea32020-12-04 10:51:21 -0500269 return s && s->is<Type>();
ethannicholasb3058bd2016-07-01 08:22:01 -0700270}
271
John Stiles80b02af2021-02-12 17:07:51 -0500272bool Parser::isArrayType(ASTNode::ID type) {
273 const ASTNode& node = this->getNode(type);
274 SkASSERT(node.fKind == ASTNode::Kind::kType);
275 return node.begin() != node.end();
276}
277
Ethan Nicholas11d53972016-11-28 11:23:23 -0500278/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
ethannicholas5961bc92016-10-12 06:39:56 -0700279 DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400280ASTNode::ID Parser::directive() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700281 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400282 if (!this->expect(Token::Kind::TK_DIRECTIVE, "a directive", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400283 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700284 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400285 skstd::string_view text = this->text(start);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400286 if (text == "#extension") {
ethannicholasb3058bd2016-07-01 08:22:01 -0700287 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500288 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400289 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700290 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400291 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400292 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700293 }
294 // FIXME: need to start paying attention to this token
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400295 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400296 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700297 }
John Stiles3b209362020-11-16 17:03:10 -0500298 return this->createNode(start.fOffset, ASTNode::Kind::kExtension, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700299 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700300 this->error(start, "unsupported directive '" + this->text(start) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400301 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700302 }
303}
304
Brian Osmanc9145f32021-07-08 13:40:10 -0400305/* modifiers (interfaceBlock | structVarDeclaration | SEMICOLON |
John Stiles147cfda2021-05-21 14:11:38 -0400306 type IDENTIFIER (varDeclarationEnd | LPAREN functionDeclarationEnd))) */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400307ASTNode::ID Parser::declaration() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700308 Token lookahead = this->peek();
Ethan Nicholasda6320c2020-09-02 14:08:23 -0400309 switch (lookahead.fKind) {
Ethan Nicholasda6320c2020-09-02 14:08:23 -0400310 case Token::Kind::TK_SEMICOLON:
311 this->error(lookahead.fOffset, "expected a declaration, but found ';'");
312 return ASTNode::ID::Invalid();
313 default:
314 break;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500315 }
316 Modifiers modifiers = this->modifiers();
317 lookahead = this->peek();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400318 if (lookahead.fKind == Token::Kind::TK_IDENTIFIER && !this->isType(this->text(lookahead))) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700319 // we have an identifier that's not a type, could be the start of an interface block
320 return this->interfaceBlock(modifiers);
321 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400322 if (lookahead.fKind == Token::Kind::TK_STRUCT) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700323 return this->structVarDeclaration(modifiers);
324 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400325 if (lookahead.fKind == Token::Kind::TK_SEMICOLON) {
ethannicholas5961bc92016-10-12 06:39:56 -0700326 this->nextToken();
John Stiles3b209362020-11-16 17:03:10 -0500327 return this->createNode(lookahead.fOffset, ASTNode::Kind::kModifiers, modifiers);
ethannicholas5961bc92016-10-12 06:39:56 -0700328 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400329 ASTNode::ID type = this->type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700330 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400331 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700332 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700333 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500334 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400335 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700336 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400337 if (this->checkNext(Token::Kind::TK_LPAREN)) {
John Stiles147cfda2021-05-21 14:11:38 -0400338 return this->functionDeclarationEnd(modifiers, type, name);
ethannicholasb3058bd2016-07-01 08:22:01 -0700339 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400340 return this->varDeclarationEnd(modifiers, type, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700341 }
342}
343
John Stiles147cfda2021-05-21 14:11:38 -0400344/* (RPAREN | VOID RPAREN | parameter (COMMA parameter)* RPAREN) (block | SEMICOLON) */
345ASTNode::ID Parser::functionDeclarationEnd(Modifiers modifiers,
346 ASTNode::ID type,
347 const Token& name) {
348 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kFunction);
349 ASTNode::FunctionData fd(modifiers, this->text(name), 0);
350 getNode(result).addChild(type);
351 Token lookahead = this->peek();
352 if (lookahead.fKind == Token::Kind::TK_RPAREN) {
353 // `()` means no parameters at all.
354 } else if (lookahead.fKind == Token::Kind::TK_IDENTIFIER && this->text(lookahead) == "void") {
355 // `(void)` also means no parameters at all.
356 this->nextToken();
357 } else {
358 for (;;) {
359 ASTNode::ID parameter = this->parameter();
360 if (!parameter) {
361 return ASTNode::ID::Invalid();
362 }
363 ++fd.fParameterCount;
364 getNode(result).addChild(parameter);
365 if (!this->checkNext(Token::Kind::TK_COMMA)) {
366 break;
367 }
368 }
369 }
370 getNode(result).setFunctionData(fd);
371 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
372 return ASTNode::ID::Invalid();
373 }
374 ASTNode::ID body;
375 if (!this->checkNext(Token::Kind::TK_SEMICOLON)) {
376 body = this->block();
377 if (!body) {
378 return ASTNode::ID::Invalid();
379 }
380 getNode(result).addChild(body);
381 }
382 return result;
383}
384
John Stiles76389b72021-01-25 13:49:05 -0500385/* (varDeclarations | expressionStatement) */
386ASTNode::ID Parser::varDeclarationsOrExpressionStatement() {
John Stiles89b484a2021-04-19 14:57:27 -0400387 Token nextToken = this->peek();
388 if (nextToken.fKind == Token::Kind::TK_CONST) {
389 // Statements that begin with `const` might be variable declarations, but can't be legal
390 // SkSL expression-statements. (SkSL constructors don't take a `const` modifier.)
391 return this->varDeclarations();
392 }
393
John Stiles02014312021-08-04 16:03:12 -0400394 if (nextToken.fKind == Token::Kind::TK_HIGHP ||
395 nextToken.fKind == Token::Kind::TK_MEDIUMP ||
396 nextToken.fKind == Token::Kind::TK_LOWP ||
397 this->isType(this->text(nextToken))) {
John Stiles76389b72021-01-25 13:49:05 -0500398 // Statements that begin with a typename are most often variable declarations, but
399 // occasionally the type is part of a constructor, and these are actually expression-
400 // statements in disguise. First, attempt the common case: parse it as a vardecl.
401 Checkpoint checkpoint(this);
John Stiles8dabeac2021-02-12 16:05:00 -0500402 VarDeclarationsPrefix prefix;
403 if (this->varDeclarationsPrefix(&prefix)) {
Ethan Nicholas55478662021-08-10 17:14:26 -0400404 checkpoint.accept();
John Stiles8dabeac2021-02-12 16:05:00 -0500405 return this->varDeclarationEnd(prefix.modifiers, prefix.type, this->text(prefix.name));
John Stiles76389b72021-01-25 13:49:05 -0500406 }
407
408 // If this statement wasn't actually a vardecl after all, rewind and try parsing it as an
409 // expression-statement instead.
410 checkpoint.rewind();
411 }
412
413 return this->expressionStatement();
414}
415
John Stiles8dabeac2021-02-12 16:05:00 -0500416// Helper function for varDeclarations(). If this function succeeds, we assume that the rest of the
417// statement is a variable-declaration statement, not an expression-statement.
418bool Parser::varDeclarationsPrefix(VarDeclarationsPrefix* prefixData) {
419 prefixData->modifiers = this->modifiers();
420 prefixData->type = this->type();
421 if (!prefixData->type) {
422 return false;
423 }
424 return this->expectIdentifier(&prefixData->name);
425}
426
ethannicholasb3058bd2016-07-01 08:22:01 -0700427/* modifiers type IDENTIFIER varDeclarationEnd */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400428ASTNode::ID Parser::varDeclarations() {
John Stiles8dabeac2021-02-12 16:05:00 -0500429 VarDeclarationsPrefix prefix;
430 if (!this->varDeclarationsPrefix(&prefix)) {
John Stiles76389b72021-01-25 13:49:05 -0500431 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700432 }
John Stiles8dabeac2021-02-12 16:05:00 -0500433 return this->varDeclarationEnd(prefix.modifiers, prefix.type, this->text(prefix.name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700434}
435
436/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400437ASTNode::ID Parser::structDeclaration() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400438 if (!this->expect(Token::Kind::TK_STRUCT, "'struct'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400439 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700440 }
441 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500442 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400443 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700444 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400445 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400446 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700447 }
448 std::vector<Type::Field> fields;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400449 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400450 ASTNode::ID decls = this->varDeclarations();
451 if (!decls) {
452 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700453 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400454 ASTNode& declsNode = getNode(decls);
John Stilesece1bf02021-03-08 11:15:55 -0500455 const Modifiers& modifiers = declsNode.begin()->getModifiers();
John Stiles13fc2602020-10-09 17:42:31 -0400456 if (modifiers.fFlags != Modifiers::kNo_Flag) {
457 String desc = modifiers.description();
458 desc.pop_back(); // remove trailing space
459 this->error(declsNode.fOffset,
460 "modifier '" + desc + "' is not permitted on a struct field");
461 }
462
Ethan Nicholas962dec42021-06-10 13:06:39 -0400463 const Symbol* symbol = fSymbols[(declsNode.begin() + 1)->getStringView()];
John Stiles13fc2602020-10-09 17:42:31 -0400464 SkASSERT(symbol);
465 const Type* type = &symbol->as<Type>();
John Stiles1d757782020-11-17 09:43:22 -0500466 if (type->isOpaque()) {
467 this->error(declsNode.fOffset,
468 "opaque type '" + type->name() + "' is not permitted in a struct");
469 }
John Stiles13fc2602020-10-09 17:42:31 -0400470
Ethan Nicholasfc994162019-06-06 10:04:27 -0400471 for (auto iter = declsNode.begin() + 2; iter != declsNode.end(); ++iter) {
472 ASTNode& var = *iter;
John Stilesece1bf02021-03-08 11:15:55 -0500473 const ASTNode::VarData& vd = var.getVarData();
John Stiles6bef6a72020-12-02 14:26:04 -0500474
John Stilesd39aec92020-12-03 14:37:16 -0500475 // Read array size if one is present.
476 if (vd.fIsArray) {
477 const ASTNode& size = *var.begin();
Ethan Nicholasfc994162019-06-06 10:04:27 -0400478 if (!size || size.fKind != ASTNode::Kind::kInt) {
479 this->error(declsNode.fOffset, "array size in struct field must be a constant");
480 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700481 }
John Stiles6bef6a72020-12-02 14:26:04 -0500482 if (size.getInt() <= 0 || size.getInt() > INT_MAX) {
483 this->error(declsNode.fOffset, "array size is invalid");
484 return ASTNode::ID::Invalid();
485 }
John Stilesd39aec92020-12-03 14:37:16 -0500486 // Add the array dimensions to our type.
487 int arraySize = size.getInt();
John Stilesa2179502020-12-03 14:37:57 -0500488 type = fSymbols.addArrayDimension(type, arraySize);
ethannicholasb3058bd2016-07-01 08:22:01 -0700489 }
John Stiles13fc2602020-10-09 17:42:31 -0400490
491 fields.push_back(Type::Field(modifiers, vd.fName, type));
John Stilesd39aec92020-12-03 14:37:16 -0500492 if (vd.fIsArray ? var.begin()->fNext : var.fFirstChild) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400493 this->error(declsNode.fOffset, "initializers are not permitted on struct fields");
ethannicholasb3058bd2016-07-01 08:22:01 -0700494 }
495 }
496 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400497 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400498 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700499 }
Brian Osman6c3b23f2021-02-12 13:09:58 -0500500 if (fields.empty()) {
501 this->error(name.fOffset,
502 "struct '" + this->text(name) + "' must contain at least one field");
503 return ASTNode::ID::Invalid();
504 }
Ethan Nicholas27f06eb2021-07-26 16:39:40 -0400505 std::unique_ptr<Type> newType = Type::MakeStructType(name.fOffset, this->text(name), fields);
John Stilesa695d622020-11-10 10:04:26 -0500506 if (struct_is_too_deeply_nested(*newType, kMaxStructDepth)) {
507 this->error(name.fOffset, "struct '" + this->text(name) + "' is too deeply nested");
508 return ASTNode::ID::Invalid();
509 }
510 fSymbols.add(std::move(newType));
Brian Osman00fea5b2021-01-28 09:46:30 -0500511 return this->createNode(name.fOffset, ASTNode::Kind::kType, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700512}
513
514/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400515ASTNode::ID Parser::structVarDeclaration(Modifiers modifiers) {
516 ASTNode::ID type = this->structDeclaration();
ethannicholasb3058bd2016-07-01 08:22:01 -0700517 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400518 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700519 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400520 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400521 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400522 return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700523 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400524 this->expect(Token::Kind::TK_SEMICOLON, "';'");
John Stilesdc75a972020-11-25 16:24:55 -0500525 return type;
ethannicholasb3058bd2016-07-01 08:22:01 -0700526}
527
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400528/* (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)? (COMMA IDENTIFER
529 (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
Ethan Nicholas962dec42021-06-10 13:06:39 -0400530ASTNode::ID Parser::varDeclarationEnd(Modifiers mods, ASTNode::ID type, skstd::string_view name) {
John Stiles08070f62020-11-17 10:45:49 -0500531 int offset = this->peek().fOffset;
532 ASTNode::ID result = this->createNode(offset, ASTNode::Kind::kVarDeclarations);
533 this->addChild(result, this->createNode(offset, ASTNode::Kind::kModifiers, mods));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400534 getNode(result).addChild(type);
John Stilesd39aec92020-12-03 14:37:16 -0500535
John Stiles80b02af2021-02-12 17:07:51 -0500536 auto parseArrayDimensions = [&](ASTNode::ID currentVar, ASTNode::VarData* vd) -> bool {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400537 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stiles80b02af2021-02-12 17:07:51 -0500538 if (vd->fIsArray || this->isArrayType(type)) {
John Stilesd39aec92020-12-03 14:37:16 -0500539 this->error(this->peek(), "multi-dimensional arrays are not supported");
540 return false;
541 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400542 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
John Stiles3b209362020-11-16 17:03:10 -0500543 this->createEmptyChild(currentVar);
ethannicholasb3058bd2016-07-01 08:22:01 -0700544 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400545 ASTNode::ID size = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700546 if (!size) {
John Stilesd39aec92020-12-03 14:37:16 -0500547 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700548 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400549 getNode(currentVar).addChild(size);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400550 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
John Stilesd39aec92020-12-03 14:37:16 -0500551 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700552 }
553 }
John Stilesd39aec92020-12-03 14:37:16 -0500554 vd->fIsArray = true;
ethannicholasb3058bd2016-07-01 08:22:01 -0700555 }
John Stilesd39aec92020-12-03 14:37:16 -0500556 return true;
557 };
558
559 auto parseInitializer = [this](ASTNode::ID currentVar) -> bool {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400560 if (this->checkNext(Token::Kind::TK_EQ)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400561 ASTNode::ID value = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700562 if (!value) {
John Stilesd39aec92020-12-03 14:37:16 -0500563 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700564 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400565 getNode(currentVar).addChild(value);
ethannicholasb3058bd2016-07-01 08:22:01 -0700566 }
John Stilesd39aec92020-12-03 14:37:16 -0500567 return true;
568 };
569
570 ASTNode::ID currentVar = this->createNode(offset, ASTNode::Kind::kVarDeclaration);
571 ASTNode::VarData vd{name, /*isArray=*/false};
572
573 getNode(result).addChild(currentVar);
574 if (!parseArrayDimensions(currentVar, &vd)) {
575 return ASTNode::ID::Invalid();
576 }
577 getNode(currentVar).setVarData(vd);
578 if (!parseInitializer(currentVar)) {
579 return ASTNode::ID::Invalid();
580 }
581
582 while (this->checkNext(Token::Kind::TK_COMMA)) {
583 Token identifierName;
John Stiles2630ea32020-12-04 10:51:21 -0500584 if (!this->expectIdentifier(&identifierName)) {
John Stilesd39aec92020-12-03 14:37:16 -0500585 return ASTNode::ID::Invalid();
586 }
587
588 currentVar = ASTNode::ID(fFile->fNodes.size());
589 vd = ASTNode::VarData{this->text(identifierName), /*isArray=*/false};
590 fFile->fNodes.emplace_back(&fFile->fNodes, offset, ASTNode::Kind::kVarDeclaration);
591
592 getNode(result).addChild(currentVar);
593 if (!parseArrayDimensions(currentVar, &vd)) {
594 return ASTNode::ID::Invalid();
595 }
596 getNode(currentVar).setVarData(vd);
597 if (!parseInitializer(currentVar)) {
598 return ASTNode::ID::Invalid();
599 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700600 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400601 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400602 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700603 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400604 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700605}
606
607/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400608ASTNode::ID Parser::parameter() {
Ethan Nicholasc6f5e102017-03-31 14:53:17 -0400609 Modifiers modifiers = this->modifiersWithDefaults(0);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400610 ASTNode::ID type = this->type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700611 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400612 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700613 }
614 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500615 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400616 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700617 }
John Stiles3b209362020-11-16 17:03:10 -0500618 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kParameter);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400619 ASTNode::ParameterData pd(modifiers, this->text(name), 0);
620 getNode(result).addChild(type);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400621 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stiles80b02af2021-02-12 17:07:51 -0500622 if (pd.fIsArray || this->isArrayType(type)) {
John Stilesd39aec92020-12-03 14:37:16 -0500623 this->error(this->peek(), "multi-dimensional arrays are not supported");
624 return ASTNode::ID::Invalid();
625 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700626 Token sizeToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400627 if (!this->expect(Token::Kind::TK_INT_LITERAL, "a positive integer", &sizeToken)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400628 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700629 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400630 skstd::string_view arraySizeFrag = this->text(sizeToken);
John Stilesf94348f2020-12-23 18:58:43 -0500631 SKSL_INT arraySize;
632 if (!SkSL::stoi(arraySizeFrag, &arraySize)) {
633 this->error(sizeToken, "array size is too large: " + arraySizeFrag);
634 return ASTNode::ID::Invalid();
635 }
636 this->addChild(result, this->createNode(sizeToken.fOffset, ASTNode::Kind::kInt, arraySize));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400637 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400638 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700639 }
John Stilesd39aec92020-12-03 14:37:16 -0500640 pd.fIsArray = true;
ethannicholasb3058bd2016-07-01 08:22:01 -0700641 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400642 getNode(result).setParameterData(pd);
643 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700644}
645
Ethan Nicholasd608c092017-10-26 09:30:08 -0400646/** EQ INT_LITERAL */
ethannicholasb3058bd2016-07-01 08:22:01 -0700647int Parser::layoutInt() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400648 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700649 return -1;
650 }
651 Token resultToken;
John Stilesf94348f2020-12-23 18:58:43 -0500652 if (!this->expect(Token::Kind::TK_INT_LITERAL, "a non-negative integer", &resultToken)) {
653 return -1;
ethannicholasb3058bd2016-07-01 08:22:01 -0700654 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400655 skstd::string_view resultFrag = this->text(resultToken);
John Stilesf94348f2020-12-23 18:58:43 -0500656 SKSL_INT resultValue;
657 if (!SkSL::stoi(resultFrag, &resultValue)) {
658 this->error(resultToken, "value in layout is too large: " + resultFrag);
659 return -1;
660 }
661 return resultValue;
ethannicholasb3058bd2016-07-01 08:22:01 -0700662}
663
Ethan Nicholasd608c092017-10-26 09:30:08 -0400664/** EQ IDENTIFIER */
Ethan Nicholas962dec42021-06-10 13:06:39 -0400665skstd::string_view Parser::layoutIdentifier() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400666 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
Ethan Nicholas962dec42021-06-10 13:06:39 -0400667 return skstd::string_view();
Ethan Nicholasd608c092017-10-26 09:30:08 -0400668 }
669 Token resultToken;
John Stiles2630ea32020-12-04 10:51:21 -0500670 if (!this->expectIdentifier(&resultToken)) {
Ethan Nicholas962dec42021-06-10 13:06:39 -0400671 return skstd::string_view();
Ethan Nicholasd608c092017-10-26 09:30:08 -0400672 }
673 return this->text(resultToken);
674}
675
ethannicholas8ac838d2016-11-22 08:39:36 -0800676/* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500677Layout Parser::layout() {
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500678 int flags = 0;
ethannicholasb3058bd2016-07-01 08:22:01 -0700679 int location = -1;
Ethan Nicholas19671772016-11-28 16:30:17 -0500680 int offset = -1;
ethannicholasb3058bd2016-07-01 08:22:01 -0700681 int binding = -1;
682 int index = -1;
683 int set = -1;
684 int builtin = -1;
Greg Daniel64773e62016-11-22 09:44:03 -0500685 int inputAttachmentIndex = -1;
Ethan Nicholas52cad152017-02-16 16:37:32 -0500686 Layout::Primitive primitive = Layout::kUnspecified_Primitive;
687 int maxVertices = -1;
688 int invocations = -1;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400689 if (this->checkNext(Token::Kind::TK_LAYOUT)) {
690 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500691 return Layout(flags, location, offset, binding, index, set, builtin,
Brian Osman8c264792021-07-01 16:41:27 -0400692 inputAttachmentIndex, primitive, maxVertices, invocations);
ethannicholasb3058bd2016-07-01 08:22:01 -0700693 }
694 for (;;) {
695 Token t = this->nextToken();
Ethan Nicholasd2e09602021-06-10 11:21:59 -0400696 String text(this->text(t));
Brian Osmana77ed8b2021-02-23 12:54:22 -0500697 auto setFlag = [&](Layout::Flag f) {
698 if (flags & f) {
699 this->error(t, "layout qualifier '" + text + "' appears more than once");
700 }
701 flags |= f;
702 };
703 auto setPrimitive = [&](Layout::Primitive p) {
704 if (flags & Layout::kPrimitive_Flag) {
705 this->error(t, "only one primitive-type layout qualifier is allowed");
706 }
707 flags |= Layout::kPrimitive_Flag;
708 primitive = p;
709 };
710
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400711 auto found = layoutTokens->find(text);
712 if (found != layoutTokens->end()) {
713 switch (found->second) {
Brian Osmana77ed8b2021-02-23 12:54:22 -0500714 case LayoutToken::ORIGIN_UPPER_LEFT:
715 setFlag(Layout::kOriginUpperLeft_Flag);
716 break;
Brian Osmana77ed8b2021-02-23 12:54:22 -0500717 case LayoutToken::PUSH_CONSTANT:
718 setFlag(Layout::kPushConstant_Flag);
719 break;
720 case LayoutToken::BLEND_SUPPORT_ALL_EQUATIONS:
721 setFlag(Layout::kBlendSupportAllEquations_Flag);
722 break;
Brian Osmana77ed8b2021-02-23 12:54:22 -0500723 case LayoutToken::SRGB_UNPREMUL:
724 setFlag(Layout::kSRGBUnpremul_Flag);
725 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700726 case LayoutToken::LOCATION:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500727 setFlag(Layout::kLocation_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500728 location = this->layoutInt();
729 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700730 case LayoutToken::OFFSET:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500731 setFlag(Layout::kOffset_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500732 offset = this->layoutInt();
733 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700734 case LayoutToken::BINDING:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500735 setFlag(Layout::kBinding_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500736 binding = this->layoutInt();
737 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700738 case LayoutToken::INDEX:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500739 setFlag(Layout::kIndex_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500740 index = this->layoutInt();
741 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700742 case LayoutToken::SET:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500743 setFlag(Layout::kSet_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500744 set = this->layoutInt();
745 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700746 case LayoutToken::BUILTIN:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500747 setFlag(Layout::kBuiltin_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500748 builtin = this->layoutInt();
749 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700750 case LayoutToken::INPUT_ATTACHMENT_INDEX:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500751 setFlag(Layout::kInputAttachmentIndex_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500752 inputAttachmentIndex = this->layoutInt();
753 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700754 case LayoutToken::POINTS:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500755 setPrimitive(Layout::kPoints_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500756 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700757 case LayoutToken::LINES:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500758 setPrimitive(Layout::kLines_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500759 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700760 case LayoutToken::LINE_STRIP:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500761 setPrimitive(Layout::kLineStrip_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500762 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700763 case LayoutToken::LINES_ADJACENCY:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500764 setPrimitive(Layout::kLinesAdjacency_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500765 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700766 case LayoutToken::TRIANGLES:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500767 setPrimitive(Layout::kTriangles_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500768 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700769 case LayoutToken::TRIANGLE_STRIP:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500770 setPrimitive(Layout::kTriangleStrip_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500771 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700772 case LayoutToken::TRIANGLES_ADJACENCY:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500773 setPrimitive(Layout::kTrianglesAdjacency_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500774 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700775 case LayoutToken::MAX_VERTICES:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500776 setFlag(Layout::kMaxVertices_Flag);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500777 maxVertices = this->layoutInt();
778 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700779 case LayoutToken::INVOCATIONS:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500780 setFlag(Layout::kInvocations_Flag);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500781 invocations = this->layoutInt();
782 break;
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400783 default:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500784 this->error(t, "'" + text + "' is not a valid layout qualifier");
Ethan Nicholasd608c092017-10-26 09:30:08 -0400785 break;
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500786 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700787 } else {
Brian Osmana77ed8b2021-02-23 12:54:22 -0500788 this->error(t, "'" + text + "' is not a valid layout qualifier");
ethannicholasb3058bd2016-07-01 08:22:01 -0700789 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400790 if (this->checkNext(Token::Kind::TK_RPAREN)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700791 break;
792 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400793 if (!this->expect(Token::Kind::TK_COMMA, "','")) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700794 break;
795 }
796 }
797 }
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500798 return Layout(flags, location, offset, binding, index, set, builtin, inputAttachmentIndex,
Brian Osman8c264792021-07-01 16:41:27 -0400799 primitive, maxVertices, invocations);
ethannicholasb3058bd2016-07-01 08:22:01 -0700800}
801
Brian Osmane49703f2021-04-19 11:15:24 -0400802/* layout? (UNIFORM | CONST | IN | OUT | INOUT | FLAT | NOPERSPECTIVE | INLINE)* */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500803Modifiers Parser::modifiers() {
804 Layout layout = this->layout();
ethannicholasb3058bd2016-07-01 08:22:01 -0700805 int flags = 0;
806 for (;;) {
807 // TODO: handle duplicate / incompatible flags
John Stiles7d5b90a2021-01-21 14:26:51 -0500808 int tokenFlag = parse_modifier_token(peek().fKind);
809 if (!tokenFlag) {
810 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700811 }
John Stiles7d5b90a2021-01-21 14:26:51 -0500812 flags |= tokenFlag;
813 this->nextToken();
ethannicholasb3058bd2016-07-01 08:22:01 -0700814 }
John Stiles7d5b90a2021-01-21 14:26:51 -0500815 return Modifiers(layout, flags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700816}
817
Ethan Nicholas11d53972016-11-28 11:23:23 -0500818Modifiers Parser::modifiersWithDefaults(int defaultFlags) {
819 Modifiers result = this->modifiers();
ethannicholasb3058bd2016-07-01 08:22:01 -0700820 if (!result.fFlags) {
Ethan Nicholas11d53972016-11-28 11:23:23 -0500821 return Modifiers(result.fLayout, defaultFlags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700822 }
823 return result;
824}
825
826/* ifStatement | forStatement | doStatement | whileStatement | block | expression */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400827ASTNode::ID Parser::statement() {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -0400828 Token start = this->nextToken();
829 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -0400830 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -0400831 return ASTNode::ID::Invalid();
832 }
833 this->pushback(start);
ethannicholasb3058bd2016-07-01 08:22:01 -0700834 switch (start.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400835 case Token::Kind::TK_IF: // fall through
836 case Token::Kind::TK_STATIC_IF:
ethannicholasb3058bd2016-07-01 08:22:01 -0700837 return this->ifStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400838 case Token::Kind::TK_FOR:
ethannicholasb3058bd2016-07-01 08:22:01 -0700839 return this->forStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400840 case Token::Kind::TK_DO:
ethannicholasb3058bd2016-07-01 08:22:01 -0700841 return this->doStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400842 case Token::Kind::TK_WHILE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700843 return this->whileStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400844 case Token::Kind::TK_SWITCH: // fall through
845 case Token::Kind::TK_STATIC_SWITCH:
Ethan Nicholasaf197692017-02-27 13:26:45 -0500846 return this->switchStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400847 case Token::Kind::TK_RETURN:
ethannicholasb3058bd2016-07-01 08:22:01 -0700848 return this->returnStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400849 case Token::Kind::TK_BREAK:
ethannicholasb3058bd2016-07-01 08:22:01 -0700850 return this->breakStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400851 case Token::Kind::TK_CONTINUE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700852 return this->continueStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400853 case Token::Kind::TK_DISCARD:
ethannicholasb3058bd2016-07-01 08:22:01 -0700854 return this->discardStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400855 case Token::Kind::TK_LBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700856 return this->block();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400857 case Token::Kind::TK_SEMICOLON:
Ethan Nicholas11d53972016-11-28 11:23:23 -0500858 this->nextToken();
John Stiles3b209362020-11-16 17:03:10 -0500859 return this->createNode(start.fOffset, ASTNode::Kind::kBlock);
John Stiles02014312021-08-04 16:03:12 -0400860 case Token::Kind::TK_HIGHP:
861 case Token::Kind::TK_MEDIUMP:
862 case Token::Kind::TK_LOWP:
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400863 case Token::Kind::TK_CONST:
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400864 case Token::Kind::TK_IDENTIFIER:
John Stiles76389b72021-01-25 13:49:05 -0500865 return this->varDeclarationsOrExpressionStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700866 default:
867 return this->expressionStatement();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500868 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700869}
870
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500871/* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* QUESTION? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400872ASTNode::ID Parser::type() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700873 Token type;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400874 if (!this->expect(Token::Kind::TK_IDENTIFIER, "a type", &type)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400875 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700876 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700877 if (!this->isType(this->text(type))) {
878 this->error(type, ("no type named '" + this->text(type) + "'").c_str());
Ethan Nicholasfc994162019-06-06 10:04:27 -0400879 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700880 }
Brian Osman00fea5b2021-01-28 09:46:30 -0500881 ASTNode::ID result = this->createNode(type.fOffset, ASTNode::Kind::kType, this->text(type));
John Stilesd39aec92020-12-03 14:37:16 -0500882 bool isArray = false;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400883 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stilesd39aec92020-12-03 14:37:16 -0500884 if (isArray) {
885 this->error(this->peek(), "multi-dimensional arrays are not supported");
886 return ASTNode::ID::Invalid();
887 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400888 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400889 SKSL_INT i;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500890 if (this->intLiteral(&i)) {
John Stiles08070f62020-11-17 10:45:49 -0500891 this->addChild(result, this->createNode(this->peek().fOffset,
892 ASTNode::Kind::kInt, i));
Ethan Nicholas50afc172017-02-16 14:49:57 -0500893 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400894 return ASTNode::ID::Invalid();
Ethan Nicholas50afc172017-02-16 14:49:57 -0500895 }
896 } else {
John Stiles3b209362020-11-16 17:03:10 -0500897 this->createEmptyChild(result);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500898 }
John Stilesd39aec92020-12-03 14:37:16 -0500899 isArray = true;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400900 this->expect(Token::Kind::TK_RBRACKET, "']'");
Ethan Nicholas50afc172017-02-16 14:49:57 -0500901 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400902 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700903}
904
John Stiles57a996b2020-04-19 19:05:12 -0700905/* IDENTIFIER LBRACE
906 varDeclaration+
907 RBRACE (IDENTIFIER (LBRACKET expression? RBRACKET)*)? SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400908ASTNode::ID Parser::interfaceBlock(Modifiers mods) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700909 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500910 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400911 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700912 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400913 if (peek().fKind != Token::Kind::TK_LBRACE) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700914 // we only get into interfaceBlock if we found a top-level identifier which was not a type.
Ethan Nicholas11d53972016-11-28 11:23:23 -0500915 // 99% of the time, the user was not actually intending to create an interface block, so
ethannicholasb3058bd2016-07-01 08:22:01 -0700916 // it's better to report it as an unknown type
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700917 this->error(name, "no type named '" + this->text(name) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400918 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700919 }
John Stiles3b209362020-11-16 17:03:10 -0500920 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kInterfaceBlock);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400921 ASTNode::InterfaceBlockData id(mods, this->text(name), 0, "", 0);
ethannicholasb3058bd2016-07-01 08:22:01 -0700922 this->nextToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400923 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400924 ASTNode::ID decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700925 if (!decl) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400926 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700927 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400928 getNode(result).addChild(decl);
929 ++id.fDeclarationCount;
ethannicholasb3058bd2016-07-01 08:22:01 -0700930 }
John Stiles57a996b2020-04-19 19:05:12 -0700931 if (id.fDeclarationCount == 0) {
932 this->error(name, "interface block '" + this->text(name) +
933 "' must contain at least one member");
934 return ASTNode::ID::Invalid();
935 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700936 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -0400937 std::vector<ASTNode> sizes;
Ethan Nicholas962dec42021-06-10 13:06:39 -0400938 skstd::string_view instanceName;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700939 Token instanceNameToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400940 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &instanceNameToken)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400941 id.fInstanceName = this->text(instanceNameToken);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400942 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stilesd39aec92020-12-03 14:37:16 -0500943 if (id.fIsArray) {
944 this->error(this->peek(), "multi-dimensional arrays are not supported");
945 return false;
946 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400947 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400948 ASTNode::ID size = this->expression();
Ethan Nicholas50afc172017-02-16 14:49:57 -0500949 if (!size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400950 return ASTNode::ID::Invalid();
Ethan Nicholas50afc172017-02-16 14:49:57 -0500951 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400952 getNode(result).addChild(size);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500953 } else {
John Stiles3b209362020-11-16 17:03:10 -0500954 this->createEmptyChild(result);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500955 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400956 this->expect(Token::Kind::TK_RBRACKET, "']'");
John Stilesd39aec92020-12-03 14:37:16 -0500957 id.fIsArray = true;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500958 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700959 instanceName = this->text(instanceNameToken);
ethannicholasb3058bd2016-07-01 08:22:01 -0700960 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400961 getNode(result).setInterfaceBlockData(id);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400962 this->expect(Token::Kind::TK_SEMICOLON, "';'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400963 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700964}
965
966/* IF LPAREN expression RPAREN statement (ELSE statement)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400967ASTNode::ID Parser::ifStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700968 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400969 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_IF, &start);
970 if (!isStatic && !this->expect(Token::Kind::TK_IF, "'if'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400971 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700972 }
John Stiles3b209362020-11-16 17:03:10 -0500973 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kIf, isStatic);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400974 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400975 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700976 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400977 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700978 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400979 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700980 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400981 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400982 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400983 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700984 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400985 ASTNode::ID ifTrue = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700986 if (!ifTrue) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400987 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700988 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400989 getNode(result).addChild(ifTrue);
990 ASTNode::ID ifFalse;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400991 if (this->checkNext(Token::Kind::TK_ELSE)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700992 ifFalse = this->statement();
993 if (!ifFalse) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400994 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700995 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400996 getNode(result).addChild(ifFalse);
ethannicholasb3058bd2016-07-01 08:22:01 -0700997 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400998 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700999}
1000
1001/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001002ASTNode::ID Parser::doStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001003 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001004 if (!this->expect(Token::Kind::TK_DO, "'do'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001005 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001006 }
John Stiles3b209362020-11-16 17:03:10 -05001007 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kDo);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001008 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001009 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001010 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001011 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001012 getNode(result).addChild(statement);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001013 if (!this->expect(Token::Kind::TK_WHILE, "'while'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001014 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001015 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001016 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001017 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001018 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001019 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001020 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001021 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001022 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001023 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001024 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001025 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001026 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001027 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001028 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001029 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001030 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001031}
1032
1033/* WHILE LPAREN expression RPAREN STATEMENT */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001034ASTNode::ID Parser::whileStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001035 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001036 if (!this->expect(Token::Kind::TK_WHILE, "'while'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001037 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001038 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001039 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001040 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001041 }
John Stiles3b209362020-11-16 17:03:10 -05001042 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kWhile);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001043 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001044 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001045 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001046 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001047 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001048 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001049 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001050 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001051 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001052 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001053 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001054 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001055 getNode(result).addChild(statement);
1056 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001057}
1058
Ethan Nicholasaf197692017-02-27 13:26:45 -05001059/* CASE expression COLON statement* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001060ASTNode::ID Parser::switchCase() {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001061 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001062 if (!this->expect(Token::Kind::TK_CASE, "'case'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001063 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001064 }
John Stiles3b209362020-11-16 17:03:10 -05001065 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kSwitchCase);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001066 ASTNode::ID value = this->expression();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001067 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001068 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001069 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001070 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001071 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001072 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001073 getNode(result).addChild(value);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001074 while (this->peek().fKind != Token::Kind::TK_RBRACE &&
1075 this->peek().fKind != Token::Kind::TK_CASE &&
1076 this->peek().fKind != Token::Kind::TK_DEFAULT) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001077 ASTNode::ID s = this->statement();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001078 if (!s) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001079 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001080 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001081 getNode(result).addChild(s);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001082 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001083 return result;
Ethan Nicholasaf197692017-02-27 13:26:45 -05001084}
1085
1086/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001087ASTNode::ID Parser::switchStatement() {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001088 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001089 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_SWITCH, &start);
1090 if (!isStatic && !this->expect(Token::Kind::TK_SWITCH, "'switch'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001091 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001092 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001093 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001094 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001095 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001096 ASTNode::ID value = this->expression();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001097 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001098 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001099 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001100 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001101 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001102 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001103 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001104 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001105 }
John Stiles3b209362020-11-16 17:03:10 -05001106 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kSwitch, isStatic);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001107 getNode(result).addChild(value);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001108 while (this->peek().fKind == Token::Kind::TK_CASE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001109 ASTNode::ID c = this->switchCase();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001110 if (!c) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001111 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001112 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001113 getNode(result).addChild(c);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001114 }
1115 // Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
1116 // parts of the compiler may rely upon this assumption.
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001117 if (this->peek().fKind == Token::Kind::TK_DEFAULT) {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001118 Token defaultStart;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001119 SkAssertResult(this->expect(Token::Kind::TK_DEFAULT, "'default'", &defaultStart));
1120 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001121 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001122 }
John Stiles3b209362020-11-16 17:03:10 -05001123 ASTNode::ID defaultCase = this->addChild(
1124 result, this->createNode(defaultStart.fOffset, ASTNode::Kind::kSwitchCase));
1125 this->createEmptyChild(defaultCase); // empty test to signify default case
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001126 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001127 ASTNode::ID s = this->statement();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001128 if (!s) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001129 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001130 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001131 getNode(defaultCase).addChild(s);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001132 }
Ethan Nicholasaf197692017-02-27 13:26:45 -05001133 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001134 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001135 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001136 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001137 return result;
Ethan Nicholasaf197692017-02-27 13:26:45 -05001138}
1139
Ethan Nicholas11d53972016-11-28 11:23:23 -05001140/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
ethannicholasb3058bd2016-07-01 08:22:01 -07001141 STATEMENT */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001142ASTNode::ID Parser::forStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001143 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001144 if (!this->expect(Token::Kind::TK_FOR, "'for'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001145 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001146 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001147 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001148 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001149 }
John Stiles3b209362020-11-16 17:03:10 -05001150 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kFor);
ethannicholasb3058bd2016-07-01 08:22:01 -07001151 Token nextToken = this->peek();
John Stiles89b484a2021-04-19 14:57:27 -04001152 if (nextToken.fKind == Token::Kind::TK_SEMICOLON) {
1153 // An empty init-statement.
1154 this->nextToken();
1155 this->createEmptyChild(result);
1156 } else {
1157 // The init-statement must be an expression or variable declaration.
1158 ASTNode::ID initializer = this->varDeclarationsOrExpressionStatement();
1159 if (!initializer) {
1160 return ASTNode::ID::Invalid();
ethannicholasa54401d2016-10-14 08:37:32 -07001161 }
John Stiles89b484a2021-04-19 14:57:27 -04001162 getNode(result).addChild(initializer);
ethannicholasb3058bd2016-07-01 08:22:01 -07001163 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001164 ASTNode::ID test;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001165 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001166 test = this->expression();
1167 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001168 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001169 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001170 getNode(result).addChild(test);
1171 } else {
John Stiles3b209362020-11-16 17:03:10 -05001172 this->createEmptyChild(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001173 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001174 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001175 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001176 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001177 ASTNode::ID next;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001178 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001179 next = this->expression();
1180 if (!next) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001181 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001182 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001183 getNode(result).addChild(next);
1184 } else {
John Stiles3b209362020-11-16 17:03:10 -05001185 this->createEmptyChild(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001186 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001187 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001188 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001189 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001190 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001191 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001192 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001193 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001194 getNode(result).addChild(statement);
1195 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001196}
1197
1198/* RETURN expression? SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001199ASTNode::ID Parser::returnStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001200 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001201 if (!this->expect(Token::Kind::TK_RETURN, "'return'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001202 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001203 }
John Stiles3b209362020-11-16 17:03:10 -05001204 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kReturn);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001205 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001206 ASTNode::ID expression = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001207 if (!expression) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001208 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001209 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001210 getNode(result).addChild(expression);
ethannicholasb3058bd2016-07-01 08:22:01 -07001211 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001212 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001213 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001214 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001215 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001216}
1217
1218/* BREAK SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001219ASTNode::ID Parser::breakStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001220 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001221 if (!this->expect(Token::Kind::TK_BREAK, "'break'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001222 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001223 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001224 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001225 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001226 }
John Stiles3b209362020-11-16 17:03:10 -05001227 return this->createNode(start.fOffset, ASTNode::Kind::kBreak);
ethannicholasb3058bd2016-07-01 08:22:01 -07001228}
1229
1230/* CONTINUE SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001231ASTNode::ID Parser::continueStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001232 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001233 if (!this->expect(Token::Kind::TK_CONTINUE, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001234 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001235 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001236 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001237 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001238 }
John Stiles3b209362020-11-16 17:03:10 -05001239 return this->createNode(start.fOffset, ASTNode::Kind::kContinue);
ethannicholasb3058bd2016-07-01 08:22:01 -07001240}
1241
1242/* DISCARD SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001243ASTNode::ID Parser::discardStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001244 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001245 if (!this->expect(Token::Kind::TK_DISCARD, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001246 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001247 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001248 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001249 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001250 }
John Stiles3b209362020-11-16 17:03:10 -05001251 return this->createNode(start.fOffset, ASTNode::Kind::kDiscard);
ethannicholasb3058bd2016-07-01 08:22:01 -07001252}
1253
1254/* LBRACE statement* RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001255ASTNode::ID Parser::block() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001256 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001257 if (!this->expect(Token::Kind::TK_LBRACE, "'{'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001258 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001259 }
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001260 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001261 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001262 return ASTNode::ID::Invalid();
1263 }
John Stiles3b209362020-11-16 17:03:10 -05001264 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kBlock);
ethannicholasb3058bd2016-07-01 08:22:01 -07001265 for (;;) {
1266 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001267 case Token::Kind::TK_RBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -07001268 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001269 return result;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001270 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001271 this->error(this->peek(), "expected '}', but found end of file");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001272 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001273 default: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001274 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001275 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001276 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001277 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001278 getNode(result).addChild(statement);
ethannicholasb3058bd2016-07-01 08:22:01 -07001279 }
1280 }
1281 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001282 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001283}
1284
1285/* expression SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001286ASTNode::ID Parser::expressionStatement() {
1287 ASTNode::ID expr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001288 if (expr) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001289 if (this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001290 return expr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001291 }
1292 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001293 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001294}
1295
1296/* assignmentExpression (COMMA assignmentExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001297ASTNode::ID Parser::expression() {
1298 ASTNode::ID result = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001299 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001300 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001301 }
1302 Token t;
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001303 AutoDepth depth(this);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001304 while (this->checkNext(Token::Kind::TK_COMMA, &t)) {
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001305 if (!depth.increase()) {
1306 return ASTNode::ID::Invalid();
1307 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001308 ASTNode::ID right = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001309 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001310 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001311 }
John Stiles45990502021-02-16 10:55:27 -05001312 ASTNode::ID newResult = this->createNode(t.fOffset, ASTNode::Kind::kBinary,
1313 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001314 getNode(newResult).addChild(result);
1315 getNode(newResult).addChild(right);
1316 result = newResult;
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001317 }
1318 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001319}
1320
1321/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1322 BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1323 assignmentExpression)*
1324 */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001325ASTNode::ID Parser::assignmentExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001326 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001327 ASTNode::ID result = this->ternaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001328 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001329 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001330 }
1331 for (;;) {
1332 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001333 case Token::Kind::TK_EQ: // fall through
1334 case Token::Kind::TK_STAREQ: // fall through
1335 case Token::Kind::TK_SLASHEQ: // fall through
1336 case Token::Kind::TK_PERCENTEQ: // fall through
1337 case Token::Kind::TK_PLUSEQ: // fall through
1338 case Token::Kind::TK_MINUSEQ: // fall through
1339 case Token::Kind::TK_SHLEQ: // fall through
1340 case Token::Kind::TK_SHREQ: // fall through
1341 case Token::Kind::TK_BITWISEANDEQ: // fall through
1342 case Token::Kind::TK_BITWISEXOREQ: // fall through
John Stiles8b3b1592020-11-23 11:06:44 -05001343 case Token::Kind::TK_BITWISEOREQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001344 if (!depth.increase()) {
1345 return ASTNode::ID::Invalid();
1346 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001347 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001348 ASTNode::ID right = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001349 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001350 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001351 }
John Stiles3b209362020-11-16 17:03:10 -05001352 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001353 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001354 getNode(newResult).addChild(result);
1355 getNode(newResult).addChild(right);
1356 result = newResult;
1357 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001358 }
1359 default:
1360 return result;
1361 }
1362 }
1363}
1364
1365/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001366ASTNode::ID Parser::ternaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001367 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001368 ASTNode::ID base = this->logicalOrExpression();
1369 if (!base) {
1370 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001371 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001372 if (this->checkNext(Token::Kind::TK_QUESTION)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001373 if (!depth.increase()) {
1374 return ASTNode::ID::Invalid();
1375 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001376 ASTNode::ID trueExpr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001377 if (!trueExpr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001378 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001379 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001380 if (this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001381 ASTNode::ID falseExpr = this->assignmentExpression();
1382 if (!falseExpr) {
1383 return ASTNode::ID::Invalid();
1384 }
John Stiles3b209362020-11-16 17:03:10 -05001385 ASTNode::ID ternary = this->createNode(getNode(base).fOffset, ASTNode::Kind::kTernary);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001386 getNode(ternary).addChild(base);
1387 getNode(ternary).addChild(trueExpr);
1388 getNode(ternary).addChild(falseExpr);
1389 return ternary;
ethannicholasb3058bd2016-07-01 08:22:01 -07001390 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001391 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001392 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001393 return base;
ethannicholasb3058bd2016-07-01 08:22:01 -07001394}
1395
1396/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001397ASTNode::ID Parser::logicalOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001398 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001399 ASTNode::ID result = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001400 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001401 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001402 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001403 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001404 while (this->checkNext(Token::Kind::TK_LOGICALOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001405 if (!depth.increase()) {
1406 return ASTNode::ID::Invalid();
1407 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001408 ASTNode::ID right = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001409 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001410 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001411 }
John Stiles3b209362020-11-16 17:03:10 -05001412 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001413 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001414 getNode(newResult).addChild(result);
1415 getNode(newResult).addChild(right);
1416 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001417 }
1418 return result;
1419}
1420
1421/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001422ASTNode::ID Parser::logicalXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001423 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001424 ASTNode::ID result = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001425 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001426 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001427 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001428 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001429 while (this->checkNext(Token::Kind::TK_LOGICALXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001430 if (!depth.increase()) {
1431 return ASTNode::ID::Invalid();
1432 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001433 ASTNode::ID right = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001434 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001435 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001436 }
John Stiles3b209362020-11-16 17:03:10 -05001437 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001438 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001439 getNode(newResult).addChild(result);
1440 getNode(newResult).addChild(right);
1441 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001442 }
1443 return result;
1444}
1445
1446/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001447ASTNode::ID Parser::logicalAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001448 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001449 ASTNode::ID result = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001450 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001451 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001452 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001453 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001454 while (this->checkNext(Token::Kind::TK_LOGICALAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001455 if (!depth.increase()) {
1456 return ASTNode::ID::Invalid();
1457 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001458 ASTNode::ID right = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001459 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001460 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001461 }
John Stiles3b209362020-11-16 17:03:10 -05001462 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001463 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001464 getNode(newResult).addChild(result);
1465 getNode(newResult).addChild(right);
1466 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001467 }
1468 return result;
1469}
1470
1471/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001472ASTNode::ID Parser::bitwiseOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001473 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001474 ASTNode::ID result = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001475 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001476 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001477 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001478 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001479 while (this->checkNext(Token::Kind::TK_BITWISEOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001480 if (!depth.increase()) {
1481 return ASTNode::ID::Invalid();
1482 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001483 ASTNode::ID right = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001484 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001485 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001486 }
John Stiles45990502021-02-16 10:55:27 -05001487 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
1488 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001489 getNode(newResult).addChild(result);
1490 getNode(newResult).addChild(right);
1491 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001492 }
1493 return result;
1494}
1495
1496/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001497ASTNode::ID Parser::bitwiseXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001498 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001499 ASTNode::ID result = this->bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001500 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001501 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001502 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001503 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001504 while (this->checkNext(Token::Kind::TK_BITWISEXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001505 if (!depth.increase()) {
1506 return ASTNode::ID::Invalid();
1507 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001508 ASTNode::ID right = this->bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001509 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001510 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001511 }
John Stiles45990502021-02-16 10:55:27 -05001512 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
1513 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001514 getNode(newResult).addChild(result);
1515 getNode(newResult).addChild(right);
1516 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001517 }
1518 return result;
1519}
1520
1521/* equalityExpression (BITWISEAND equalityExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001522ASTNode::ID Parser::bitwiseAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001523 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001524 ASTNode::ID result = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001525 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001526 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001527 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001528 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001529 while (this->checkNext(Token::Kind::TK_BITWISEAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001530 if (!depth.increase()) {
1531 return ASTNode::ID::Invalid();
1532 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001533 ASTNode::ID right = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001534 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001535 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001536 }
John Stiles3b209362020-11-16 17:03:10 -05001537 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001538 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001539 getNode(newResult).addChild(result);
1540 getNode(newResult).addChild(right);
1541 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001542 }
1543 return result;
1544}
1545
1546/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001547ASTNode::ID Parser::equalityExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001548 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001549 ASTNode::ID result = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001550 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001551 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001552 }
1553 for (;;) {
1554 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001555 case Token::Kind::TK_EQEQ: // fall through
1556 case Token::Kind::TK_NEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001557 if (!depth.increase()) {
1558 return ASTNode::ID::Invalid();
1559 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001560 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001561 ASTNode::ID right = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001562 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001563 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001564 }
John Stiles3b209362020-11-16 17:03:10 -05001565 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001566 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001567 getNode(newResult).addChild(result);
1568 getNode(newResult).addChild(right);
1569 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001570 break;
1571 }
1572 default:
1573 return result;
1574 }
1575 }
1576}
1577
1578/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001579ASTNode::ID Parser::relationalExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001580 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001581 ASTNode::ID result = this->shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001582 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001583 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001584 }
1585 for (;;) {
1586 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001587 case Token::Kind::TK_LT: // fall through
1588 case Token::Kind::TK_GT: // fall through
1589 case Token::Kind::TK_LTEQ: // fall through
1590 case Token::Kind::TK_GTEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001591 if (!depth.increase()) {
1592 return ASTNode::ID::Invalid();
1593 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001594 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001595 ASTNode::ID right = this->shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001596 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001597 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001598 }
John Stiles3b209362020-11-16 17:03:10 -05001599 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001600 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001601 getNode(newResult).addChild(result);
1602 getNode(newResult).addChild(right);
1603 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001604 break;
1605 }
1606 default:
1607 return result;
1608 }
1609 }
1610}
1611
1612/* additiveExpression ((SHL | SHR) additiveExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001613ASTNode::ID Parser::shiftExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001614 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001615 ASTNode::ID result = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001616 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001617 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001618 }
1619 for (;;) {
1620 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001621 case Token::Kind::TK_SHL: // fall through
1622 case Token::Kind::TK_SHR: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001623 if (!depth.increase()) {
1624 return ASTNode::ID::Invalid();
1625 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001626 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001627 ASTNode::ID right = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001628 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001629 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001630 }
John Stiles3b209362020-11-16 17:03:10 -05001631 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001632 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001633 getNode(newResult).addChild(result);
1634 getNode(newResult).addChild(right);
1635 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001636 break;
1637 }
1638 default:
1639 return result;
1640 }
1641 }
1642}
1643
1644/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001645ASTNode::ID Parser::additiveExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001646 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001647 ASTNode::ID result = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001648 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001649 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001650 }
1651 for (;;) {
1652 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001653 case Token::Kind::TK_PLUS: // fall through
1654 case Token::Kind::TK_MINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001655 if (!depth.increase()) {
1656 return ASTNode::ID::Invalid();
1657 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001658 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001659 ASTNode::ID right = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001660 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001661 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001662 }
John Stiles3b209362020-11-16 17:03:10 -05001663 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001664 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001665 getNode(newResult).addChild(result);
1666 getNode(newResult).addChild(right);
1667 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001668 break;
1669 }
1670 default:
1671 return result;
1672 }
1673 }
1674}
1675
1676/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001677ASTNode::ID Parser::multiplicativeExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001678 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001679 ASTNode::ID result = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001680 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001681 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001682 }
1683 for (;;) {
1684 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001685 case Token::Kind::TK_STAR: // fall through
1686 case Token::Kind::TK_SLASH: // fall through
1687 case Token::Kind::TK_PERCENT: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001688 if (!depth.increase()) {
1689 return ASTNode::ID::Invalid();
1690 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001691 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001692 ASTNode::ID right = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001693 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001694 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001695 }
John Stiles3b209362020-11-16 17:03:10 -05001696 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001697 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001698 getNode(newResult).addChild(result);
1699 getNode(newResult).addChild(right);
1700 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001701 break;
1702 }
1703 default:
1704 return result;
1705 }
1706 }
1707}
1708
1709/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001710ASTNode::ID Parser::unaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001711 AutoDepth depth(this);
ethannicholasb3058bd2016-07-01 08:22:01 -07001712 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001713 case Token::Kind::TK_PLUS: // fall through
1714 case Token::Kind::TK_MINUS: // fall through
1715 case Token::Kind::TK_LOGICALNOT: // fall through
1716 case Token::Kind::TK_BITWISENOT: // fall through
1717 case Token::Kind::TK_PLUSPLUS: // fall through
1718 case Token::Kind::TK_MINUSMINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001719 if (!depth.increase()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001720 return ASTNode::ID::Invalid();
Ethan Nicholas6dcc3252019-02-20 15:18:36 -05001721 }
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001722 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001723 ASTNode::ID expr = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001724 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001725 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001726 }
John Stiles45990502021-02-16 10:55:27 -05001727 ASTNode::ID result = this->createNode(t.fOffset, ASTNode::Kind::kPrefix,
1728 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001729 getNode(result).addChild(expr);
1730 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001731 }
1732 default:
1733 return this->postfixExpression();
1734 }
1735}
1736
1737/* term suffix* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001738ASTNode::ID Parser::postfixExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001739 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001740 ASTNode::ID result = this->term();
ethannicholasb3058bd2016-07-01 08:22:01 -07001741 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001742 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001743 }
1744 for (;;) {
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001745 Token t = this->peek();
1746 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001747 case Token::Kind::TK_FLOAT_LITERAL:
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001748 if (this->text(t)[0] != '.') {
1749 return result;
1750 }
John Stiles30212b72020-06-11 17:55:07 -04001751 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001752 case Token::Kind::TK_LBRACKET:
1753 case Token::Kind::TK_DOT:
1754 case Token::Kind::TK_LPAREN:
1755 case Token::Kind::TK_PLUSPLUS:
1756 case Token::Kind::TK_MINUSMINUS:
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001757 if (!depth.increase()) {
1758 return ASTNode::ID::Invalid();
1759 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001760 result = this->suffix(result);
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001761 if (!result) {
1762 return ASTNode::ID::Invalid();
1763 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001764 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001765 default:
1766 return result;
1767 }
1768 }
1769}
1770
Ethan Nicholas11d53972016-11-28 11:23:23 -05001771/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
Brian Osmanc9145f32021-07-08 13:40:10 -04001772 PLUSPLUS | MINUSMINUS | FLOAT_LITERAL [IDENTIFIER] */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001773ASTNode::ID Parser::suffix(ASTNode::ID base) {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001774 SkASSERT(base);
ethannicholasb3058bd2016-07-01 08:22:01 -07001775 Token next = this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001776 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001777 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001778 return ASTNode::ID::Invalid();
1779 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001780 switch (next.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001781 case Token::Kind::TK_LBRACKET: {
1782 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
John Stiles3b209362020-11-16 17:03:10 -05001783 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kIndex);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001784 getNode(result).addChild(base);
1785 return result;
ethannicholas5961bc92016-10-12 06:39:56 -07001786 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001787 ASTNode::ID e = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001788 if (!e) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001789 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001790 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001791 this->expect(Token::Kind::TK_RBRACKET, "']' to complete array access expression");
John Stiles3b209362020-11-16 17:03:10 -05001792 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kIndex);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001793 getNode(result).addChild(base);
1794 getNode(result).addChild(e);
1795 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001796 }
Brian Osman6518d772020-09-10 16:50:06 -04001797 case Token::Kind::TK_DOT: {
1798 int offset = this->peek().fOffset;
Ethan Nicholas962dec42021-06-10 13:06:39 -04001799 skstd::string_view text;
Brian Osman6518d772020-09-10 16:50:06 -04001800 if (this->identifier(&text)) {
John Stiles3b209362020-11-16 17:03:10 -05001801 ASTNode::ID result = this->createNode(offset, ASTNode::Kind::kField,
1802 std::move(text));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001803 getNode(result).addChild(base);
1804 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001805 }
Brian Osman6518d772020-09-10 16:50:06 -04001806 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04001807 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001808 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholase455f652019-09-13 12:52:55 -04001809 // Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
1810 // floating point literals, possibly followed by an identifier. Handle that here.
Ethan Nicholas962dec42021-06-10 13:06:39 -04001811 skstd::string_view field = this->text(next);
Ethan Nicholasd2e09602021-06-10 11:21:59 -04001812 SkASSERT(field[0] == '.');
1813 field.remove_prefix(1);
1814 for (auto iter = field.begin(); iter != field.end(); ++iter) {
1815 if (*iter != '0' && *iter != '1') {
Ethan Nicholase455f652019-09-13 12:52:55 -04001816 this->error(next, "invalid swizzle");
1817 return ASTNode::ID::Invalid();
1818 }
1819 }
1820 // use the next *raw* token so we don't ignore whitespace - we only care about
1821 // identifiers that directly follow the float
1822 Token id = this->nextRawToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001823 if (id.fKind == Token::Kind::TK_IDENTIFIER) {
Ethan Nicholas962dec42021-06-10 13:06:39 -04001824 field = skstd::string_view(field.data(), field.length() + id.fLength);
Ethan Nicholase455f652019-09-13 12:52:55 -04001825 } else {
1826 this->pushback(id);
1827 }
John Stiles3b209362020-11-16 17:03:10 -05001828 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kField, field);
Ethan Nicholase455f652019-09-13 12:52:55 -04001829 getNode(result).addChild(base);
1830 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001831 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001832 case Token::Kind::TK_LPAREN: {
John Stiles3b209362020-11-16 17:03:10 -05001833 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kCall);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001834 getNode(result).addChild(base);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001835 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001836 for (;;) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001837 ASTNode::ID expr = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001838 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001839 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001840 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001841 getNode(result).addChild(expr);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001842 if (!this->checkNext(Token::Kind::TK_COMMA)) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001843 break;
1844 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001845 }
1846 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001847 this->expect(Token::Kind::TK_RPAREN, "')' to complete function parameters");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001848 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001849 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001850 case Token::Kind::TK_PLUSPLUS: // fall through
1851 case Token::Kind::TK_MINUSMINUS: {
John Stiles45990502021-02-16 10:55:27 -05001852 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kPostfix,
1853 Operator(next.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001854 getNode(result).addChild(base);
1855 return result;
1856 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001857 default: {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001858 this->error(next, "expected expression suffix, but found '" + this->text(next) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001859 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001860 }
1861 }
1862}
1863
Brian Osman33c64a42020-12-23 10:26:38 -05001864/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001865ASTNode::ID Parser::term() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001866 Token t = this->peek();
1867 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001868 case Token::Kind::TK_IDENTIFIER: {
Ethan Nicholas962dec42021-06-10 13:06:39 -04001869 skstd::string_view text;
ethannicholasb3058bd2016-07-01 08:22:01 -07001870 if (this->identifier(&text)) {
John Stiles3b209362020-11-16 17:03:10 -05001871 return this->createNode(t.fOffset, ASTNode::Kind::kIdentifier, std::move(text));
ethannicholasb3058bd2016-07-01 08:22:01 -07001872 }
John Stiles30212b72020-06-11 17:55:07 -04001873 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001874 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001875 case Token::Kind::TK_INT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001876 SKSL_INT i;
ethannicholasb3058bd2016-07-01 08:22:01 -07001877 if (this->intLiteral(&i)) {
John Stiles3b209362020-11-16 17:03:10 -05001878 return this->createNode(t.fOffset, ASTNode::Kind::kInt, i);
ethannicholasb3058bd2016-07-01 08:22:01 -07001879 }
1880 break;
1881 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001882 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001883 SKSL_FLOAT f;
ethannicholasb3058bd2016-07-01 08:22:01 -07001884 if (this->floatLiteral(&f)) {
John Stiles3b209362020-11-16 17:03:10 -05001885 return this->createNode(t.fOffset, ASTNode::Kind::kFloat, f);
ethannicholasb3058bd2016-07-01 08:22:01 -07001886 }
1887 break;
1888 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001889 case Token::Kind::TK_TRUE_LITERAL: // fall through
1890 case Token::Kind::TK_FALSE_LITERAL: {
ethannicholasb3058bd2016-07-01 08:22:01 -07001891 bool b;
1892 if (this->boolLiteral(&b)) {
John Stiles3b209362020-11-16 17:03:10 -05001893 return this->createNode(t.fOffset, ASTNode::Kind::kBool, b);
ethannicholasb3058bd2016-07-01 08:22:01 -07001894 }
1895 break;
1896 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001897 case Token::Kind::TK_LPAREN: {
ethannicholasb3058bd2016-07-01 08:22:01 -07001898 this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001899 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001900 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001901 return ASTNode::ID::Invalid();
1902 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001903 ASTNode::ID result = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001904 if (result) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001905 this->expect(Token::Kind::TK_RPAREN, "')' to complete expression");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001906 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001907 }
1908 break;
1909 }
1910 default:
1911 this->nextToken();
John Stilesf94348f2020-12-23 18:58:43 -05001912 this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001913 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001914 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001915}
1916
1917/* INT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001918bool Parser::intLiteral(SKSL_INT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001919 Token t;
John Stilesf94348f2020-12-23 18:58:43 -05001920 if (!this->expect(Token::Kind::TK_INT_LITERAL, "integer literal", &t)) {
1921 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001922 }
Ethan Nicholas962dec42021-06-10 13:06:39 -04001923 skstd::string_view s = this->text(t);
John Stilesf94348f2020-12-23 18:58:43 -05001924 if (!SkSL::stoi(s, dest)) {
1925 this->error(t, "integer is too large: " + s);
1926 return false;
1927 }
1928 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001929}
1930
John Stilesf94348f2020-12-23 18:58:43 -05001931
ethannicholasb3058bd2016-07-01 08:22:01 -07001932/* FLOAT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001933bool Parser::floatLiteral(SKSL_FLOAT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001934 Token t;
John Stilesf94348f2020-12-23 18:58:43 -05001935 if (!this->expect(Token::Kind::TK_FLOAT_LITERAL, "float literal", &t)) {
1936 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001937 }
Ethan Nicholas962dec42021-06-10 13:06:39 -04001938 skstd::string_view s = this->text(t);
John Stilesf94348f2020-12-23 18:58:43 -05001939 if (!SkSL::stod(s, dest)) {
1940 this->error(t, "floating-point value is too large: " + s);
1941 return false;
1942 }
1943 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001944}
1945
1946/* TRUE_LITERAL | FALSE_LITERAL */
1947bool Parser::boolLiteral(bool* dest) {
1948 Token t = this->nextToken();
1949 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001950 case Token::Kind::TK_TRUE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07001951 *dest = true;
1952 return true;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001953 case Token::Kind::TK_FALSE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07001954 *dest = false;
1955 return true;
1956 default:
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001957 this->error(t, "expected 'true' or 'false', but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001958 return false;
1959 }
1960}
1961
1962/* IDENTIFIER */
Ethan Nicholas962dec42021-06-10 13:06:39 -04001963bool Parser::identifier(skstd::string_view* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001964 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001965 if (this->expect(Token::Kind::TK_IDENTIFIER, "identifier", &t)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001966 *dest = this->text(t);
ethannicholasb3058bd2016-07-01 08:22:01 -07001967 return true;
1968 }
1969 return false;
1970}
1971
John Stilesa6841be2020-08-06 14:11:56 -04001972} // namespace SkSL