blob: d631c0c86c89e6e1cdb84036af636fb74992c219 [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;
ethannicholascad64162016-10-27 10:54:02 -070025
John Stiles7d5b90a2021-01-21 14:26:51 -050026static int parse_modifier_token(Token::Kind token) {
27 switch (token) {
28 case Token::Kind::TK_UNIFORM: return Modifiers::kUniform_Flag;
29 case Token::Kind::TK_CONST: return Modifiers::kConst_Flag;
30 case Token::Kind::TK_IN: return Modifiers::kIn_Flag;
31 case Token::Kind::TK_OUT: return Modifiers::kOut_Flag;
32 case Token::Kind::TK_INOUT: return Modifiers::kIn_Flag | Modifiers::kOut_Flag;
33 case Token::Kind::TK_FLAT: return Modifiers::kFlat_Flag;
34 case Token::Kind::TK_NOPERSPECTIVE: return Modifiers::kNoPerspective_Flag;
John Stiles7d5b90a2021-01-21 14:26:51 -050035 case Token::Kind::TK_HASSIDEEFFECTS: return Modifiers::kHasSideEffects_Flag;
John Stiles7d5b90a2021-01-21 14:26:51 -050036 case Token::Kind::TK_INLINE: return Modifiers::kInline_Flag;
John Stiles0dd1a772021-03-09 22:14:27 -050037 case Token::Kind::TK_NOINLINE: return Modifiers::kNoInline_Flag;
John Stiles02014312021-08-04 16:03:12 -040038 case Token::Kind::TK_HIGHP: return Modifiers::kHighp_Flag;
39 case Token::Kind::TK_MEDIUMP: return Modifiers::kMediump_Flag;
40 case Token::Kind::TK_LOWP: return Modifiers::kLowp_Flag;
John Stilesefde90d2021-08-12 23:06:24 -040041 case Token::Kind::TK_ES3: return Modifiers::kES3_Flag;
John Stiles7d5b90a2021-01-21 14:26:51 -050042 default: return 0;
43 }
44}
45
ethannicholascad64162016-10-27 10:54:02 -070046class AutoDepth {
47public:
48 AutoDepth(Parser* p)
Ethan Nicholascf4deab2019-09-13 16:28:14 -040049 : fParser(p)
50 , fDepth(0) {}
ethannicholascad64162016-10-27 10:54:02 -070051
52 ~AutoDepth() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -040053 fParser->fDepth -= fDepth;
ethannicholascad64162016-10-27 10:54:02 -070054 }
55
Ethan Nicholascf4deab2019-09-13 16:28:14 -040056 bool increase() {
57 ++fDepth;
58 ++fParser->fDepth;
John Stiles8d056592020-11-10 10:03:50 -050059 if (fParser->fDepth > kMaxParseDepth) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070060 fParser->error(fParser->peek(), String("exceeded max parse depth"));
ethannicholascad64162016-10-27 10:54:02 -070061 return false;
62 }
63 return true;
64 }
65
66private:
67 Parser* fParser;
Ethan Nicholascf4deab2019-09-13 16:28:14 -040068 int fDepth;
ethannicholascad64162016-10-27 10:54:02 -070069};
70
Brian Salomon140f3da2018-08-23 13:51:27 +000071std::unordered_map<String, Parser::LayoutToken>* Parser::layoutTokens;
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040072
73void Parser::InitLayoutMap() {
Brian Salomon140f3da2018-08-23 13:51:27 +000074 layoutTokens = new std::unordered_map<String, LayoutToken>;
Brian Salomon23356442018-11-30 15:33:19 -050075 #define TOKEN(name, text) (*layoutTokens)[text] = LayoutToken::name
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040076 TOKEN(LOCATION, "location");
77 TOKEN(OFFSET, "offset");
78 TOKEN(BINDING, "binding");
79 TOKEN(INDEX, "index");
80 TOKEN(SET, "set");
81 TOKEN(BUILTIN, "builtin");
82 TOKEN(INPUT_ATTACHMENT_INDEX, "input_attachment_index");
83 TOKEN(ORIGIN_UPPER_LEFT, "origin_upper_left");
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040084 TOKEN(BLEND_SUPPORT_ALL_EQUATIONS, "blend_support_all_equations");
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040085 TOKEN(PUSH_CONSTANT, "push_constant");
Brian Osmanb32d66b2020-04-30 17:12:03 -040086 TOKEN(SRGB_UNPREMUL, "srgb_unpremul");
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040087 #undef TOKEN
88}
89
Ethan Nicholas6823b502021-06-15 11:42:07 -040090Parser::Parser(skstd::string_view text, SymbolTable& symbols, ErrorReporter& errors)
91: fText(text)
John Stiles7cbb09c22021-01-07 16:07:00 -050092, fPushback(Token::Kind::TK_NONE, -1, -1)
Ethan Nicholasc18bb512020-07-28 14:46:53 -040093, fSymbols(symbols)
Ethan Nicholas55478662021-08-10 17:14:26 -040094, fErrors(&errors) {
Ethan Nicholas6823b502021-06-15 11:42:07 -040095 fLexer.start(text);
Brian Salomon3b83afe2018-08-23 11:04:36 -040096 static const bool layoutMapInitialized = []{ return (void)InitLayoutMap(), true; }();
97 (void) layoutMapInitialized;
ethannicholasb3058bd2016-07-01 08:22:01 -070098}
99
John Stiles3b209362020-11-16 17:03:10 -0500100template <typename... Args>
101ASTNode::ID Parser::createNode(Args&&... args) {
102 ASTNode::ID result(fFile->fNodes.size());
103 fFile->fNodes.emplace_back(&fFile->fNodes, std::forward<Args>(args)...);
104 return result;
105}
Ethan Nicholasfc994162019-06-06 10:04:27 -0400106
John Stiles3b209362020-11-16 17:03:10 -0500107ASTNode::ID Parser::addChild(ASTNode::ID target, ASTNode::ID child) {
108 fFile->fNodes[target.fValue].addChild(child);
109 return child;
110}
Ethan Nicholasfc994162019-06-06 10:04:27 -0400111
John Stiles3b209362020-11-16 17:03:10 -0500112void Parser::createEmptyChild(ASTNode::ID target) {
113 ASTNode::ID child(fFile->fNodes.size());
114 fFile->fNodes.emplace_back();
115 fFile->fNodes[target.fValue].addChild(child);
116}
Ethan Nicholasfc994162019-06-06 10:04:27 -0400117
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400118/* (directive | section | declaration)* END_OF_FILE */
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500119std::unique_ptr<ASTFile> Parser::compilationUnit() {
John Stilesfbd050b2020-08-03 13:21:46 -0400120 fFile = std::make_unique<ASTFile>();
John Stiles18a45b32021-03-29 18:07:32 -0400121 fFile->fNodes.reserve(fText.size() / 10); // a typical program is approx 10:1 for chars:nodes
John Stiles3b209362020-11-16 17:03:10 -0500122 ASTNode::ID result = this->createNode(/*offset=*/0, ASTNode::Kind::kFile);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400123 fFile->fRoot = result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700124 for (;;) {
125 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400126 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholasfc994162019-06-06 10:04:27 -0400127 return std::move(fFile);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400128 case Token::Kind::TK_DIRECTIVE: {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400129 ASTNode::ID dir = this->directive();
Ethan Nicholas55478662021-08-10 17:14:26 -0400130 if (fErrors->errorCount()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400131 return nullptr;
132 }
133 if (dir) {
134 getNode(result).addChild(dir);
ethannicholasb3058bd2016-07-01 08:22:01 -0700135 }
136 break;
137 }
John Stiles7cbb09c22021-01-07 16:07:00 -0500138 case Token::Kind::TK_INVALID: {
139 this->error(this->peek(), String("invalid token"));
140 return nullptr;
141 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700142 default: {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400143 ASTNode::ID decl = this->declaration();
Ethan Nicholas55478662021-08-10 17:14:26 -0400144 if (fErrors->errorCount()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400145 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700146 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400147 if (decl) {
148 getNode(result).addChild(decl);
149 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700150 }
151 }
152 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400153 return std::move(fFile);
ethannicholasb3058bd2016-07-01 08:22:01 -0700154}
155
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700156Token Parser::nextRawToken() {
John Stiles7cbb09c22021-01-07 16:07:00 -0500157 if (fPushback.fKind != Token::Kind::TK_NONE) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700158 Token result = fPushback;
John Stiles7cbb09c22021-01-07 16:07:00 -0500159 fPushback.fKind = Token::Kind::TK_NONE;
ethannicholasb3058bd2016-07-01 08:22:01 -0700160 return result;
161 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700162 Token result = fLexer.next();
163 return result;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400164}
165
166Token Parser::nextToken() {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700167 Token token = this->nextRawToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400168 while (token.fKind == Token::Kind::TK_WHITESPACE ||
169 token.fKind == Token::Kind::TK_LINE_COMMENT ||
170 token.fKind == Token::Kind::TK_BLOCK_COMMENT) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700171 token = this->nextRawToken();
172 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400173 return token;
ethannicholasb3058bd2016-07-01 08:22:01 -0700174}
175
176void Parser::pushback(Token t) {
John Stiles7cbb09c22021-01-07 16:07:00 -0500177 SkASSERT(fPushback.fKind == Token::Kind::TK_NONE);
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400178 fPushback = std::move(t);
ethannicholasb3058bd2016-07-01 08:22:01 -0700179}
180
181Token Parser::peek() {
John Stiles7cbb09c22021-01-07 16:07:00 -0500182 if (fPushback.fKind == Token::Kind::TK_NONE) {
Brian Osman634624a2017-08-15 11:14:30 -0400183 fPushback = this->nextToken();
184 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700185 return fPushback;
186}
187
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400188bool Parser::checkNext(Token::Kind kind, Token* result) {
John Stiles7cbb09c22021-01-07 16:07:00 -0500189 if (fPushback.fKind != Token::Kind::TK_NONE && fPushback.fKind != kind) {
Brian Osman634624a2017-08-15 11:14:30 -0400190 return false;
191 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400192 Token next = this->nextToken();
193 if (next.fKind == kind) {
194 if (result) {
195 *result = next;
196 }
197 return true;
198 }
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400199 this->pushback(std::move(next));
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400200 return false;
201}
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500202
203bool Parser::expect(Token::Kind kind, const char* expected, Token* result) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700204 Token next = this->nextToken();
205 if (next.fKind == kind) {
206 if (result) {
Brian Osman634624a2017-08-15 11:14:30 -0400207 *result = std::move(next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700208 }
209 return true;
210 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700211 this->error(next, "expected " + String(expected) + ", but found '" +
212 this->text(next) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700213 return false;
214 }
215}
216
John Stiles2630ea32020-12-04 10:51:21 -0500217bool Parser::expectIdentifier(Token* result) {
218 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", result)) {
219 return false;
220 }
221 if (this->isType(this->text(*result))) {
222 this->error(*result, "expected an identifier, but found type '" +
223 this->text(*result) + "'");
224 return false;
225 }
226 return true;
227}
228
Ethan Nicholas962dec42021-06-10 13:06:39 -0400229skstd::string_view Parser::text(Token token) {
230 return skstd::string_view(fText.begin() + token.fOffset, token.fLength);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500231}
232
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700233void Parser::error(Token token, String msg) {
234 this->error(token.fOffset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -0700235}
236
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700237void Parser::error(int offset, String msg) {
Ethan Nicholas55478662021-08-10 17:14:26 -0400238 fErrors->error(offset, msg);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700239}
240
Ethan Nicholas962dec42021-06-10 13:06:39 -0400241bool Parser::isType(skstd::string_view name) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400242 const Symbol* s = fSymbols[name];
John Stiles2630ea32020-12-04 10:51:21 -0500243 return s && s->is<Type>();
ethannicholasb3058bd2016-07-01 08:22:01 -0700244}
245
John Stiles80b02af2021-02-12 17:07:51 -0500246bool Parser::isArrayType(ASTNode::ID type) {
247 const ASTNode& node = this->getNode(type);
248 SkASSERT(node.fKind == ASTNode::Kind::kType);
249 return node.begin() != node.end();
250}
251
Ethan Nicholas11d53972016-11-28 11:23:23 -0500252/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
ethannicholas5961bc92016-10-12 06:39:56 -0700253 DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400254ASTNode::ID Parser::directive() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700255 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400256 if (!this->expect(Token::Kind::TK_DIRECTIVE, "a directive", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400257 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700258 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400259 skstd::string_view text = this->text(start);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400260 if (text == "#extension") {
ethannicholasb3058bd2016-07-01 08:22:01 -0700261 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500262 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400263 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700264 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400265 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400266 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700267 }
268 // FIXME: need to start paying attention to this token
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400269 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400270 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700271 }
John Stiles3b209362020-11-16 17:03:10 -0500272 return this->createNode(start.fOffset, ASTNode::Kind::kExtension, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700273 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700274 this->error(start, "unsupported directive '" + this->text(start) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400275 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700276 }
277}
278
Brian Osmanc9145f32021-07-08 13:40:10 -0400279/* modifiers (interfaceBlock | structVarDeclaration | SEMICOLON |
John Stiles147cfda2021-05-21 14:11:38 -0400280 type IDENTIFIER (varDeclarationEnd | LPAREN functionDeclarationEnd))) */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400281ASTNode::ID Parser::declaration() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700282 Token lookahead = this->peek();
Ethan Nicholasda6320c2020-09-02 14:08:23 -0400283 switch (lookahead.fKind) {
Ethan Nicholasda6320c2020-09-02 14:08:23 -0400284 case Token::Kind::TK_SEMICOLON:
285 this->error(lookahead.fOffset, "expected a declaration, but found ';'");
286 return ASTNode::ID::Invalid();
287 default:
288 break;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500289 }
290 Modifiers modifiers = this->modifiers();
291 lookahead = this->peek();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400292 if (lookahead.fKind == Token::Kind::TK_IDENTIFIER && !this->isType(this->text(lookahead))) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700293 // we have an identifier that's not a type, could be the start of an interface block
294 return this->interfaceBlock(modifiers);
295 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400296 if (lookahead.fKind == Token::Kind::TK_STRUCT) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700297 return this->structVarDeclaration(modifiers);
298 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400299 if (lookahead.fKind == Token::Kind::TK_SEMICOLON) {
ethannicholas5961bc92016-10-12 06:39:56 -0700300 this->nextToken();
John Stiles3b209362020-11-16 17:03:10 -0500301 return this->createNode(lookahead.fOffset, ASTNode::Kind::kModifiers, modifiers);
ethannicholas5961bc92016-10-12 06:39:56 -0700302 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400303 ASTNode::ID type = this->type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700304 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400305 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700306 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700307 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500308 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400309 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700310 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400311 if (this->checkNext(Token::Kind::TK_LPAREN)) {
John Stiles147cfda2021-05-21 14:11:38 -0400312 return this->functionDeclarationEnd(modifiers, type, name);
ethannicholasb3058bd2016-07-01 08:22:01 -0700313 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400314 return this->varDeclarationEnd(modifiers, type, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700315 }
316}
317
John Stiles147cfda2021-05-21 14:11:38 -0400318/* (RPAREN | VOID RPAREN | parameter (COMMA parameter)* RPAREN) (block | SEMICOLON) */
319ASTNode::ID Parser::functionDeclarationEnd(Modifiers modifiers,
320 ASTNode::ID type,
321 const Token& name) {
322 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kFunction);
323 ASTNode::FunctionData fd(modifiers, this->text(name), 0);
324 getNode(result).addChild(type);
325 Token lookahead = this->peek();
326 if (lookahead.fKind == Token::Kind::TK_RPAREN) {
327 // `()` means no parameters at all.
328 } else if (lookahead.fKind == Token::Kind::TK_IDENTIFIER && this->text(lookahead) == "void") {
329 // `(void)` also means no parameters at all.
330 this->nextToken();
331 } else {
332 for (;;) {
333 ASTNode::ID parameter = this->parameter();
334 if (!parameter) {
335 return ASTNode::ID::Invalid();
336 }
337 ++fd.fParameterCount;
338 getNode(result).addChild(parameter);
339 if (!this->checkNext(Token::Kind::TK_COMMA)) {
340 break;
341 }
342 }
343 }
344 getNode(result).setFunctionData(fd);
345 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
346 return ASTNode::ID::Invalid();
347 }
348 ASTNode::ID body;
349 if (!this->checkNext(Token::Kind::TK_SEMICOLON)) {
350 body = this->block();
351 if (!body) {
352 return ASTNode::ID::Invalid();
353 }
354 getNode(result).addChild(body);
355 }
356 return result;
357}
358
John Stiles76389b72021-01-25 13:49:05 -0500359/* (varDeclarations | expressionStatement) */
360ASTNode::ID Parser::varDeclarationsOrExpressionStatement() {
John Stiles89b484a2021-04-19 14:57:27 -0400361 Token nextToken = this->peek();
362 if (nextToken.fKind == Token::Kind::TK_CONST) {
363 // Statements that begin with `const` might be variable declarations, but can't be legal
364 // SkSL expression-statements. (SkSL constructors don't take a `const` modifier.)
365 return this->varDeclarations();
366 }
367
John Stiles02014312021-08-04 16:03:12 -0400368 if (nextToken.fKind == Token::Kind::TK_HIGHP ||
369 nextToken.fKind == Token::Kind::TK_MEDIUMP ||
370 nextToken.fKind == Token::Kind::TK_LOWP ||
371 this->isType(this->text(nextToken))) {
John Stiles76389b72021-01-25 13:49:05 -0500372 // Statements that begin with a typename are most often variable declarations, but
373 // occasionally the type is part of a constructor, and these are actually expression-
374 // statements in disguise. First, attempt the common case: parse it as a vardecl.
375 Checkpoint checkpoint(this);
John Stiles8dabeac2021-02-12 16:05:00 -0500376 VarDeclarationsPrefix prefix;
377 if (this->varDeclarationsPrefix(&prefix)) {
Ethan Nicholas55478662021-08-10 17:14:26 -0400378 checkpoint.accept();
John Stiles8dabeac2021-02-12 16:05:00 -0500379 return this->varDeclarationEnd(prefix.modifiers, prefix.type, this->text(prefix.name));
John Stiles76389b72021-01-25 13:49:05 -0500380 }
381
382 // If this statement wasn't actually a vardecl after all, rewind and try parsing it as an
383 // expression-statement instead.
384 checkpoint.rewind();
385 }
386
387 return this->expressionStatement();
388}
389
John Stiles8dabeac2021-02-12 16:05:00 -0500390// Helper function for varDeclarations(). If this function succeeds, we assume that the rest of the
391// statement is a variable-declaration statement, not an expression-statement.
392bool Parser::varDeclarationsPrefix(VarDeclarationsPrefix* prefixData) {
393 prefixData->modifiers = this->modifiers();
394 prefixData->type = this->type();
395 if (!prefixData->type) {
396 return false;
397 }
398 return this->expectIdentifier(&prefixData->name);
399}
400
ethannicholasb3058bd2016-07-01 08:22:01 -0700401/* modifiers type IDENTIFIER varDeclarationEnd */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400402ASTNode::ID Parser::varDeclarations() {
John Stiles8dabeac2021-02-12 16:05:00 -0500403 VarDeclarationsPrefix prefix;
404 if (!this->varDeclarationsPrefix(&prefix)) {
John Stiles76389b72021-01-25 13:49:05 -0500405 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700406 }
John Stiles8dabeac2021-02-12 16:05:00 -0500407 return this->varDeclarationEnd(prefix.modifiers, prefix.type, this->text(prefix.name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700408}
409
410/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400411ASTNode::ID Parser::structDeclaration() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400412 if (!this->expect(Token::Kind::TK_STRUCT, "'struct'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400413 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700414 }
415 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500416 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400417 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700418 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400419 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400420 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700421 }
422 std::vector<Type::Field> fields;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400423 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400424 ASTNode::ID decls = this->varDeclarations();
425 if (!decls) {
426 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700427 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400428 ASTNode& declsNode = getNode(decls);
John Stilesece1bf02021-03-08 11:15:55 -0500429 const Modifiers& modifiers = declsNode.begin()->getModifiers();
John Stiles13fc2602020-10-09 17:42:31 -0400430 if (modifiers.fFlags != Modifiers::kNo_Flag) {
431 String desc = modifiers.description();
432 desc.pop_back(); // remove trailing space
433 this->error(declsNode.fOffset,
434 "modifier '" + desc + "' is not permitted on a struct field");
435 }
436
Ethan Nicholas962dec42021-06-10 13:06:39 -0400437 const Symbol* symbol = fSymbols[(declsNode.begin() + 1)->getStringView()];
John Stiles13fc2602020-10-09 17:42:31 -0400438 SkASSERT(symbol);
439 const Type* type = &symbol->as<Type>();
John Stiles1d757782020-11-17 09:43:22 -0500440 if (type->isOpaque()) {
441 this->error(declsNode.fOffset,
442 "opaque type '" + type->name() + "' is not permitted in a struct");
443 }
John Stiles13fc2602020-10-09 17:42:31 -0400444
Ethan Nicholasfc994162019-06-06 10:04:27 -0400445 for (auto iter = declsNode.begin() + 2; iter != declsNode.end(); ++iter) {
446 ASTNode& var = *iter;
John Stilesece1bf02021-03-08 11:15:55 -0500447 const ASTNode::VarData& vd = var.getVarData();
John Stiles6bef6a72020-12-02 14:26:04 -0500448
John Stilesd39aec92020-12-03 14:37:16 -0500449 // Read array size if one is present.
John Stiles31c87102021-08-25 12:01:21 -0400450 const Type* fieldType = type;
John Stilesd39aec92020-12-03 14:37:16 -0500451 if (vd.fIsArray) {
452 const ASTNode& size = *var.begin();
Ethan Nicholasfc994162019-06-06 10:04:27 -0400453 if (!size || size.fKind != ASTNode::Kind::kInt) {
454 this->error(declsNode.fOffset, "array size in struct field must be a constant");
455 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700456 }
John Stiles6bef6a72020-12-02 14:26:04 -0500457 if (size.getInt() <= 0 || size.getInt() > INT_MAX) {
458 this->error(declsNode.fOffset, "array size is invalid");
459 return ASTNode::ID::Invalid();
460 }
John Stilesd39aec92020-12-03 14:37:16 -0500461 // Add the array dimensions to our type.
462 int arraySize = size.getInt();
John Stiles31c87102021-08-25 12:01:21 -0400463 fieldType = fSymbols.addArrayDimension(fieldType, arraySize);
ethannicholasb3058bd2016-07-01 08:22:01 -0700464 }
John Stiles13fc2602020-10-09 17:42:31 -0400465
John Stiles31c87102021-08-25 12:01:21 -0400466 fields.push_back(Type::Field(modifiers, vd.fName, fieldType));
John Stilesd39aec92020-12-03 14:37:16 -0500467 if (vd.fIsArray ? var.begin()->fNext : var.fFirstChild) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400468 this->error(declsNode.fOffset, "initializers are not permitted on struct fields");
ethannicholasb3058bd2016-07-01 08:22:01 -0700469 }
470 }
471 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400472 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400473 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700474 }
Brian Osman6c3b23f2021-02-12 13:09:58 -0500475 if (fields.empty()) {
476 this->error(name.fOffset,
477 "struct '" + this->text(name) + "' must contain at least one field");
478 return ASTNode::ID::Invalid();
479 }
Ethan Nicholas27f06eb2021-07-26 16:39:40 -0400480 std::unique_ptr<Type> newType = Type::MakeStructType(name.fOffset, this->text(name), fields);
Ethan Nicholas833cd202021-09-02 14:46:41 -0400481 if (newType->isTooDeeplyNested()) {
John Stilesa695d622020-11-10 10:04:26 -0500482 this->error(name.fOffset, "struct '" + this->text(name) + "' is too deeply nested");
483 return ASTNode::ID::Invalid();
484 }
485 fSymbols.add(std::move(newType));
Brian Osman00fea5b2021-01-28 09:46:30 -0500486 return this->createNode(name.fOffset, ASTNode::Kind::kType, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700487}
488
489/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400490ASTNode::ID Parser::structVarDeclaration(Modifiers modifiers) {
491 ASTNode::ID type = this->structDeclaration();
ethannicholasb3058bd2016-07-01 08:22:01 -0700492 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400493 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700494 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400495 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400496 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400497 return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700498 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400499 this->expect(Token::Kind::TK_SEMICOLON, "';'");
John Stilesdc75a972020-11-25 16:24:55 -0500500 return type;
ethannicholasb3058bd2016-07-01 08:22:01 -0700501}
502
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400503/* (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)? (COMMA IDENTIFER
504 (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
Ethan Nicholas962dec42021-06-10 13:06:39 -0400505ASTNode::ID Parser::varDeclarationEnd(Modifiers mods, ASTNode::ID type, skstd::string_view name) {
John Stiles08070f62020-11-17 10:45:49 -0500506 int offset = this->peek().fOffset;
507 ASTNode::ID result = this->createNode(offset, ASTNode::Kind::kVarDeclarations);
508 this->addChild(result, this->createNode(offset, ASTNode::Kind::kModifiers, mods));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400509 getNode(result).addChild(type);
John Stilesd39aec92020-12-03 14:37:16 -0500510
John Stiles80b02af2021-02-12 17:07:51 -0500511 auto parseArrayDimensions = [&](ASTNode::ID currentVar, ASTNode::VarData* vd) -> bool {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400512 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stiles80b02af2021-02-12 17:07:51 -0500513 if (vd->fIsArray || this->isArrayType(type)) {
John Stilesd39aec92020-12-03 14:37:16 -0500514 this->error(this->peek(), "multi-dimensional arrays are not supported");
515 return false;
516 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400517 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
John Stiles3b209362020-11-16 17:03:10 -0500518 this->createEmptyChild(currentVar);
ethannicholasb3058bd2016-07-01 08:22:01 -0700519 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400520 ASTNode::ID size = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700521 if (!size) {
John Stilesd39aec92020-12-03 14:37:16 -0500522 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700523 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400524 getNode(currentVar).addChild(size);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400525 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
John Stilesd39aec92020-12-03 14:37:16 -0500526 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700527 }
528 }
John Stilesd39aec92020-12-03 14:37:16 -0500529 vd->fIsArray = true;
ethannicholasb3058bd2016-07-01 08:22:01 -0700530 }
John Stilesd39aec92020-12-03 14:37:16 -0500531 return true;
532 };
533
534 auto parseInitializer = [this](ASTNode::ID currentVar) -> bool {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400535 if (this->checkNext(Token::Kind::TK_EQ)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400536 ASTNode::ID value = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700537 if (!value) {
John Stilesd39aec92020-12-03 14:37:16 -0500538 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700539 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400540 getNode(currentVar).addChild(value);
ethannicholasb3058bd2016-07-01 08:22:01 -0700541 }
John Stilesd39aec92020-12-03 14:37:16 -0500542 return true;
543 };
544
545 ASTNode::ID currentVar = this->createNode(offset, ASTNode::Kind::kVarDeclaration);
546 ASTNode::VarData vd{name, /*isArray=*/false};
547
548 getNode(result).addChild(currentVar);
549 if (!parseArrayDimensions(currentVar, &vd)) {
550 return ASTNode::ID::Invalid();
551 }
552 getNode(currentVar).setVarData(vd);
553 if (!parseInitializer(currentVar)) {
554 return ASTNode::ID::Invalid();
555 }
556
557 while (this->checkNext(Token::Kind::TK_COMMA)) {
558 Token identifierName;
John Stiles2630ea32020-12-04 10:51:21 -0500559 if (!this->expectIdentifier(&identifierName)) {
John Stilesd39aec92020-12-03 14:37:16 -0500560 return ASTNode::ID::Invalid();
561 }
562
563 currentVar = ASTNode::ID(fFile->fNodes.size());
564 vd = ASTNode::VarData{this->text(identifierName), /*isArray=*/false};
565 fFile->fNodes.emplace_back(&fFile->fNodes, offset, ASTNode::Kind::kVarDeclaration);
566
567 getNode(result).addChild(currentVar);
568 if (!parseArrayDimensions(currentVar, &vd)) {
569 return ASTNode::ID::Invalid();
570 }
571 getNode(currentVar).setVarData(vd);
572 if (!parseInitializer(currentVar)) {
573 return ASTNode::ID::Invalid();
574 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700575 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400576 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400577 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700578 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400579 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700580}
581
582/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400583ASTNode::ID Parser::parameter() {
Ethan Nicholasc6f5e102017-03-31 14:53:17 -0400584 Modifiers modifiers = this->modifiersWithDefaults(0);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400585 ASTNode::ID type = this->type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700586 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400587 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700588 }
589 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500590 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400591 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700592 }
John Stiles3b209362020-11-16 17:03:10 -0500593 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kParameter);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400594 ASTNode::ParameterData pd(modifiers, this->text(name), 0);
595 getNode(result).addChild(type);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400596 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stiles80b02af2021-02-12 17:07:51 -0500597 if (pd.fIsArray || this->isArrayType(type)) {
John Stilesd39aec92020-12-03 14:37:16 -0500598 this->error(this->peek(), "multi-dimensional arrays are not supported");
599 return ASTNode::ID::Invalid();
600 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700601 Token sizeToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400602 if (!this->expect(Token::Kind::TK_INT_LITERAL, "a positive integer", &sizeToken)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400603 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700604 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400605 skstd::string_view arraySizeFrag = this->text(sizeToken);
John Stilesf94348f2020-12-23 18:58:43 -0500606 SKSL_INT arraySize;
607 if (!SkSL::stoi(arraySizeFrag, &arraySize)) {
608 this->error(sizeToken, "array size is too large: " + arraySizeFrag);
609 return ASTNode::ID::Invalid();
610 }
611 this->addChild(result, this->createNode(sizeToken.fOffset, ASTNode::Kind::kInt, arraySize));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400612 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400613 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700614 }
John Stilesd39aec92020-12-03 14:37:16 -0500615 pd.fIsArray = true;
ethannicholasb3058bd2016-07-01 08:22:01 -0700616 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400617 getNode(result).setParameterData(pd);
618 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700619}
620
Ethan Nicholasd608c092017-10-26 09:30:08 -0400621/** EQ INT_LITERAL */
ethannicholasb3058bd2016-07-01 08:22:01 -0700622int Parser::layoutInt() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400623 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700624 return -1;
625 }
626 Token resultToken;
John Stilesf94348f2020-12-23 18:58:43 -0500627 if (!this->expect(Token::Kind::TK_INT_LITERAL, "a non-negative integer", &resultToken)) {
628 return -1;
ethannicholasb3058bd2016-07-01 08:22:01 -0700629 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400630 skstd::string_view resultFrag = this->text(resultToken);
John Stilesf94348f2020-12-23 18:58:43 -0500631 SKSL_INT resultValue;
632 if (!SkSL::stoi(resultFrag, &resultValue)) {
633 this->error(resultToken, "value in layout is too large: " + resultFrag);
634 return -1;
635 }
636 return resultValue;
ethannicholasb3058bd2016-07-01 08:22:01 -0700637}
638
Ethan Nicholasd608c092017-10-26 09:30:08 -0400639/** EQ IDENTIFIER */
Ethan Nicholas962dec42021-06-10 13:06:39 -0400640skstd::string_view Parser::layoutIdentifier() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400641 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
Ethan Nicholas962dec42021-06-10 13:06:39 -0400642 return skstd::string_view();
Ethan Nicholasd608c092017-10-26 09:30:08 -0400643 }
644 Token resultToken;
John Stiles2630ea32020-12-04 10:51:21 -0500645 if (!this->expectIdentifier(&resultToken)) {
Ethan Nicholas962dec42021-06-10 13:06:39 -0400646 return skstd::string_view();
Ethan Nicholasd608c092017-10-26 09:30:08 -0400647 }
648 return this->text(resultToken);
649}
650
ethannicholas8ac838d2016-11-22 08:39:36 -0800651/* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500652Layout Parser::layout() {
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500653 int flags = 0;
ethannicholasb3058bd2016-07-01 08:22:01 -0700654 int location = -1;
Ethan Nicholas19671772016-11-28 16:30:17 -0500655 int offset = -1;
ethannicholasb3058bd2016-07-01 08:22:01 -0700656 int binding = -1;
657 int index = -1;
658 int set = -1;
659 int builtin = -1;
Greg Daniel64773e62016-11-22 09:44:03 -0500660 int inputAttachmentIndex = -1;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400661 if (this->checkNext(Token::Kind::TK_LAYOUT)) {
662 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Brian Osman99ddd2a2021-08-27 11:21:12 -0400663 return Layout(
664 flags, location, offset, binding, index, set, builtin, inputAttachmentIndex);
ethannicholasb3058bd2016-07-01 08:22:01 -0700665 }
666 for (;;) {
667 Token t = this->nextToken();
Ethan Nicholasd2e09602021-06-10 11:21:59 -0400668 String text(this->text(t));
Brian Osmana77ed8b2021-02-23 12:54:22 -0500669 auto setFlag = [&](Layout::Flag f) {
670 if (flags & f) {
671 this->error(t, "layout qualifier '" + text + "' appears more than once");
672 }
673 flags |= f;
674 };
Brian Osmana77ed8b2021-02-23 12:54:22 -0500675
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400676 auto found = layoutTokens->find(text);
677 if (found != layoutTokens->end()) {
678 switch (found->second) {
Brian Osmana77ed8b2021-02-23 12:54:22 -0500679 case LayoutToken::ORIGIN_UPPER_LEFT:
680 setFlag(Layout::kOriginUpperLeft_Flag);
681 break;
Brian Osmana77ed8b2021-02-23 12:54:22 -0500682 case LayoutToken::PUSH_CONSTANT:
683 setFlag(Layout::kPushConstant_Flag);
684 break;
685 case LayoutToken::BLEND_SUPPORT_ALL_EQUATIONS:
686 setFlag(Layout::kBlendSupportAllEquations_Flag);
687 break;
Brian Osmana77ed8b2021-02-23 12:54:22 -0500688 case LayoutToken::SRGB_UNPREMUL:
689 setFlag(Layout::kSRGBUnpremul_Flag);
690 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700691 case LayoutToken::LOCATION:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500692 setFlag(Layout::kLocation_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500693 location = this->layoutInt();
694 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700695 case LayoutToken::OFFSET:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500696 setFlag(Layout::kOffset_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500697 offset = this->layoutInt();
698 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700699 case LayoutToken::BINDING:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500700 setFlag(Layout::kBinding_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500701 binding = this->layoutInt();
702 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700703 case LayoutToken::INDEX:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500704 setFlag(Layout::kIndex_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500705 index = this->layoutInt();
706 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700707 case LayoutToken::SET:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500708 setFlag(Layout::kSet_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500709 set = this->layoutInt();
710 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700711 case LayoutToken::BUILTIN:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500712 setFlag(Layout::kBuiltin_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500713 builtin = this->layoutInt();
714 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700715 case LayoutToken::INPUT_ATTACHMENT_INDEX:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500716 setFlag(Layout::kInputAttachmentIndex_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500717 inputAttachmentIndex = this->layoutInt();
718 break;
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400719 default:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500720 this->error(t, "'" + text + "' is not a valid layout qualifier");
Ethan Nicholasd608c092017-10-26 09:30:08 -0400721 break;
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500722 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700723 } else {
Brian Osmana77ed8b2021-02-23 12:54:22 -0500724 this->error(t, "'" + text + "' is not a valid layout qualifier");
ethannicholasb3058bd2016-07-01 08:22:01 -0700725 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400726 if (this->checkNext(Token::Kind::TK_RPAREN)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700727 break;
728 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400729 if (!this->expect(Token::Kind::TK_COMMA, "','")) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700730 break;
731 }
732 }
733 }
Brian Osman99ddd2a2021-08-27 11:21:12 -0400734 return Layout(flags, location, offset, binding, index, set, builtin, inputAttachmentIndex);
ethannicholasb3058bd2016-07-01 08:22:01 -0700735}
736
Brian Osmane49703f2021-04-19 11:15:24 -0400737/* layout? (UNIFORM | CONST | IN | OUT | INOUT | FLAT | NOPERSPECTIVE | INLINE)* */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500738Modifiers Parser::modifiers() {
739 Layout layout = this->layout();
ethannicholasb3058bd2016-07-01 08:22:01 -0700740 int flags = 0;
741 for (;;) {
742 // TODO: handle duplicate / incompatible flags
John Stiles7d5b90a2021-01-21 14:26:51 -0500743 int tokenFlag = parse_modifier_token(peek().fKind);
744 if (!tokenFlag) {
745 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700746 }
John Stiles7d5b90a2021-01-21 14:26:51 -0500747 flags |= tokenFlag;
748 this->nextToken();
ethannicholasb3058bd2016-07-01 08:22:01 -0700749 }
John Stiles7d5b90a2021-01-21 14:26:51 -0500750 return Modifiers(layout, flags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700751}
752
Ethan Nicholas11d53972016-11-28 11:23:23 -0500753Modifiers Parser::modifiersWithDefaults(int defaultFlags) {
754 Modifiers result = this->modifiers();
ethannicholasb3058bd2016-07-01 08:22:01 -0700755 if (!result.fFlags) {
Ethan Nicholas11d53972016-11-28 11:23:23 -0500756 return Modifiers(result.fLayout, defaultFlags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700757 }
758 return result;
759}
760
761/* ifStatement | forStatement | doStatement | whileStatement | block | expression */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400762ASTNode::ID Parser::statement() {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -0400763 Token start = this->nextToken();
764 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -0400765 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -0400766 return ASTNode::ID::Invalid();
767 }
768 this->pushback(start);
ethannicholasb3058bd2016-07-01 08:22:01 -0700769 switch (start.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400770 case Token::Kind::TK_IF: // fall through
771 case Token::Kind::TK_STATIC_IF:
ethannicholasb3058bd2016-07-01 08:22:01 -0700772 return this->ifStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400773 case Token::Kind::TK_FOR:
ethannicholasb3058bd2016-07-01 08:22:01 -0700774 return this->forStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400775 case Token::Kind::TK_DO:
ethannicholasb3058bd2016-07-01 08:22:01 -0700776 return this->doStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400777 case Token::Kind::TK_WHILE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700778 return this->whileStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400779 case Token::Kind::TK_SWITCH: // fall through
780 case Token::Kind::TK_STATIC_SWITCH:
Ethan Nicholasaf197692017-02-27 13:26:45 -0500781 return this->switchStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400782 case Token::Kind::TK_RETURN:
ethannicholasb3058bd2016-07-01 08:22:01 -0700783 return this->returnStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400784 case Token::Kind::TK_BREAK:
ethannicholasb3058bd2016-07-01 08:22:01 -0700785 return this->breakStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400786 case Token::Kind::TK_CONTINUE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700787 return this->continueStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400788 case Token::Kind::TK_DISCARD:
ethannicholasb3058bd2016-07-01 08:22:01 -0700789 return this->discardStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400790 case Token::Kind::TK_LBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700791 return this->block();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400792 case Token::Kind::TK_SEMICOLON:
Ethan Nicholas11d53972016-11-28 11:23:23 -0500793 this->nextToken();
John Stiles3b209362020-11-16 17:03:10 -0500794 return this->createNode(start.fOffset, ASTNode::Kind::kBlock);
John Stiles02014312021-08-04 16:03:12 -0400795 case Token::Kind::TK_HIGHP:
796 case Token::Kind::TK_MEDIUMP:
797 case Token::Kind::TK_LOWP:
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400798 case Token::Kind::TK_CONST:
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400799 case Token::Kind::TK_IDENTIFIER:
John Stiles76389b72021-01-25 13:49:05 -0500800 return this->varDeclarationsOrExpressionStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700801 default:
802 return this->expressionStatement();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500803 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700804}
805
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500806/* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* QUESTION? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400807ASTNode::ID Parser::type() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700808 Token type;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400809 if (!this->expect(Token::Kind::TK_IDENTIFIER, "a type", &type)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400810 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700811 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700812 if (!this->isType(this->text(type))) {
813 this->error(type, ("no type named '" + this->text(type) + "'").c_str());
Ethan Nicholasfc994162019-06-06 10:04:27 -0400814 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700815 }
Brian Osman00fea5b2021-01-28 09:46:30 -0500816 ASTNode::ID result = this->createNode(type.fOffset, ASTNode::Kind::kType, this->text(type));
John Stilesd39aec92020-12-03 14:37:16 -0500817 bool isArray = false;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400818 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stilesd39aec92020-12-03 14:37:16 -0500819 if (isArray) {
820 this->error(this->peek(), "multi-dimensional arrays are not supported");
821 return ASTNode::ID::Invalid();
822 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400823 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400824 SKSL_INT i;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500825 if (this->intLiteral(&i)) {
John Stiles08070f62020-11-17 10:45:49 -0500826 this->addChild(result, this->createNode(this->peek().fOffset,
827 ASTNode::Kind::kInt, i));
Ethan Nicholas50afc172017-02-16 14:49:57 -0500828 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400829 return ASTNode::ID::Invalid();
Ethan Nicholas50afc172017-02-16 14:49:57 -0500830 }
831 } else {
John Stiles3b209362020-11-16 17:03:10 -0500832 this->createEmptyChild(result);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500833 }
John Stilesd39aec92020-12-03 14:37:16 -0500834 isArray = true;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400835 this->expect(Token::Kind::TK_RBRACKET, "']'");
Ethan Nicholas50afc172017-02-16 14:49:57 -0500836 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400837 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700838}
839
John Stiles57a996b2020-04-19 19:05:12 -0700840/* IDENTIFIER LBRACE
841 varDeclaration+
842 RBRACE (IDENTIFIER (LBRACKET expression? RBRACKET)*)? SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400843ASTNode::ID Parser::interfaceBlock(Modifiers mods) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700844 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500845 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400846 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700847 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400848 if (peek().fKind != Token::Kind::TK_LBRACE) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700849 // we only get into interfaceBlock if we found a top-level identifier which was not a type.
Ethan Nicholas11d53972016-11-28 11:23:23 -0500850 // 99% of the time, the user was not actually intending to create an interface block, so
ethannicholasb3058bd2016-07-01 08:22:01 -0700851 // it's better to report it as an unknown type
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700852 this->error(name, "no type named '" + this->text(name) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400853 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700854 }
John Stiles3b209362020-11-16 17:03:10 -0500855 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kInterfaceBlock);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400856 ASTNode::InterfaceBlockData id(mods, this->text(name), 0, "", 0);
ethannicholasb3058bd2016-07-01 08:22:01 -0700857 this->nextToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400858 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400859 ASTNode::ID decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700860 if (!decl) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400861 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700862 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400863 getNode(result).addChild(decl);
864 ++id.fDeclarationCount;
ethannicholasb3058bd2016-07-01 08:22:01 -0700865 }
John Stiles57a996b2020-04-19 19:05:12 -0700866 if (id.fDeclarationCount == 0) {
867 this->error(name, "interface block '" + this->text(name) +
868 "' must contain at least one member");
869 return ASTNode::ID::Invalid();
870 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700871 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -0400872 std::vector<ASTNode> sizes;
Ethan Nicholas962dec42021-06-10 13:06:39 -0400873 skstd::string_view instanceName;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700874 Token instanceNameToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400875 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &instanceNameToken)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400876 id.fInstanceName = this->text(instanceNameToken);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400877 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stilesd39aec92020-12-03 14:37:16 -0500878 if (id.fIsArray) {
879 this->error(this->peek(), "multi-dimensional arrays are not supported");
880 return false;
881 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400882 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400883 ASTNode::ID size = this->expression();
Ethan Nicholas50afc172017-02-16 14:49:57 -0500884 if (!size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400885 return ASTNode::ID::Invalid();
Ethan Nicholas50afc172017-02-16 14:49:57 -0500886 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400887 getNode(result).addChild(size);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500888 } else {
John Stiles3b209362020-11-16 17:03:10 -0500889 this->createEmptyChild(result);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500890 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400891 this->expect(Token::Kind::TK_RBRACKET, "']'");
John Stilesd39aec92020-12-03 14:37:16 -0500892 id.fIsArray = true;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500893 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700894 instanceName = this->text(instanceNameToken);
ethannicholasb3058bd2016-07-01 08:22:01 -0700895 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400896 getNode(result).setInterfaceBlockData(id);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400897 this->expect(Token::Kind::TK_SEMICOLON, "';'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400898 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700899}
900
901/* IF LPAREN expression RPAREN statement (ELSE statement)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400902ASTNode::ID Parser::ifStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700903 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400904 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_IF, &start);
905 if (!isStatic && !this->expect(Token::Kind::TK_IF, "'if'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400906 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700907 }
John Stiles3b209362020-11-16 17:03:10 -0500908 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kIf, isStatic);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400909 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400910 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700911 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400912 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700913 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400914 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700915 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400916 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400917 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400918 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700919 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400920 ASTNode::ID ifTrue = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700921 if (!ifTrue) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400922 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700923 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400924 getNode(result).addChild(ifTrue);
925 ASTNode::ID ifFalse;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400926 if (this->checkNext(Token::Kind::TK_ELSE)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700927 ifFalse = this->statement();
928 if (!ifFalse) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400929 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700930 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400931 getNode(result).addChild(ifFalse);
ethannicholasb3058bd2016-07-01 08:22:01 -0700932 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400933 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700934}
935
936/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400937ASTNode::ID Parser::doStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700938 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400939 if (!this->expect(Token::Kind::TK_DO, "'do'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400940 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700941 }
John Stiles3b209362020-11-16 17:03:10 -0500942 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kDo);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400943 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700944 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400945 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700946 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400947 getNode(result).addChild(statement);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400948 if (!this->expect(Token::Kind::TK_WHILE, "'while'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400949 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700950 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400951 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400952 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700953 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400954 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700955 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400956 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700957 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400958 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400959 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400960 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700961 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400962 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400963 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700964 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400965 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700966}
967
968/* WHILE LPAREN expression RPAREN STATEMENT */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400969ASTNode::ID Parser::whileStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700970 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400971 if (!this->expect(Token::Kind::TK_WHILE, "'while'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400972 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700973 }
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 }
John Stiles3b209362020-11-16 17:03:10 -0500977 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kWhile);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400978 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700979 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400980 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700981 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400982 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400983 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400984 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700985 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400986 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700987 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400988 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700989 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400990 getNode(result).addChild(statement);
991 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700992}
993
Ethan Nicholasaf197692017-02-27 13:26:45 -0500994/* CASE expression COLON statement* */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400995ASTNode::ID Parser::switchCase() {
Ethan Nicholasaf197692017-02-27 13:26:45 -0500996 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400997 if (!this->expect(Token::Kind::TK_CASE, "'case'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400998 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -0500999 }
John Stiles3b209362020-11-16 17:03:10 -05001000 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kSwitchCase);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001001 ASTNode::ID value = this->expression();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001002 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001003 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001004 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001005 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001006 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001007 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001008 getNode(result).addChild(value);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001009 while (this->peek().fKind != Token::Kind::TK_RBRACE &&
1010 this->peek().fKind != Token::Kind::TK_CASE &&
1011 this->peek().fKind != Token::Kind::TK_DEFAULT) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001012 ASTNode::ID s = this->statement();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001013 if (!s) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001014 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001015 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001016 getNode(result).addChild(s);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001017 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001018 return result;
Ethan Nicholasaf197692017-02-27 13:26:45 -05001019}
1020
1021/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001022ASTNode::ID Parser::switchStatement() {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001023 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001024 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_SWITCH, &start);
1025 if (!isStatic && !this->expect(Token::Kind::TK_SWITCH, "'switch'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001026 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001027 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001028 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001029 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001030 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001031 ASTNode::ID value = this->expression();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001032 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001033 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001034 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001035 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001036 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001037 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001038 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001039 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001040 }
John Stiles3b209362020-11-16 17:03:10 -05001041 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kSwitch, isStatic);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001042 getNode(result).addChild(value);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001043 while (this->peek().fKind == Token::Kind::TK_CASE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001044 ASTNode::ID c = this->switchCase();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001045 if (!c) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001046 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001047 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001048 getNode(result).addChild(c);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001049 }
1050 // Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
1051 // parts of the compiler may rely upon this assumption.
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001052 if (this->peek().fKind == Token::Kind::TK_DEFAULT) {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001053 Token defaultStart;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001054 SkAssertResult(this->expect(Token::Kind::TK_DEFAULT, "'default'", &defaultStart));
1055 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001056 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001057 }
John Stiles3b209362020-11-16 17:03:10 -05001058 ASTNode::ID defaultCase = this->addChild(
1059 result, this->createNode(defaultStart.fOffset, ASTNode::Kind::kSwitchCase));
1060 this->createEmptyChild(defaultCase); // empty test to signify default case
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001061 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001062 ASTNode::ID s = this->statement();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001063 if (!s) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001064 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001065 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001066 getNode(defaultCase).addChild(s);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001067 }
Ethan Nicholasaf197692017-02-27 13:26:45 -05001068 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001069 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001070 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001071 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001072 return result;
Ethan Nicholasaf197692017-02-27 13:26:45 -05001073}
1074
Ethan Nicholas11d53972016-11-28 11:23:23 -05001075/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
ethannicholasb3058bd2016-07-01 08:22:01 -07001076 STATEMENT */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001077ASTNode::ID Parser::forStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001078 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001079 if (!this->expect(Token::Kind::TK_FOR, "'for'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001080 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001081 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001082 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001083 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001084 }
John Stiles3b209362020-11-16 17:03:10 -05001085 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kFor);
ethannicholasb3058bd2016-07-01 08:22:01 -07001086 Token nextToken = this->peek();
John Stiles89b484a2021-04-19 14:57:27 -04001087 if (nextToken.fKind == Token::Kind::TK_SEMICOLON) {
1088 // An empty init-statement.
1089 this->nextToken();
1090 this->createEmptyChild(result);
1091 } else {
1092 // The init-statement must be an expression or variable declaration.
1093 ASTNode::ID initializer = this->varDeclarationsOrExpressionStatement();
1094 if (!initializer) {
1095 return ASTNode::ID::Invalid();
ethannicholasa54401d2016-10-14 08:37:32 -07001096 }
John Stiles89b484a2021-04-19 14:57:27 -04001097 getNode(result).addChild(initializer);
ethannicholasb3058bd2016-07-01 08:22:01 -07001098 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001099 ASTNode::ID test;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001100 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001101 test = this->expression();
1102 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001103 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001104 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001105 getNode(result).addChild(test);
1106 } else {
John Stiles3b209362020-11-16 17:03:10 -05001107 this->createEmptyChild(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001108 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001109 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001110 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001111 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001112 ASTNode::ID next;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001113 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001114 next = this->expression();
1115 if (!next) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001116 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001117 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001118 getNode(result).addChild(next);
1119 } else {
John Stiles3b209362020-11-16 17:03:10 -05001120 this->createEmptyChild(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001121 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001122 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001123 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001124 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001125 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001126 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001127 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001128 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001129 getNode(result).addChild(statement);
1130 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001131}
1132
1133/* RETURN expression? SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001134ASTNode::ID Parser::returnStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001135 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001136 if (!this->expect(Token::Kind::TK_RETURN, "'return'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001137 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001138 }
John Stiles3b209362020-11-16 17:03:10 -05001139 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kReturn);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001140 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001141 ASTNode::ID expression = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001142 if (!expression) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001143 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001144 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001145 getNode(result).addChild(expression);
ethannicholasb3058bd2016-07-01 08:22:01 -07001146 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001147 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001148 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001149 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001150 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001151}
1152
1153/* BREAK SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001154ASTNode::ID Parser::breakStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001155 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001156 if (!this->expect(Token::Kind::TK_BREAK, "'break'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001157 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001158 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001159 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001160 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001161 }
John Stiles3b209362020-11-16 17:03:10 -05001162 return this->createNode(start.fOffset, ASTNode::Kind::kBreak);
ethannicholasb3058bd2016-07-01 08:22:01 -07001163}
1164
1165/* CONTINUE SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001166ASTNode::ID Parser::continueStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001167 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001168 if (!this->expect(Token::Kind::TK_CONTINUE, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001169 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001170 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001171 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001172 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001173 }
John Stiles3b209362020-11-16 17:03:10 -05001174 return this->createNode(start.fOffset, ASTNode::Kind::kContinue);
ethannicholasb3058bd2016-07-01 08:22:01 -07001175}
1176
1177/* DISCARD SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001178ASTNode::ID Parser::discardStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001179 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001180 if (!this->expect(Token::Kind::TK_DISCARD, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001181 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001182 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001183 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001184 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001185 }
John Stiles3b209362020-11-16 17:03:10 -05001186 return this->createNode(start.fOffset, ASTNode::Kind::kDiscard);
ethannicholasb3058bd2016-07-01 08:22:01 -07001187}
1188
1189/* LBRACE statement* RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001190ASTNode::ID Parser::block() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001191 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001192 if (!this->expect(Token::Kind::TK_LBRACE, "'{'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001193 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001194 }
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001195 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001196 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001197 return ASTNode::ID::Invalid();
1198 }
John Stiles3b209362020-11-16 17:03:10 -05001199 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kBlock);
ethannicholasb3058bd2016-07-01 08:22:01 -07001200 for (;;) {
1201 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001202 case Token::Kind::TK_RBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -07001203 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001204 return result;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001205 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001206 this->error(this->peek(), "expected '}', but found end of file");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001207 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001208 default: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001209 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001210 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001211 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001212 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001213 getNode(result).addChild(statement);
ethannicholasb3058bd2016-07-01 08:22:01 -07001214 }
1215 }
1216 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001217 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001218}
1219
1220/* expression SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001221ASTNode::ID Parser::expressionStatement() {
1222 ASTNode::ID expr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001223 if (expr) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001224 if (this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001225 return expr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001226 }
1227 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001228 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001229}
1230
1231/* assignmentExpression (COMMA assignmentExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001232ASTNode::ID Parser::expression() {
1233 ASTNode::ID result = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001234 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001235 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001236 }
1237 Token t;
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001238 AutoDepth depth(this);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001239 while (this->checkNext(Token::Kind::TK_COMMA, &t)) {
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001240 if (!depth.increase()) {
1241 return ASTNode::ID::Invalid();
1242 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001243 ASTNode::ID right = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001244 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001245 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001246 }
John Stiles45990502021-02-16 10:55:27 -05001247 ASTNode::ID newResult = this->createNode(t.fOffset, ASTNode::Kind::kBinary,
1248 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001249 getNode(newResult).addChild(result);
1250 getNode(newResult).addChild(right);
1251 result = newResult;
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001252 }
1253 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001254}
1255
1256/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1257 BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1258 assignmentExpression)*
1259 */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001260ASTNode::ID Parser::assignmentExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001261 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001262 ASTNode::ID result = this->ternaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001263 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001264 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001265 }
1266 for (;;) {
1267 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001268 case Token::Kind::TK_EQ: // fall through
1269 case Token::Kind::TK_STAREQ: // fall through
1270 case Token::Kind::TK_SLASHEQ: // fall through
1271 case Token::Kind::TK_PERCENTEQ: // fall through
1272 case Token::Kind::TK_PLUSEQ: // fall through
1273 case Token::Kind::TK_MINUSEQ: // fall through
1274 case Token::Kind::TK_SHLEQ: // fall through
1275 case Token::Kind::TK_SHREQ: // fall through
1276 case Token::Kind::TK_BITWISEANDEQ: // fall through
1277 case Token::Kind::TK_BITWISEXOREQ: // fall through
John Stiles8b3b1592020-11-23 11:06:44 -05001278 case Token::Kind::TK_BITWISEOREQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001279 if (!depth.increase()) {
1280 return ASTNode::ID::Invalid();
1281 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001282 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001283 ASTNode::ID right = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001284 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001285 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001286 }
John Stiles3b209362020-11-16 17:03:10 -05001287 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001288 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001289 getNode(newResult).addChild(result);
1290 getNode(newResult).addChild(right);
1291 result = newResult;
1292 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001293 }
1294 default:
1295 return result;
1296 }
1297 }
1298}
1299
1300/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001301ASTNode::ID Parser::ternaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001302 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001303 ASTNode::ID base = this->logicalOrExpression();
1304 if (!base) {
1305 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001306 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001307 if (this->checkNext(Token::Kind::TK_QUESTION)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001308 if (!depth.increase()) {
1309 return ASTNode::ID::Invalid();
1310 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001311 ASTNode::ID trueExpr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001312 if (!trueExpr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001313 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001314 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001315 if (this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001316 ASTNode::ID falseExpr = this->assignmentExpression();
1317 if (!falseExpr) {
1318 return ASTNode::ID::Invalid();
1319 }
John Stiles3b209362020-11-16 17:03:10 -05001320 ASTNode::ID ternary = this->createNode(getNode(base).fOffset, ASTNode::Kind::kTernary);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001321 getNode(ternary).addChild(base);
1322 getNode(ternary).addChild(trueExpr);
1323 getNode(ternary).addChild(falseExpr);
1324 return ternary;
ethannicholasb3058bd2016-07-01 08:22:01 -07001325 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001326 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001327 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001328 return base;
ethannicholasb3058bd2016-07-01 08:22:01 -07001329}
1330
1331/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001332ASTNode::ID Parser::logicalOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001333 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001334 ASTNode::ID result = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001335 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001336 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001337 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001338 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001339 while (this->checkNext(Token::Kind::TK_LOGICALOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001340 if (!depth.increase()) {
1341 return ASTNode::ID::Invalid();
1342 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001343 ASTNode::ID right = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001344 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001345 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001346 }
John Stiles3b209362020-11-16 17:03:10 -05001347 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001348 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001349 getNode(newResult).addChild(result);
1350 getNode(newResult).addChild(right);
1351 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001352 }
1353 return result;
1354}
1355
1356/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001357ASTNode::ID Parser::logicalXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001358 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001359 ASTNode::ID result = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001360 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001361 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001362 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001363 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001364 while (this->checkNext(Token::Kind::TK_LOGICALXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001365 if (!depth.increase()) {
1366 return ASTNode::ID::Invalid();
1367 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001368 ASTNode::ID right = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001369 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001370 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001371 }
John Stiles3b209362020-11-16 17:03:10 -05001372 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001373 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001374 getNode(newResult).addChild(result);
1375 getNode(newResult).addChild(right);
1376 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001377 }
1378 return result;
1379}
1380
1381/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001382ASTNode::ID Parser::logicalAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001383 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001384 ASTNode::ID result = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001385 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001386 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001387 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001388 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001389 while (this->checkNext(Token::Kind::TK_LOGICALAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001390 if (!depth.increase()) {
1391 return ASTNode::ID::Invalid();
1392 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001393 ASTNode::ID right = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001394 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001395 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001396 }
John Stiles3b209362020-11-16 17:03:10 -05001397 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001398 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001399 getNode(newResult).addChild(result);
1400 getNode(newResult).addChild(right);
1401 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001402 }
1403 return result;
1404}
1405
1406/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001407ASTNode::ID Parser::bitwiseOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001408 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001409 ASTNode::ID result = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001410 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001411 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001412 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001413 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001414 while (this->checkNext(Token::Kind::TK_BITWISEOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001415 if (!depth.increase()) {
1416 return ASTNode::ID::Invalid();
1417 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001418 ASTNode::ID right = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001419 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001420 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001421 }
John Stiles45990502021-02-16 10:55:27 -05001422 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
1423 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001424 getNode(newResult).addChild(result);
1425 getNode(newResult).addChild(right);
1426 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001427 }
1428 return result;
1429}
1430
1431/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001432ASTNode::ID Parser::bitwiseXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001433 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001434 ASTNode::ID result = this->bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001435 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001436 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001437 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001438 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001439 while (this->checkNext(Token::Kind::TK_BITWISEXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001440 if (!depth.increase()) {
1441 return ASTNode::ID::Invalid();
1442 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001443 ASTNode::ID right = this->bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001444 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001445 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001446 }
John Stiles45990502021-02-16 10:55:27 -05001447 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
1448 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001449 getNode(newResult).addChild(result);
1450 getNode(newResult).addChild(right);
1451 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001452 }
1453 return result;
1454}
1455
1456/* equalityExpression (BITWISEAND equalityExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001457ASTNode::ID Parser::bitwiseAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001458 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001459 ASTNode::ID result = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001460 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001461 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001462 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001463 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001464 while (this->checkNext(Token::Kind::TK_BITWISEAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001465 if (!depth.increase()) {
1466 return ASTNode::ID::Invalid();
1467 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001468 ASTNode::ID right = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001469 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001470 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001471 }
John Stiles3b209362020-11-16 17:03:10 -05001472 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001473 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001474 getNode(newResult).addChild(result);
1475 getNode(newResult).addChild(right);
1476 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001477 }
1478 return result;
1479}
1480
1481/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001482ASTNode::ID Parser::equalityExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001483 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001484 ASTNode::ID result = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001485 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001486 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001487 }
1488 for (;;) {
1489 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001490 case Token::Kind::TK_EQEQ: // fall through
1491 case Token::Kind::TK_NEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001492 if (!depth.increase()) {
1493 return ASTNode::ID::Invalid();
1494 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001495 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001496 ASTNode::ID right = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001497 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001498 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001499 }
John Stiles3b209362020-11-16 17:03:10 -05001500 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001501 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001502 getNode(newResult).addChild(result);
1503 getNode(newResult).addChild(right);
1504 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001505 break;
1506 }
1507 default:
1508 return result;
1509 }
1510 }
1511}
1512
1513/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001514ASTNode::ID Parser::relationalExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001515 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001516 ASTNode::ID result = this->shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001517 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001518 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001519 }
1520 for (;;) {
1521 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001522 case Token::Kind::TK_LT: // fall through
1523 case Token::Kind::TK_GT: // fall through
1524 case Token::Kind::TK_LTEQ: // fall through
1525 case Token::Kind::TK_GTEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001526 if (!depth.increase()) {
1527 return ASTNode::ID::Invalid();
1528 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001529 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001530 ASTNode::ID right = this->shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001531 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001532 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001533 }
John Stiles3b209362020-11-16 17:03:10 -05001534 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001535 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001536 getNode(newResult).addChild(result);
1537 getNode(newResult).addChild(right);
1538 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001539 break;
1540 }
1541 default:
1542 return result;
1543 }
1544 }
1545}
1546
1547/* additiveExpression ((SHL | SHR) additiveExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001548ASTNode::ID Parser::shiftExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001549 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001550 ASTNode::ID result = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001551 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001552 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001553 }
1554 for (;;) {
1555 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001556 case Token::Kind::TK_SHL: // fall through
1557 case Token::Kind::TK_SHR: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001558 if (!depth.increase()) {
1559 return ASTNode::ID::Invalid();
1560 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001561 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001562 ASTNode::ID right = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001563 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001564 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001565 }
John Stiles3b209362020-11-16 17:03:10 -05001566 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001567 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001568 getNode(newResult).addChild(result);
1569 getNode(newResult).addChild(right);
1570 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001571 break;
1572 }
1573 default:
1574 return result;
1575 }
1576 }
1577}
1578
1579/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001580ASTNode::ID Parser::additiveExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001581 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001582 ASTNode::ID result = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001583 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001584 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001585 }
1586 for (;;) {
1587 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001588 case Token::Kind::TK_PLUS: // fall through
1589 case Token::Kind::TK_MINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001590 if (!depth.increase()) {
1591 return ASTNode::ID::Invalid();
1592 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001593 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001594 ASTNode::ID right = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001595 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001596 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001597 }
John Stiles3b209362020-11-16 17:03:10 -05001598 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001599 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001600 getNode(newResult).addChild(result);
1601 getNode(newResult).addChild(right);
1602 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001603 break;
1604 }
1605 default:
1606 return result;
1607 }
1608 }
1609}
1610
1611/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001612ASTNode::ID Parser::multiplicativeExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001613 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001614 ASTNode::ID result = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001615 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001616 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001617 }
1618 for (;;) {
1619 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001620 case Token::Kind::TK_STAR: // fall through
1621 case Token::Kind::TK_SLASH: // fall through
1622 case Token::Kind::TK_PERCENT: {
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->unaryExpression();
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/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001645ASTNode::ID Parser::unaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001646 AutoDepth depth(this);
ethannicholasb3058bd2016-07-01 08:22:01 -07001647 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001648 case Token::Kind::TK_PLUS: // fall through
1649 case Token::Kind::TK_MINUS: // fall through
1650 case Token::Kind::TK_LOGICALNOT: // fall through
1651 case Token::Kind::TK_BITWISENOT: // fall through
1652 case Token::Kind::TK_PLUSPLUS: // fall through
1653 case Token::Kind::TK_MINUSMINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001654 if (!depth.increase()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001655 return ASTNode::ID::Invalid();
Ethan Nicholas6dcc3252019-02-20 15:18:36 -05001656 }
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001657 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001658 ASTNode::ID expr = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001659 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001660 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001661 }
John Stiles45990502021-02-16 10:55:27 -05001662 ASTNode::ID result = this->createNode(t.fOffset, ASTNode::Kind::kPrefix,
1663 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001664 getNode(result).addChild(expr);
1665 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001666 }
1667 default:
1668 return this->postfixExpression();
1669 }
1670}
1671
1672/* term suffix* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001673ASTNode::ID Parser::postfixExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001674 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001675 ASTNode::ID result = this->term();
ethannicholasb3058bd2016-07-01 08:22:01 -07001676 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001677 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001678 }
1679 for (;;) {
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001680 Token t = this->peek();
1681 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001682 case Token::Kind::TK_FLOAT_LITERAL:
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001683 if (this->text(t)[0] != '.') {
1684 return result;
1685 }
John Stiles30212b72020-06-11 17:55:07 -04001686 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001687 case Token::Kind::TK_LBRACKET:
1688 case Token::Kind::TK_DOT:
1689 case Token::Kind::TK_LPAREN:
1690 case Token::Kind::TK_PLUSPLUS:
1691 case Token::Kind::TK_MINUSMINUS:
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001692 if (!depth.increase()) {
1693 return ASTNode::ID::Invalid();
1694 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001695 result = this->suffix(result);
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001696 if (!result) {
1697 return ASTNode::ID::Invalid();
1698 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001699 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001700 default:
1701 return result;
1702 }
1703 }
1704}
1705
Ethan Nicholas11d53972016-11-28 11:23:23 -05001706/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
Brian Osmanc9145f32021-07-08 13:40:10 -04001707 PLUSPLUS | MINUSMINUS | FLOAT_LITERAL [IDENTIFIER] */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001708ASTNode::ID Parser::suffix(ASTNode::ID base) {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001709 SkASSERT(base);
ethannicholasb3058bd2016-07-01 08:22:01 -07001710 Token next = this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001711 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001712 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001713 return ASTNode::ID::Invalid();
1714 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001715 switch (next.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001716 case Token::Kind::TK_LBRACKET: {
1717 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
John Stiles3b209362020-11-16 17:03:10 -05001718 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kIndex);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001719 getNode(result).addChild(base);
1720 return result;
ethannicholas5961bc92016-10-12 06:39:56 -07001721 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001722 ASTNode::ID e = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001723 if (!e) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001724 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001725 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001726 this->expect(Token::Kind::TK_RBRACKET, "']' to complete array access expression");
John Stiles3b209362020-11-16 17:03:10 -05001727 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kIndex);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001728 getNode(result).addChild(base);
1729 getNode(result).addChild(e);
1730 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001731 }
Brian Osman6518d772020-09-10 16:50:06 -04001732 case Token::Kind::TK_DOT: {
1733 int offset = this->peek().fOffset;
Ethan Nicholas962dec42021-06-10 13:06:39 -04001734 skstd::string_view text;
Brian Osman6518d772020-09-10 16:50:06 -04001735 if (this->identifier(&text)) {
John Stiles3b209362020-11-16 17:03:10 -05001736 ASTNode::ID result = this->createNode(offset, ASTNode::Kind::kField,
1737 std::move(text));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001738 getNode(result).addChild(base);
1739 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001740 }
Brian Osman6518d772020-09-10 16:50:06 -04001741 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04001742 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001743 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholase455f652019-09-13 12:52:55 -04001744 // Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
1745 // floating point literals, possibly followed by an identifier. Handle that here.
Ethan Nicholas962dec42021-06-10 13:06:39 -04001746 skstd::string_view field = this->text(next);
Ethan Nicholasd2e09602021-06-10 11:21:59 -04001747 SkASSERT(field[0] == '.');
1748 field.remove_prefix(1);
1749 for (auto iter = field.begin(); iter != field.end(); ++iter) {
1750 if (*iter != '0' && *iter != '1') {
Ethan Nicholase455f652019-09-13 12:52:55 -04001751 this->error(next, "invalid swizzle");
1752 return ASTNode::ID::Invalid();
1753 }
1754 }
1755 // use the next *raw* token so we don't ignore whitespace - we only care about
1756 // identifiers that directly follow the float
1757 Token id = this->nextRawToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001758 if (id.fKind == Token::Kind::TK_IDENTIFIER) {
Ethan Nicholas962dec42021-06-10 13:06:39 -04001759 field = skstd::string_view(field.data(), field.length() + id.fLength);
Ethan Nicholase455f652019-09-13 12:52:55 -04001760 } else {
1761 this->pushback(id);
1762 }
John Stiles3b209362020-11-16 17:03:10 -05001763 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kField, field);
Ethan Nicholase455f652019-09-13 12:52:55 -04001764 getNode(result).addChild(base);
1765 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001766 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001767 case Token::Kind::TK_LPAREN: {
John Stiles3b209362020-11-16 17:03:10 -05001768 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kCall);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001769 getNode(result).addChild(base);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001770 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001771 for (;;) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001772 ASTNode::ID expr = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001773 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001774 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001775 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001776 getNode(result).addChild(expr);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001777 if (!this->checkNext(Token::Kind::TK_COMMA)) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001778 break;
1779 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001780 }
1781 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001782 this->expect(Token::Kind::TK_RPAREN, "')' to complete function parameters");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001783 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001784 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001785 case Token::Kind::TK_PLUSPLUS: // fall through
1786 case Token::Kind::TK_MINUSMINUS: {
John Stiles45990502021-02-16 10:55:27 -05001787 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kPostfix,
1788 Operator(next.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001789 getNode(result).addChild(base);
1790 return result;
1791 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001792 default: {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001793 this->error(next, "expected expression suffix, but found '" + this->text(next) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001794 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001795 }
1796 }
1797}
1798
Brian Osman33c64a42020-12-23 10:26:38 -05001799/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001800ASTNode::ID Parser::term() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001801 Token t = this->peek();
1802 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001803 case Token::Kind::TK_IDENTIFIER: {
Ethan Nicholas962dec42021-06-10 13:06:39 -04001804 skstd::string_view text;
ethannicholasb3058bd2016-07-01 08:22:01 -07001805 if (this->identifier(&text)) {
John Stiles3b209362020-11-16 17:03:10 -05001806 return this->createNode(t.fOffset, ASTNode::Kind::kIdentifier, std::move(text));
ethannicholasb3058bd2016-07-01 08:22:01 -07001807 }
John Stiles30212b72020-06-11 17:55:07 -04001808 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001809 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001810 case Token::Kind::TK_INT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001811 SKSL_INT i;
ethannicholasb3058bd2016-07-01 08:22:01 -07001812 if (this->intLiteral(&i)) {
John Stiles3b209362020-11-16 17:03:10 -05001813 return this->createNode(t.fOffset, ASTNode::Kind::kInt, i);
ethannicholasb3058bd2016-07-01 08:22:01 -07001814 }
1815 break;
1816 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001817 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001818 SKSL_FLOAT f;
ethannicholasb3058bd2016-07-01 08:22:01 -07001819 if (this->floatLiteral(&f)) {
John Stiles3b209362020-11-16 17:03:10 -05001820 return this->createNode(t.fOffset, ASTNode::Kind::kFloat, f);
ethannicholasb3058bd2016-07-01 08:22:01 -07001821 }
1822 break;
1823 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001824 case Token::Kind::TK_TRUE_LITERAL: // fall through
1825 case Token::Kind::TK_FALSE_LITERAL: {
ethannicholasb3058bd2016-07-01 08:22:01 -07001826 bool b;
1827 if (this->boolLiteral(&b)) {
John Stiles3b209362020-11-16 17:03:10 -05001828 return this->createNode(t.fOffset, ASTNode::Kind::kBool, b);
ethannicholasb3058bd2016-07-01 08:22:01 -07001829 }
1830 break;
1831 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001832 case Token::Kind::TK_LPAREN: {
ethannicholasb3058bd2016-07-01 08:22:01 -07001833 this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001834 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001835 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001836 return ASTNode::ID::Invalid();
1837 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001838 ASTNode::ID result = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001839 if (result) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001840 this->expect(Token::Kind::TK_RPAREN, "')' to complete expression");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001841 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001842 }
1843 break;
1844 }
1845 default:
1846 this->nextToken();
John Stilesf94348f2020-12-23 18:58:43 -05001847 this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001848 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001849 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001850}
1851
1852/* INT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001853bool Parser::intLiteral(SKSL_INT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001854 Token t;
John Stilesf94348f2020-12-23 18:58:43 -05001855 if (!this->expect(Token::Kind::TK_INT_LITERAL, "integer literal", &t)) {
1856 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001857 }
Ethan Nicholas962dec42021-06-10 13:06:39 -04001858 skstd::string_view s = this->text(t);
John Stilesf94348f2020-12-23 18:58:43 -05001859 if (!SkSL::stoi(s, dest)) {
1860 this->error(t, "integer is too large: " + s);
1861 return false;
1862 }
1863 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001864}
1865
John Stilesf94348f2020-12-23 18:58:43 -05001866
ethannicholasb3058bd2016-07-01 08:22:01 -07001867/* FLOAT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001868bool Parser::floatLiteral(SKSL_FLOAT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001869 Token t;
John Stilesf94348f2020-12-23 18:58:43 -05001870 if (!this->expect(Token::Kind::TK_FLOAT_LITERAL, "float literal", &t)) {
1871 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001872 }
Ethan Nicholas962dec42021-06-10 13:06:39 -04001873 skstd::string_view s = this->text(t);
John Stilesf94348f2020-12-23 18:58:43 -05001874 if (!SkSL::stod(s, dest)) {
1875 this->error(t, "floating-point value is too large: " + s);
1876 return false;
1877 }
1878 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001879}
1880
1881/* TRUE_LITERAL | FALSE_LITERAL */
1882bool Parser::boolLiteral(bool* dest) {
1883 Token t = this->nextToken();
1884 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001885 case Token::Kind::TK_TRUE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07001886 *dest = true;
1887 return true;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001888 case Token::Kind::TK_FALSE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07001889 *dest = false;
1890 return true;
1891 default:
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001892 this->error(t, "expected 'true' or 'false', but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001893 return false;
1894 }
1895}
1896
1897/* IDENTIFIER */
Ethan Nicholas962dec42021-06-10 13:06:39 -04001898bool Parser::identifier(skstd::string_view* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001899 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001900 if (this->expect(Token::Kind::TK_IDENTIFIER, "identifier", &t)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001901 *dest = this->text(t);
ethannicholasb3058bd2016-07-01 08:22:01 -07001902 return true;
1903 }
1904 return false;
1905}
1906
John Stilesa6841be2020-08-06 14:11:56 -04001907} // namespace SkSL