blob: 09d65ae9151f3599c88b6a84ef465a325b6497a2 [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)
Ethan Nicholas5fad2b882021-09-27 10:39:18 -040092, fPushback(Token::Kind::TK_NONE, /*offset=*/-1, /*length=*/-1, /*line=*/-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
Ethan Nicholas5fad2b882021-09-27 10:39:18 -0400122 ASTNode::ID result = this->createNode(/*offset=*/1, 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 }
Ethan Nicholasb13f3692021-09-10 16:49:42 -0400150 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700151 }
152 }
153 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400154 return std::move(fFile);
ethannicholasb3058bd2016-07-01 08:22:01 -0700155}
156
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700157Token Parser::nextRawToken() {
John Stiles7cbb09c22021-01-07 16:07:00 -0500158 if (fPushback.fKind != Token::Kind::TK_NONE) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700159 Token result = fPushback;
John Stiles7cbb09c22021-01-07 16:07:00 -0500160 fPushback.fKind = Token::Kind::TK_NONE;
ethannicholasb3058bd2016-07-01 08:22:01 -0700161 return result;
162 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700163 Token result = fLexer.next();
164 return result;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400165}
166
167Token Parser::nextToken() {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700168 Token token = this->nextRawToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400169 while (token.fKind == Token::Kind::TK_WHITESPACE ||
170 token.fKind == Token::Kind::TK_LINE_COMMENT ||
171 token.fKind == Token::Kind::TK_BLOCK_COMMENT) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700172 token = this->nextRawToken();
173 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400174 return token;
ethannicholasb3058bd2016-07-01 08:22:01 -0700175}
176
177void Parser::pushback(Token t) {
John Stiles7cbb09c22021-01-07 16:07:00 -0500178 SkASSERT(fPushback.fKind == Token::Kind::TK_NONE);
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400179 fPushback = std::move(t);
ethannicholasb3058bd2016-07-01 08:22:01 -0700180}
181
182Token Parser::peek() {
John Stiles7cbb09c22021-01-07 16:07:00 -0500183 if (fPushback.fKind == Token::Kind::TK_NONE) {
Brian Osman634624a2017-08-15 11:14:30 -0400184 fPushback = this->nextToken();
185 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700186 return fPushback;
187}
188
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400189bool Parser::checkNext(Token::Kind kind, Token* result) {
John Stiles7cbb09c22021-01-07 16:07:00 -0500190 if (fPushback.fKind != Token::Kind::TK_NONE && fPushback.fKind != kind) {
Brian Osman634624a2017-08-15 11:14:30 -0400191 return false;
192 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400193 Token next = this->nextToken();
194 if (next.fKind == kind) {
195 if (result) {
196 *result = next;
197 }
198 return true;
199 }
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400200 this->pushback(std::move(next));
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400201 return false;
202}
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500203
204bool Parser::expect(Token::Kind kind, const char* expected, Token* result) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700205 Token next = this->nextToken();
206 if (next.fKind == kind) {
207 if (result) {
Brian Osman634624a2017-08-15 11:14:30 -0400208 *result = std::move(next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700209 }
210 return true;
211 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700212 this->error(next, "expected " + String(expected) + ", but found '" +
213 this->text(next) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700214 return false;
215 }
216}
217
John Stiles2630ea32020-12-04 10:51:21 -0500218bool Parser::expectIdentifier(Token* result) {
219 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", result)) {
220 return false;
221 }
222 if (this->isType(this->text(*result))) {
223 this->error(*result, "expected an identifier, but found type '" +
224 this->text(*result) + "'");
225 return false;
226 }
227 return true;
228}
229
Ethan Nicholas962dec42021-06-10 13:06:39 -0400230skstd::string_view Parser::text(Token token) {
231 return skstd::string_view(fText.begin() + token.fOffset, token.fLength);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500232}
233
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700234void Parser::error(Token token, String msg) {
Brian Osmancc914522021-09-24 18:58:37 +0000235 this->error(token.fOffset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -0700236}
237
Brian Osmancc914522021-09-24 18:58:37 +0000238void Parser::error(int offset, String msg) {
239 fErrors->error(offset, msg);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700240}
241
Ethan Nicholas962dec42021-06-10 13:06:39 -0400242bool Parser::isType(skstd::string_view name) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400243 const Symbol* s = fSymbols[name];
John Stiles2630ea32020-12-04 10:51:21 -0500244 return s && s->is<Type>();
ethannicholasb3058bd2016-07-01 08:22:01 -0700245}
246
John Stiles80b02af2021-02-12 17:07:51 -0500247bool Parser::isArrayType(ASTNode::ID type) {
248 const ASTNode& node = this->getNode(type);
249 SkASSERT(node.fKind == ASTNode::Kind::kType);
250 return node.begin() != node.end();
251}
252
Ethan Nicholas11d53972016-11-28 11:23:23 -0500253/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
ethannicholas5961bc92016-10-12 06:39:56 -0700254 DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400255ASTNode::ID Parser::directive() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700256 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400257 if (!this->expect(Token::Kind::TK_DIRECTIVE, "a directive", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400258 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700259 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400260 skstd::string_view text = this->text(start);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400261 if (text == "#extension") {
ethannicholasb3058bd2016-07-01 08:22:01 -0700262 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500263 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400264 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700265 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400266 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400267 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700268 }
269 // FIXME: need to start paying attention to this token
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400270 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400271 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700272 }
Brian Osmancc914522021-09-24 18:58:37 +0000273 return this->createNode(start.fOffset, ASTNode::Kind::kExtension, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700274 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700275 this->error(start, "unsupported directive '" + this->text(start) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400276 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700277 }
278}
279
Brian Osmanc9145f32021-07-08 13:40:10 -0400280/* modifiers (interfaceBlock | structVarDeclaration | SEMICOLON |
John Stiles147cfda2021-05-21 14:11:38 -0400281 type IDENTIFIER (varDeclarationEnd | LPAREN functionDeclarationEnd))) */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400282ASTNode::ID Parser::declaration() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700283 Token lookahead = this->peek();
Ethan Nicholasda6320c2020-09-02 14:08:23 -0400284 switch (lookahead.fKind) {
Ethan Nicholasda6320c2020-09-02 14:08:23 -0400285 case Token::Kind::TK_SEMICOLON:
Brian Osmancc914522021-09-24 18:58:37 +0000286 this->error(lookahead.fOffset, "expected a declaration, but found ';'");
Ethan Nicholasda6320c2020-09-02 14:08:23 -0400287 return ASTNode::ID::Invalid();
288 default:
289 break;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500290 }
291 Modifiers modifiers = this->modifiers();
292 lookahead = this->peek();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400293 if (lookahead.fKind == Token::Kind::TK_IDENTIFIER && !this->isType(this->text(lookahead))) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700294 // we have an identifier that's not a type, could be the start of an interface block
295 return this->interfaceBlock(modifiers);
296 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400297 if (lookahead.fKind == Token::Kind::TK_STRUCT) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700298 return this->structVarDeclaration(modifiers);
299 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400300 if (lookahead.fKind == Token::Kind::TK_SEMICOLON) {
ethannicholas5961bc92016-10-12 06:39:56 -0700301 this->nextToken();
Brian Osmancc914522021-09-24 18:58:37 +0000302 return this->createNode(lookahead.fOffset, ASTNode::Kind::kModifiers, modifiers);
ethannicholas5961bc92016-10-12 06:39:56 -0700303 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400304 ASTNode::ID type = this->type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700305 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400306 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700307 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700308 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500309 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400310 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700311 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400312 if (this->checkNext(Token::Kind::TK_LPAREN)) {
John Stiles147cfda2021-05-21 14:11:38 -0400313 return this->functionDeclarationEnd(modifiers, type, name);
ethannicholasb3058bd2016-07-01 08:22:01 -0700314 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400315 return this->varDeclarationEnd(modifiers, type, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700316 }
317}
318
John Stiles147cfda2021-05-21 14:11:38 -0400319/* (RPAREN | VOID RPAREN | parameter (COMMA parameter)* RPAREN) (block | SEMICOLON) */
320ASTNode::ID Parser::functionDeclarationEnd(Modifiers modifiers,
321 ASTNode::ID type,
322 const Token& name) {
Brian Osmancc914522021-09-24 18:58:37 +0000323 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kFunction);
John Stiles147cfda2021-05-21 14:11:38 -0400324 ASTNode::FunctionData fd(modifiers, this->text(name), 0);
325 getNode(result).addChild(type);
326 Token lookahead = this->peek();
327 if (lookahead.fKind == Token::Kind::TK_RPAREN) {
328 // `()` means no parameters at all.
329 } else if (lookahead.fKind == Token::Kind::TK_IDENTIFIER && this->text(lookahead) == "void") {
330 // `(void)` also means no parameters at all.
331 this->nextToken();
332 } else {
333 for (;;) {
334 ASTNode::ID parameter = this->parameter();
335 if (!parameter) {
336 return ASTNode::ID::Invalid();
337 }
338 ++fd.fParameterCount;
339 getNode(result).addChild(parameter);
340 if (!this->checkNext(Token::Kind::TK_COMMA)) {
341 break;
342 }
343 }
344 }
345 getNode(result).setFunctionData(fd);
346 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
347 return ASTNode::ID::Invalid();
348 }
349 ASTNode::ID body;
350 if (!this->checkNext(Token::Kind::TK_SEMICOLON)) {
351 body = this->block();
352 if (!body) {
353 return ASTNode::ID::Invalid();
354 }
355 getNode(result).addChild(body);
356 }
357 return result;
358}
359
John Stiles76389b72021-01-25 13:49:05 -0500360/* (varDeclarations | expressionStatement) */
361ASTNode::ID Parser::varDeclarationsOrExpressionStatement() {
John Stiles89b484a2021-04-19 14:57:27 -0400362 Token nextToken = this->peek();
363 if (nextToken.fKind == Token::Kind::TK_CONST) {
364 // Statements that begin with `const` might be variable declarations, but can't be legal
365 // SkSL expression-statements. (SkSL constructors don't take a `const` modifier.)
366 return this->varDeclarations();
367 }
368
John Stiles02014312021-08-04 16:03:12 -0400369 if (nextToken.fKind == Token::Kind::TK_HIGHP ||
370 nextToken.fKind == Token::Kind::TK_MEDIUMP ||
371 nextToken.fKind == Token::Kind::TK_LOWP ||
372 this->isType(this->text(nextToken))) {
John Stiles76389b72021-01-25 13:49:05 -0500373 // Statements that begin with a typename are most often variable declarations, but
374 // occasionally the type is part of a constructor, and these are actually expression-
375 // statements in disguise. First, attempt the common case: parse it as a vardecl.
376 Checkpoint checkpoint(this);
John Stiles8dabeac2021-02-12 16:05:00 -0500377 VarDeclarationsPrefix prefix;
378 if (this->varDeclarationsPrefix(&prefix)) {
Ethan Nicholas55478662021-08-10 17:14:26 -0400379 checkpoint.accept();
John Stiles8dabeac2021-02-12 16:05:00 -0500380 return this->varDeclarationEnd(prefix.modifiers, prefix.type, this->text(prefix.name));
John Stiles76389b72021-01-25 13:49:05 -0500381 }
382
383 // If this statement wasn't actually a vardecl after all, rewind and try parsing it as an
384 // expression-statement instead.
385 checkpoint.rewind();
386 }
387
388 return this->expressionStatement();
389}
390
John Stiles8dabeac2021-02-12 16:05:00 -0500391// Helper function for varDeclarations(). If this function succeeds, we assume that the rest of the
392// statement is a variable-declaration statement, not an expression-statement.
393bool Parser::varDeclarationsPrefix(VarDeclarationsPrefix* prefixData) {
394 prefixData->modifiers = this->modifiers();
395 prefixData->type = this->type();
396 if (!prefixData->type) {
397 return false;
398 }
399 return this->expectIdentifier(&prefixData->name);
400}
401
ethannicholasb3058bd2016-07-01 08:22:01 -0700402/* modifiers type IDENTIFIER varDeclarationEnd */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400403ASTNode::ID Parser::varDeclarations() {
John Stiles8dabeac2021-02-12 16:05:00 -0500404 VarDeclarationsPrefix prefix;
405 if (!this->varDeclarationsPrefix(&prefix)) {
John Stiles76389b72021-01-25 13:49:05 -0500406 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700407 }
John Stiles8dabeac2021-02-12 16:05:00 -0500408 return this->varDeclarationEnd(prefix.modifiers, prefix.type, this->text(prefix.name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700409}
410
411/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400412ASTNode::ID Parser::structDeclaration() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400413 if (!this->expect(Token::Kind::TK_STRUCT, "'struct'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400414 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700415 }
416 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500417 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400418 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700419 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400420 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400421 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700422 }
423 std::vector<Type::Field> fields;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400424 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400425 ASTNode::ID decls = this->varDeclarations();
426 if (!decls) {
427 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700428 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400429 ASTNode& declsNode = getNode(decls);
John Stilesece1bf02021-03-08 11:15:55 -0500430 const Modifiers& modifiers = declsNode.begin()->getModifiers();
John Stiles13fc2602020-10-09 17:42:31 -0400431 if (modifiers.fFlags != Modifiers::kNo_Flag) {
432 String desc = modifiers.description();
433 desc.pop_back(); // remove trailing space
Brian Osmancc914522021-09-24 18:58:37 +0000434 this->error(declsNode.fOffset,
John Stiles13fc2602020-10-09 17:42:31 -0400435 "modifier '" + desc + "' is not permitted on a struct field");
436 }
437
Ethan Nicholas962dec42021-06-10 13:06:39 -0400438 const Symbol* symbol = fSymbols[(declsNode.begin() + 1)->getStringView()];
John Stiles13fc2602020-10-09 17:42:31 -0400439 SkASSERT(symbol);
440 const Type* type = &symbol->as<Type>();
John Stiles1d757782020-11-17 09:43:22 -0500441 if (type->isOpaque()) {
Brian Osmancc914522021-09-24 18:58:37 +0000442 this->error(declsNode.fOffset,
John Stiles1d757782020-11-17 09:43:22 -0500443 "opaque type '" + type->name() + "' is not permitted in a struct");
444 }
John Stiles13fc2602020-10-09 17:42:31 -0400445
Ethan Nicholasfc994162019-06-06 10:04:27 -0400446 for (auto iter = declsNode.begin() + 2; iter != declsNode.end(); ++iter) {
447 ASTNode& var = *iter;
John Stilesece1bf02021-03-08 11:15:55 -0500448 const ASTNode::VarData& vd = var.getVarData();
John Stiles6bef6a72020-12-02 14:26:04 -0500449
John Stilesd39aec92020-12-03 14:37:16 -0500450 // Read array size if one is present.
John Stiles31c87102021-08-25 12:01:21 -0400451 const Type* fieldType = type;
John Stilesd39aec92020-12-03 14:37:16 -0500452 if (vd.fIsArray) {
453 const ASTNode& size = *var.begin();
Ethan Nicholasfc994162019-06-06 10:04:27 -0400454 if (!size || size.fKind != ASTNode::Kind::kInt) {
Brian Osmancc914522021-09-24 18:58:37 +0000455 this->error(declsNode.fOffset, "array size in struct field must be a constant");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400456 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700457 }
John Stiles6bef6a72020-12-02 14:26:04 -0500458 if (size.getInt() <= 0 || size.getInt() > INT_MAX) {
Brian Osmancc914522021-09-24 18:58:37 +0000459 this->error(declsNode.fOffset, "array size is invalid");
John Stiles6bef6a72020-12-02 14:26:04 -0500460 return ASTNode::ID::Invalid();
461 }
John Stilesd39aec92020-12-03 14:37:16 -0500462 // Add the array dimensions to our type.
463 int arraySize = size.getInt();
John Stiles31c87102021-08-25 12:01:21 -0400464 fieldType = fSymbols.addArrayDimension(fieldType, arraySize);
ethannicholasb3058bd2016-07-01 08:22:01 -0700465 }
John Stiles13fc2602020-10-09 17:42:31 -0400466
John Stiles31c87102021-08-25 12:01:21 -0400467 fields.push_back(Type::Field(modifiers, vd.fName, fieldType));
John Stilesd39aec92020-12-03 14:37:16 -0500468 if (vd.fIsArray ? var.begin()->fNext : var.fFirstChild) {
Brian Osmancc914522021-09-24 18:58:37 +0000469 this->error(declsNode.fOffset, "initializers are not permitted on struct fields");
ethannicholasb3058bd2016-07-01 08:22:01 -0700470 }
471 }
472 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400473 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400474 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700475 }
Brian Osman6c3b23f2021-02-12 13:09:58 -0500476 if (fields.empty()) {
Brian Osmancc914522021-09-24 18:58:37 +0000477 this->error(name.fOffset,
Brian Osman6c3b23f2021-02-12 13:09:58 -0500478 "struct '" + this->text(name) + "' must contain at least one field");
479 return ASTNode::ID::Invalid();
480 }
Brian Osmancc914522021-09-24 18:58:37 +0000481 std::unique_ptr<Type> newType = Type::MakeStructType(name.fOffset, this->text(name), fields);
Ethan Nicholas833cd202021-09-02 14:46:41 -0400482 if (newType->isTooDeeplyNested()) {
Brian Osmancc914522021-09-24 18:58:37 +0000483 this->error(name.fOffset, "struct '" + this->text(name) + "' is too deeply nested");
John Stilesa695d622020-11-10 10:04:26 -0500484 return ASTNode::ID::Invalid();
485 }
486 fSymbols.add(std::move(newType));
Brian Osmancc914522021-09-24 18:58:37 +0000487 return this->createNode(name.fOffset, ASTNode::Kind::kType, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700488}
489
490/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400491ASTNode::ID Parser::structVarDeclaration(Modifiers modifiers) {
492 ASTNode::ID type = this->structDeclaration();
ethannicholasb3058bd2016-07-01 08:22:01 -0700493 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400494 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700495 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400496 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400497 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400498 return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700499 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400500 this->expect(Token::Kind::TK_SEMICOLON, "';'");
John Stilesdc75a972020-11-25 16:24:55 -0500501 return type;
ethannicholasb3058bd2016-07-01 08:22:01 -0700502}
503
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400504/* (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)? (COMMA IDENTIFER
505 (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
Ethan Nicholas962dec42021-06-10 13:06:39 -0400506ASTNode::ID Parser::varDeclarationEnd(Modifiers mods, ASTNode::ID type, skstd::string_view name) {
Brian Osmancc914522021-09-24 18:58:37 +0000507 int offset = this->peek().fOffset;
508 ASTNode::ID result = this->createNode(offset, ASTNode::Kind::kVarDeclarations);
509 this->addChild(result, this->createNode(offset, ASTNode::Kind::kModifiers, mods));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400510 getNode(result).addChild(type);
John Stilesd39aec92020-12-03 14:37:16 -0500511
John Stiles80b02af2021-02-12 17:07:51 -0500512 auto parseArrayDimensions = [&](ASTNode::ID currentVar, ASTNode::VarData* vd) -> bool {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400513 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stiles80b02af2021-02-12 17:07:51 -0500514 if (vd->fIsArray || this->isArrayType(type)) {
John Stilesd39aec92020-12-03 14:37:16 -0500515 this->error(this->peek(), "multi-dimensional arrays are not supported");
516 return false;
517 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400518 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
John Stiles3b209362020-11-16 17:03:10 -0500519 this->createEmptyChild(currentVar);
ethannicholasb3058bd2016-07-01 08:22:01 -0700520 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400521 ASTNode::ID size = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700522 if (!size) {
John Stilesd39aec92020-12-03 14:37:16 -0500523 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700524 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400525 getNode(currentVar).addChild(size);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400526 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
John Stilesd39aec92020-12-03 14:37:16 -0500527 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700528 }
529 }
John Stilesd39aec92020-12-03 14:37:16 -0500530 vd->fIsArray = true;
ethannicholasb3058bd2016-07-01 08:22:01 -0700531 }
John Stilesd39aec92020-12-03 14:37:16 -0500532 return true;
533 };
534
535 auto parseInitializer = [this](ASTNode::ID currentVar) -> bool {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400536 if (this->checkNext(Token::Kind::TK_EQ)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400537 ASTNode::ID value = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700538 if (!value) {
John Stilesd39aec92020-12-03 14:37:16 -0500539 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700540 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400541 getNode(currentVar).addChild(value);
ethannicholasb3058bd2016-07-01 08:22:01 -0700542 }
John Stilesd39aec92020-12-03 14:37:16 -0500543 return true;
544 };
545
Brian Osmancc914522021-09-24 18:58:37 +0000546 ASTNode::ID currentVar = this->createNode(offset, ASTNode::Kind::kVarDeclaration);
John Stilesd39aec92020-12-03 14:37:16 -0500547 ASTNode::VarData vd{name, /*isArray=*/false};
548
549 getNode(result).addChild(currentVar);
550 if (!parseArrayDimensions(currentVar, &vd)) {
551 return ASTNode::ID::Invalid();
552 }
553 getNode(currentVar).setVarData(vd);
554 if (!parseInitializer(currentVar)) {
555 return ASTNode::ID::Invalid();
556 }
557
558 while (this->checkNext(Token::Kind::TK_COMMA)) {
559 Token identifierName;
John Stiles2630ea32020-12-04 10:51:21 -0500560 if (!this->expectIdentifier(&identifierName)) {
John Stilesd39aec92020-12-03 14:37:16 -0500561 return ASTNode::ID::Invalid();
562 }
563
564 currentVar = ASTNode::ID(fFile->fNodes.size());
565 vd = ASTNode::VarData{this->text(identifierName), /*isArray=*/false};
Brian Osmancc914522021-09-24 18:58:37 +0000566 fFile->fNodes.emplace_back(&fFile->fNodes, offset, ASTNode::Kind::kVarDeclaration);
John Stilesd39aec92020-12-03 14:37:16 -0500567
568 getNode(result).addChild(currentVar);
569 if (!parseArrayDimensions(currentVar, &vd)) {
570 return ASTNode::ID::Invalid();
571 }
572 getNode(currentVar).setVarData(vd);
573 if (!parseInitializer(currentVar)) {
574 return ASTNode::ID::Invalid();
575 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700576 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400577 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400578 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700579 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400580 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700581}
582
583/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400584ASTNode::ID Parser::parameter() {
Ethan Nicholasc6f5e102017-03-31 14:53:17 -0400585 Modifiers modifiers = this->modifiersWithDefaults(0);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400586 ASTNode::ID type = this->type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700587 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400588 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700589 }
590 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500591 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400592 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700593 }
Brian Osmancc914522021-09-24 18:58:37 +0000594 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kParameter);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400595 ASTNode::ParameterData pd(modifiers, this->text(name), 0);
596 getNode(result).addChild(type);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400597 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stiles80b02af2021-02-12 17:07:51 -0500598 if (pd.fIsArray || this->isArrayType(type)) {
John Stilesd39aec92020-12-03 14:37:16 -0500599 this->error(this->peek(), "multi-dimensional arrays are not supported");
600 return ASTNode::ID::Invalid();
601 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700602 Token sizeToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400603 if (!this->expect(Token::Kind::TK_INT_LITERAL, "a positive integer", &sizeToken)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400604 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700605 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400606 skstd::string_view arraySizeFrag = this->text(sizeToken);
John Stilesf94348f2020-12-23 18:58:43 -0500607 SKSL_INT arraySize;
608 if (!SkSL::stoi(arraySizeFrag, &arraySize)) {
609 this->error(sizeToken, "array size is too large: " + arraySizeFrag);
610 return ASTNode::ID::Invalid();
611 }
Brian Osmancc914522021-09-24 18:58:37 +0000612 this->addChild(result, this->createNode(sizeToken.fOffset, ASTNode::Kind::kInt, arraySize));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400613 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400614 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700615 }
John Stilesd39aec92020-12-03 14:37:16 -0500616 pd.fIsArray = true;
ethannicholasb3058bd2016-07-01 08:22:01 -0700617 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400618 getNode(result).setParameterData(pd);
619 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700620}
621
Ethan Nicholasd608c092017-10-26 09:30:08 -0400622/** EQ INT_LITERAL */
ethannicholasb3058bd2016-07-01 08:22:01 -0700623int Parser::layoutInt() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400624 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700625 return -1;
626 }
627 Token resultToken;
John Stilesf94348f2020-12-23 18:58:43 -0500628 if (!this->expect(Token::Kind::TK_INT_LITERAL, "a non-negative integer", &resultToken)) {
629 return -1;
ethannicholasb3058bd2016-07-01 08:22:01 -0700630 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400631 skstd::string_view resultFrag = this->text(resultToken);
John Stilesf94348f2020-12-23 18:58:43 -0500632 SKSL_INT resultValue;
633 if (!SkSL::stoi(resultFrag, &resultValue)) {
634 this->error(resultToken, "value in layout is too large: " + resultFrag);
635 return -1;
636 }
637 return resultValue;
ethannicholasb3058bd2016-07-01 08:22:01 -0700638}
639
Ethan Nicholasd608c092017-10-26 09:30:08 -0400640/** EQ IDENTIFIER */
Ethan Nicholas962dec42021-06-10 13:06:39 -0400641skstd::string_view Parser::layoutIdentifier() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400642 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
Ethan Nicholas962dec42021-06-10 13:06:39 -0400643 return skstd::string_view();
Ethan Nicholasd608c092017-10-26 09:30:08 -0400644 }
645 Token resultToken;
John Stiles2630ea32020-12-04 10:51:21 -0500646 if (!this->expectIdentifier(&resultToken)) {
Ethan Nicholas962dec42021-06-10 13:06:39 -0400647 return skstd::string_view();
Ethan Nicholasd608c092017-10-26 09:30:08 -0400648 }
649 return this->text(resultToken);
650}
651
ethannicholas8ac838d2016-11-22 08:39:36 -0800652/* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500653Layout Parser::layout() {
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500654 int flags = 0;
ethannicholasb3058bd2016-07-01 08:22:01 -0700655 int location = -1;
Ethan Nicholas19671772016-11-28 16:30:17 -0500656 int offset = -1;
ethannicholasb3058bd2016-07-01 08:22:01 -0700657 int binding = -1;
658 int index = -1;
659 int set = -1;
660 int builtin = -1;
Greg Daniel64773e62016-11-22 09:44:03 -0500661 int inputAttachmentIndex = -1;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400662 if (this->checkNext(Token::Kind::TK_LAYOUT)) {
663 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Brian Osman99ddd2a2021-08-27 11:21:12 -0400664 return Layout(
665 flags, location, offset, binding, index, set, builtin, inputAttachmentIndex);
ethannicholasb3058bd2016-07-01 08:22:01 -0700666 }
667 for (;;) {
668 Token t = this->nextToken();
Ethan Nicholasd2e09602021-06-10 11:21:59 -0400669 String text(this->text(t));
Brian Osmana77ed8b2021-02-23 12:54:22 -0500670 auto setFlag = [&](Layout::Flag f) {
671 if (flags & f) {
672 this->error(t, "layout qualifier '" + text + "' appears more than once");
673 }
674 flags |= f;
675 };
Brian Osmana77ed8b2021-02-23 12:54:22 -0500676
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400677 auto found = layoutTokens->find(text);
678 if (found != layoutTokens->end()) {
679 switch (found->second) {
Brian Osmana77ed8b2021-02-23 12:54:22 -0500680 case LayoutToken::ORIGIN_UPPER_LEFT:
681 setFlag(Layout::kOriginUpperLeft_Flag);
682 break;
Brian Osmana77ed8b2021-02-23 12:54:22 -0500683 case LayoutToken::PUSH_CONSTANT:
684 setFlag(Layout::kPushConstant_Flag);
685 break;
686 case LayoutToken::BLEND_SUPPORT_ALL_EQUATIONS:
687 setFlag(Layout::kBlendSupportAllEquations_Flag);
688 break;
Brian Osmana77ed8b2021-02-23 12:54:22 -0500689 case LayoutToken::SRGB_UNPREMUL:
690 setFlag(Layout::kSRGBUnpremul_Flag);
691 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700692 case LayoutToken::LOCATION:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500693 setFlag(Layout::kLocation_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500694 location = this->layoutInt();
695 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700696 case LayoutToken::OFFSET:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500697 setFlag(Layout::kOffset_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500698 offset = this->layoutInt();
699 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700700 case LayoutToken::BINDING:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500701 setFlag(Layout::kBinding_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500702 binding = this->layoutInt();
703 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700704 case LayoutToken::INDEX:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500705 setFlag(Layout::kIndex_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500706 index = this->layoutInt();
707 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700708 case LayoutToken::SET:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500709 setFlag(Layout::kSet_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500710 set = this->layoutInt();
711 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700712 case LayoutToken::BUILTIN:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500713 setFlag(Layout::kBuiltin_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500714 builtin = this->layoutInt();
715 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700716 case LayoutToken::INPUT_ATTACHMENT_INDEX:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500717 setFlag(Layout::kInputAttachmentIndex_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500718 inputAttachmentIndex = this->layoutInt();
719 break;
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400720 default:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500721 this->error(t, "'" + text + "' is not a valid layout qualifier");
Ethan Nicholasd608c092017-10-26 09:30:08 -0400722 break;
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500723 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700724 } else {
Brian Osmana77ed8b2021-02-23 12:54:22 -0500725 this->error(t, "'" + text + "' is not a valid layout qualifier");
ethannicholasb3058bd2016-07-01 08:22:01 -0700726 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400727 if (this->checkNext(Token::Kind::TK_RPAREN)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700728 break;
729 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400730 if (!this->expect(Token::Kind::TK_COMMA, "','")) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700731 break;
732 }
733 }
734 }
Brian Osman99ddd2a2021-08-27 11:21:12 -0400735 return Layout(flags, location, offset, binding, index, set, builtin, inputAttachmentIndex);
ethannicholasb3058bd2016-07-01 08:22:01 -0700736}
737
Brian Osmane49703f2021-04-19 11:15:24 -0400738/* layout? (UNIFORM | CONST | IN | OUT | INOUT | FLAT | NOPERSPECTIVE | INLINE)* */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500739Modifiers Parser::modifiers() {
740 Layout layout = this->layout();
ethannicholasb3058bd2016-07-01 08:22:01 -0700741 int flags = 0;
742 for (;;) {
743 // TODO: handle duplicate / incompatible flags
John Stiles7d5b90a2021-01-21 14:26:51 -0500744 int tokenFlag = parse_modifier_token(peek().fKind);
745 if (!tokenFlag) {
746 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700747 }
John Stiles7d5b90a2021-01-21 14:26:51 -0500748 flags |= tokenFlag;
749 this->nextToken();
ethannicholasb3058bd2016-07-01 08:22:01 -0700750 }
John Stiles7d5b90a2021-01-21 14:26:51 -0500751 return Modifiers(layout, flags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700752}
753
Ethan Nicholas11d53972016-11-28 11:23:23 -0500754Modifiers Parser::modifiersWithDefaults(int defaultFlags) {
755 Modifiers result = this->modifiers();
ethannicholasb3058bd2016-07-01 08:22:01 -0700756 if (!result.fFlags) {
Ethan Nicholas11d53972016-11-28 11:23:23 -0500757 return Modifiers(result.fLayout, defaultFlags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700758 }
759 return result;
760}
761
762/* ifStatement | forStatement | doStatement | whileStatement | block | expression */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400763ASTNode::ID Parser::statement() {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -0400764 Token start = this->nextToken();
765 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -0400766 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -0400767 return ASTNode::ID::Invalid();
768 }
769 this->pushback(start);
ethannicholasb3058bd2016-07-01 08:22:01 -0700770 switch (start.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400771 case Token::Kind::TK_IF: // fall through
772 case Token::Kind::TK_STATIC_IF:
ethannicholasb3058bd2016-07-01 08:22:01 -0700773 return this->ifStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400774 case Token::Kind::TK_FOR:
ethannicholasb3058bd2016-07-01 08:22:01 -0700775 return this->forStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400776 case Token::Kind::TK_DO:
ethannicholasb3058bd2016-07-01 08:22:01 -0700777 return this->doStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400778 case Token::Kind::TK_WHILE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700779 return this->whileStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400780 case Token::Kind::TK_SWITCH: // fall through
781 case Token::Kind::TK_STATIC_SWITCH:
Ethan Nicholasaf197692017-02-27 13:26:45 -0500782 return this->switchStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400783 case Token::Kind::TK_RETURN:
ethannicholasb3058bd2016-07-01 08:22:01 -0700784 return this->returnStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400785 case Token::Kind::TK_BREAK:
ethannicholasb3058bd2016-07-01 08:22:01 -0700786 return this->breakStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400787 case Token::Kind::TK_CONTINUE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700788 return this->continueStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400789 case Token::Kind::TK_DISCARD:
ethannicholasb3058bd2016-07-01 08:22:01 -0700790 return this->discardStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400791 case Token::Kind::TK_LBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700792 return this->block();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400793 case Token::Kind::TK_SEMICOLON:
Ethan Nicholas11d53972016-11-28 11:23:23 -0500794 this->nextToken();
Brian Osmancc914522021-09-24 18:58:37 +0000795 return this->createNode(start.fOffset, ASTNode::Kind::kBlock);
John Stiles02014312021-08-04 16:03:12 -0400796 case Token::Kind::TK_HIGHP:
797 case Token::Kind::TK_MEDIUMP:
798 case Token::Kind::TK_LOWP:
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400799 case Token::Kind::TK_CONST:
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400800 case Token::Kind::TK_IDENTIFIER:
John Stiles76389b72021-01-25 13:49:05 -0500801 return this->varDeclarationsOrExpressionStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700802 default:
803 return this->expressionStatement();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500804 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700805}
806
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500807/* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* QUESTION? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400808ASTNode::ID Parser::type() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700809 Token type;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400810 if (!this->expect(Token::Kind::TK_IDENTIFIER, "a type", &type)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400811 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700812 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700813 if (!this->isType(this->text(type))) {
814 this->error(type, ("no type named '" + this->text(type) + "'").c_str());
Ethan Nicholasfc994162019-06-06 10:04:27 -0400815 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700816 }
Brian Osmancc914522021-09-24 18:58:37 +0000817 ASTNode::ID result = this->createNode(type.fOffset, ASTNode::Kind::kType, this->text(type));
John Stilesd39aec92020-12-03 14:37:16 -0500818 bool isArray = false;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400819 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stilesd39aec92020-12-03 14:37:16 -0500820 if (isArray) {
821 this->error(this->peek(), "multi-dimensional arrays are not supported");
822 return ASTNode::ID::Invalid();
823 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400824 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400825 SKSL_INT i;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500826 if (this->intLiteral(&i)) {
Brian Osmancc914522021-09-24 18:58:37 +0000827 this->addChild(result, this->createNode(this->peek().fOffset,
John Stiles08070f62020-11-17 10:45:49 -0500828 ASTNode::Kind::kInt, i));
Ethan Nicholas50afc172017-02-16 14:49:57 -0500829 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400830 return ASTNode::ID::Invalid();
Ethan Nicholas50afc172017-02-16 14:49:57 -0500831 }
832 } else {
John Stiles3b209362020-11-16 17:03:10 -0500833 this->createEmptyChild(result);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500834 }
John Stilesd39aec92020-12-03 14:37:16 -0500835 isArray = true;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400836 this->expect(Token::Kind::TK_RBRACKET, "']'");
Ethan Nicholas50afc172017-02-16 14:49:57 -0500837 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400838 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700839}
840
John Stiles57a996b2020-04-19 19:05:12 -0700841/* IDENTIFIER LBRACE
842 varDeclaration+
843 RBRACE (IDENTIFIER (LBRACKET expression? RBRACKET)*)? SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400844ASTNode::ID Parser::interfaceBlock(Modifiers mods) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700845 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500846 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400847 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700848 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400849 if (peek().fKind != Token::Kind::TK_LBRACE) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700850 // we only get into interfaceBlock if we found a top-level identifier which was not a type.
Ethan Nicholas11d53972016-11-28 11:23:23 -0500851 // 99% of the time, the user was not actually intending to create an interface block, so
ethannicholasb3058bd2016-07-01 08:22:01 -0700852 // it's better to report it as an unknown type
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700853 this->error(name, "no type named '" + this->text(name) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400854 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700855 }
Brian Osmancc914522021-09-24 18:58:37 +0000856 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kInterfaceBlock);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400857 ASTNode::InterfaceBlockData id(mods, this->text(name), 0, "", 0);
ethannicholasb3058bd2016-07-01 08:22:01 -0700858 this->nextToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400859 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400860 ASTNode::ID decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700861 if (!decl) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400862 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700863 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400864 getNode(result).addChild(decl);
865 ++id.fDeclarationCount;
ethannicholasb3058bd2016-07-01 08:22:01 -0700866 }
John Stiles57a996b2020-04-19 19:05:12 -0700867 if (id.fDeclarationCount == 0) {
868 this->error(name, "interface block '" + this->text(name) +
869 "' must contain at least one member");
870 return ASTNode::ID::Invalid();
871 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700872 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -0400873 std::vector<ASTNode> sizes;
Ethan Nicholas962dec42021-06-10 13:06:39 -0400874 skstd::string_view instanceName;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700875 Token instanceNameToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400876 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &instanceNameToken)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400877 id.fInstanceName = this->text(instanceNameToken);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400878 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stilesd39aec92020-12-03 14:37:16 -0500879 if (id.fIsArray) {
880 this->error(this->peek(), "multi-dimensional arrays are not supported");
881 return false;
882 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400883 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400884 ASTNode::ID size = this->expression();
Ethan Nicholas50afc172017-02-16 14:49:57 -0500885 if (!size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400886 return ASTNode::ID::Invalid();
Ethan Nicholas50afc172017-02-16 14:49:57 -0500887 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400888 getNode(result).addChild(size);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500889 } else {
John Stiles3b209362020-11-16 17:03:10 -0500890 this->createEmptyChild(result);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500891 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400892 this->expect(Token::Kind::TK_RBRACKET, "']'");
John Stilesd39aec92020-12-03 14:37:16 -0500893 id.fIsArray = true;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500894 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700895 instanceName = this->text(instanceNameToken);
ethannicholasb3058bd2016-07-01 08:22:01 -0700896 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400897 getNode(result).setInterfaceBlockData(id);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400898 this->expect(Token::Kind::TK_SEMICOLON, "';'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400899 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700900}
901
902/* IF LPAREN expression RPAREN statement (ELSE statement)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400903ASTNode::ID Parser::ifStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700904 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400905 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_IF, &start);
906 if (!isStatic && !this->expect(Token::Kind::TK_IF, "'if'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400907 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700908 }
Brian Osmancc914522021-09-24 18:58:37 +0000909 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kIf, isStatic);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400910 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400911 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700912 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400913 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700914 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400915 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700916 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400917 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400918 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400919 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700920 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400921 ASTNode::ID ifTrue = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700922 if (!ifTrue) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400923 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700924 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400925 getNode(result).addChild(ifTrue);
926 ASTNode::ID ifFalse;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400927 if (this->checkNext(Token::Kind::TK_ELSE)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700928 ifFalse = this->statement();
929 if (!ifFalse) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400930 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700931 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400932 getNode(result).addChild(ifFalse);
ethannicholasb3058bd2016-07-01 08:22:01 -0700933 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400934 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700935}
936
937/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400938ASTNode::ID Parser::doStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700939 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400940 if (!this->expect(Token::Kind::TK_DO, "'do'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400941 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700942 }
Brian Osmancc914522021-09-24 18:58:37 +0000943 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kDo);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400944 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700945 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400946 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700947 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400948 getNode(result).addChild(statement);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400949 if (!this->expect(Token::Kind::TK_WHILE, "'while'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400950 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700951 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400952 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400953 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700954 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400955 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700956 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400957 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700958 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400959 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400960 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400961 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700962 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400963 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400964 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700965 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400966 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700967}
968
969/* WHILE LPAREN expression RPAREN STATEMENT */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400970ASTNode::ID Parser::whileStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700971 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400972 if (!this->expect(Token::Kind::TK_WHILE, "'while'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400973 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700974 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400975 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400976 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700977 }
Brian Osmancc914522021-09-24 18:58:37 +0000978 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kWhile);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400979 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700980 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400981 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700982 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400983 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400984 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400985 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700986 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400987 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700988 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400989 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700990 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400991 getNode(result).addChild(statement);
992 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700993}
994
Ethan Nicholasaf197692017-02-27 13:26:45 -0500995/* CASE expression COLON statement* */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400996ASTNode::ID Parser::switchCase() {
Ethan Nicholasaf197692017-02-27 13:26:45 -0500997 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400998 if (!this->expect(Token::Kind::TK_CASE, "'case'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400999 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001000 }
Brian Osmancc914522021-09-24 18:58:37 +00001001 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kSwitchCase);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001002 ASTNode::ID value = this->expression();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001003 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001004 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001005 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001006 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001007 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001008 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001009 getNode(result).addChild(value);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001010 while (this->peek().fKind != Token::Kind::TK_RBRACE &&
1011 this->peek().fKind != Token::Kind::TK_CASE &&
1012 this->peek().fKind != Token::Kind::TK_DEFAULT) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001013 ASTNode::ID s = this->statement();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001014 if (!s) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001015 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001016 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001017 getNode(result).addChild(s);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001018 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001019 return result;
Ethan Nicholasaf197692017-02-27 13:26:45 -05001020}
1021
1022/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001023ASTNode::ID Parser::switchStatement() {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001024 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001025 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_SWITCH, &start);
1026 if (!isStatic && !this->expect(Token::Kind::TK_SWITCH, "'switch'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001027 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001028 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001029 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001030 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001031 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001032 ASTNode::ID value = this->expression();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001033 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001034 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001035 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001036 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001037 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001038 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001039 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001040 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001041 }
Brian Osmancc914522021-09-24 18:58:37 +00001042 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kSwitch, isStatic);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001043 getNode(result).addChild(value);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001044 while (this->peek().fKind == Token::Kind::TK_CASE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001045 ASTNode::ID c = this->switchCase();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001046 if (!c) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001047 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001048 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001049 getNode(result).addChild(c);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001050 }
1051 // Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
1052 // parts of the compiler may rely upon this assumption.
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001053 if (this->peek().fKind == Token::Kind::TK_DEFAULT) {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001054 Token defaultStart;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001055 SkAssertResult(this->expect(Token::Kind::TK_DEFAULT, "'default'", &defaultStart));
1056 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001057 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001058 }
John Stiles3b209362020-11-16 17:03:10 -05001059 ASTNode::ID defaultCase = this->addChild(
Brian Osmancc914522021-09-24 18:58:37 +00001060 result, this->createNode(defaultStart.fOffset, ASTNode::Kind::kSwitchCase));
John Stiles3b209362020-11-16 17:03:10 -05001061 this->createEmptyChild(defaultCase); // empty test to signify default case
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001062 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001063 ASTNode::ID s = this->statement();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001064 if (!s) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001065 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001066 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001067 getNode(defaultCase).addChild(s);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001068 }
Ethan Nicholasaf197692017-02-27 13:26:45 -05001069 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001070 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001071 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001072 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001073 return result;
Ethan Nicholasaf197692017-02-27 13:26:45 -05001074}
1075
Ethan Nicholas11d53972016-11-28 11:23:23 -05001076/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
ethannicholasb3058bd2016-07-01 08:22:01 -07001077 STATEMENT */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001078ASTNode::ID Parser::forStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001079 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001080 if (!this->expect(Token::Kind::TK_FOR, "'for'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001081 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001082 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001083 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001084 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001085 }
Brian Osmancc914522021-09-24 18:58:37 +00001086 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kFor);
ethannicholasb3058bd2016-07-01 08:22:01 -07001087 Token nextToken = this->peek();
John Stiles89b484a2021-04-19 14:57:27 -04001088 if (nextToken.fKind == Token::Kind::TK_SEMICOLON) {
1089 // An empty init-statement.
1090 this->nextToken();
1091 this->createEmptyChild(result);
1092 } else {
1093 // The init-statement must be an expression or variable declaration.
1094 ASTNode::ID initializer = this->varDeclarationsOrExpressionStatement();
1095 if (!initializer) {
1096 return ASTNode::ID::Invalid();
ethannicholasa54401d2016-10-14 08:37:32 -07001097 }
John Stiles89b484a2021-04-19 14:57:27 -04001098 getNode(result).addChild(initializer);
ethannicholasb3058bd2016-07-01 08:22:01 -07001099 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001100 ASTNode::ID test;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001101 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001102 test = this->expression();
1103 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001104 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001105 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001106 getNode(result).addChild(test);
1107 } else {
John Stiles3b209362020-11-16 17:03:10 -05001108 this->createEmptyChild(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001109 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001110 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001111 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001112 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001113 ASTNode::ID next;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001114 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001115 next = this->expression();
1116 if (!next) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001117 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001118 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001119 getNode(result).addChild(next);
1120 } else {
John Stiles3b209362020-11-16 17:03:10 -05001121 this->createEmptyChild(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001122 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001123 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001124 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001125 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001126 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001127 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001128 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001129 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001130 getNode(result).addChild(statement);
1131 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001132}
1133
1134/* RETURN expression? SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001135ASTNode::ID Parser::returnStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001136 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001137 if (!this->expect(Token::Kind::TK_RETURN, "'return'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001138 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001139 }
Brian Osmancc914522021-09-24 18:58:37 +00001140 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kReturn);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001141 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001142 ASTNode::ID expression = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001143 if (!expression) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001144 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001145 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001146 getNode(result).addChild(expression);
ethannicholasb3058bd2016-07-01 08:22:01 -07001147 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001148 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001149 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001150 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001151 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001152}
1153
1154/* BREAK SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001155ASTNode::ID Parser::breakStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001156 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001157 if (!this->expect(Token::Kind::TK_BREAK, "'break'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001158 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001159 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001160 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001161 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001162 }
Brian Osmancc914522021-09-24 18:58:37 +00001163 return this->createNode(start.fOffset, ASTNode::Kind::kBreak);
ethannicholasb3058bd2016-07-01 08:22:01 -07001164}
1165
1166/* CONTINUE SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001167ASTNode::ID Parser::continueStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001168 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001169 if (!this->expect(Token::Kind::TK_CONTINUE, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001170 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001171 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001172 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001173 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001174 }
Brian Osmancc914522021-09-24 18:58:37 +00001175 return this->createNode(start.fOffset, ASTNode::Kind::kContinue);
ethannicholasb3058bd2016-07-01 08:22:01 -07001176}
1177
1178/* DISCARD SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001179ASTNode::ID Parser::discardStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001180 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001181 if (!this->expect(Token::Kind::TK_DISCARD, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001182 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001183 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001184 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001185 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001186 }
Brian Osmancc914522021-09-24 18:58:37 +00001187 return this->createNode(start.fOffset, ASTNode::Kind::kDiscard);
ethannicholasb3058bd2016-07-01 08:22:01 -07001188}
1189
1190/* LBRACE statement* RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001191ASTNode::ID Parser::block() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001192 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001193 if (!this->expect(Token::Kind::TK_LBRACE, "'{'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001194 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001195 }
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001196 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001197 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001198 return ASTNode::ID::Invalid();
1199 }
Brian Osmancc914522021-09-24 18:58:37 +00001200 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kBlock);
ethannicholasb3058bd2016-07-01 08:22:01 -07001201 for (;;) {
1202 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001203 case Token::Kind::TK_RBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -07001204 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001205 return result;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001206 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001207 this->error(this->peek(), "expected '}', but found end of file");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001208 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001209 default: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001210 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001211 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001212 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001213 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001214 getNode(result).addChild(statement);
ethannicholasb3058bd2016-07-01 08:22:01 -07001215 }
1216 }
1217 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001218 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001219}
1220
1221/* expression SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001222ASTNode::ID Parser::expressionStatement() {
1223 ASTNode::ID expr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001224 if (expr) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001225 if (this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001226 return expr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001227 }
1228 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001229 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001230}
1231
1232/* assignmentExpression (COMMA assignmentExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001233ASTNode::ID Parser::expression() {
1234 ASTNode::ID result = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001235 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001236 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001237 }
1238 Token t;
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001239 AutoDepth depth(this);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001240 while (this->checkNext(Token::Kind::TK_COMMA, &t)) {
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001241 if (!depth.increase()) {
1242 return ASTNode::ID::Invalid();
1243 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001244 ASTNode::ID right = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001245 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001246 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001247 }
Brian Osmancc914522021-09-24 18:58:37 +00001248 ASTNode::ID newResult = this->createNode(t.fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001249 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001250 getNode(newResult).addChild(result);
1251 getNode(newResult).addChild(right);
1252 result = newResult;
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001253 }
1254 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001255}
1256
1257/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1258 BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1259 assignmentExpression)*
1260 */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001261ASTNode::ID Parser::assignmentExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001262 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001263 ASTNode::ID result = this->ternaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001264 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001265 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001266 }
1267 for (;;) {
1268 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001269 case Token::Kind::TK_EQ: // fall through
1270 case Token::Kind::TK_STAREQ: // fall through
1271 case Token::Kind::TK_SLASHEQ: // fall through
1272 case Token::Kind::TK_PERCENTEQ: // fall through
1273 case Token::Kind::TK_PLUSEQ: // fall through
1274 case Token::Kind::TK_MINUSEQ: // fall through
1275 case Token::Kind::TK_SHLEQ: // fall through
1276 case Token::Kind::TK_SHREQ: // fall through
1277 case Token::Kind::TK_BITWISEANDEQ: // fall through
1278 case Token::Kind::TK_BITWISEXOREQ: // fall through
John Stiles8b3b1592020-11-23 11:06:44 -05001279 case Token::Kind::TK_BITWISEOREQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001280 if (!depth.increase()) {
1281 return ASTNode::ID::Invalid();
1282 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001283 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001284 ASTNode::ID right = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001285 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001286 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001287 }
Brian Osmancc914522021-09-24 18:58:37 +00001288 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001289 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001290 getNode(newResult).addChild(result);
1291 getNode(newResult).addChild(right);
1292 result = newResult;
1293 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001294 }
1295 default:
1296 return result;
1297 }
1298 }
1299}
1300
1301/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001302ASTNode::ID Parser::ternaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001303 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001304 ASTNode::ID base = this->logicalOrExpression();
1305 if (!base) {
1306 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001307 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001308 if (this->checkNext(Token::Kind::TK_QUESTION)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001309 if (!depth.increase()) {
1310 return ASTNode::ID::Invalid();
1311 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001312 ASTNode::ID trueExpr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001313 if (!trueExpr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001314 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001315 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001316 if (this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001317 ASTNode::ID falseExpr = this->assignmentExpression();
1318 if (!falseExpr) {
1319 return ASTNode::ID::Invalid();
1320 }
Brian Osmancc914522021-09-24 18:58:37 +00001321 ASTNode::ID ternary = this->createNode(getNode(base).fOffset, ASTNode::Kind::kTernary);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001322 getNode(ternary).addChild(base);
1323 getNode(ternary).addChild(trueExpr);
1324 getNode(ternary).addChild(falseExpr);
1325 return ternary;
ethannicholasb3058bd2016-07-01 08:22:01 -07001326 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001327 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001328 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001329 return base;
ethannicholasb3058bd2016-07-01 08:22:01 -07001330}
1331
1332/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001333ASTNode::ID Parser::logicalOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001334 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001335 ASTNode::ID result = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001336 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001337 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001338 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001339 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001340 while (this->checkNext(Token::Kind::TK_LOGICALOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001341 if (!depth.increase()) {
1342 return ASTNode::ID::Invalid();
1343 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001344 ASTNode::ID right = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001345 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001346 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001347 }
Brian Osmancc914522021-09-24 18:58:37 +00001348 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001349 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001350 getNode(newResult).addChild(result);
1351 getNode(newResult).addChild(right);
1352 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001353 }
1354 return result;
1355}
1356
1357/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001358ASTNode::ID Parser::logicalXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001359 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001360 ASTNode::ID result = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001361 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001362 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001363 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001364 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001365 while (this->checkNext(Token::Kind::TK_LOGICALXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001366 if (!depth.increase()) {
1367 return ASTNode::ID::Invalid();
1368 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001369 ASTNode::ID right = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001370 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001371 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001372 }
Brian Osmancc914522021-09-24 18:58:37 +00001373 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001374 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001375 getNode(newResult).addChild(result);
1376 getNode(newResult).addChild(right);
1377 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001378 }
1379 return result;
1380}
1381
1382/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001383ASTNode::ID Parser::logicalAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001384 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001385 ASTNode::ID result = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001386 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001387 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001388 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001389 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001390 while (this->checkNext(Token::Kind::TK_LOGICALAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001391 if (!depth.increase()) {
1392 return ASTNode::ID::Invalid();
1393 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001394 ASTNode::ID right = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001395 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001396 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001397 }
Brian Osmancc914522021-09-24 18:58:37 +00001398 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001399 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001400 getNode(newResult).addChild(result);
1401 getNode(newResult).addChild(right);
1402 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001403 }
1404 return result;
1405}
1406
1407/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001408ASTNode::ID Parser::bitwiseOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001409 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001410 ASTNode::ID result = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001411 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001412 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001413 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001414 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001415 while (this->checkNext(Token::Kind::TK_BITWISEOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001416 if (!depth.increase()) {
1417 return ASTNode::ID::Invalid();
1418 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001419 ASTNode::ID right = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001420 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001421 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001422 }
Brian Osmancc914522021-09-24 18:58:37 +00001423 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001424 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001425 getNode(newResult).addChild(result);
1426 getNode(newResult).addChild(right);
1427 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001428 }
1429 return result;
1430}
1431
1432/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001433ASTNode::ID Parser::bitwiseXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001434 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001435 ASTNode::ID result = this->bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001436 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001437 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001438 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001439 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001440 while (this->checkNext(Token::Kind::TK_BITWISEXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001441 if (!depth.increase()) {
1442 return ASTNode::ID::Invalid();
1443 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001444 ASTNode::ID right = this->bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001445 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001446 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001447 }
Brian Osmancc914522021-09-24 18:58:37 +00001448 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001449 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001450 getNode(newResult).addChild(result);
1451 getNode(newResult).addChild(right);
1452 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001453 }
1454 return result;
1455}
1456
1457/* equalityExpression (BITWISEAND equalityExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001458ASTNode::ID Parser::bitwiseAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001459 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001460 ASTNode::ID result = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001461 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001462 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001463 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001464 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001465 while (this->checkNext(Token::Kind::TK_BITWISEAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001466 if (!depth.increase()) {
1467 return ASTNode::ID::Invalid();
1468 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001469 ASTNode::ID right = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001470 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001471 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001472 }
Brian Osmancc914522021-09-24 18:58:37 +00001473 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001474 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001475 getNode(newResult).addChild(result);
1476 getNode(newResult).addChild(right);
1477 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001478 }
1479 return result;
1480}
1481
1482/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001483ASTNode::ID Parser::equalityExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001484 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001485 ASTNode::ID result = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001486 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001487 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001488 }
1489 for (;;) {
1490 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001491 case Token::Kind::TK_EQEQ: // fall through
1492 case Token::Kind::TK_NEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001493 if (!depth.increase()) {
1494 return ASTNode::ID::Invalid();
1495 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001496 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001497 ASTNode::ID right = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001498 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001499 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001500 }
Brian Osmancc914522021-09-24 18:58:37 +00001501 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001502 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001503 getNode(newResult).addChild(result);
1504 getNode(newResult).addChild(right);
1505 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001506 break;
1507 }
1508 default:
1509 return result;
1510 }
1511 }
1512}
1513
1514/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001515ASTNode::ID Parser::relationalExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001516 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001517 ASTNode::ID result = this->shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001518 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001519 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001520 }
1521 for (;;) {
1522 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001523 case Token::Kind::TK_LT: // fall through
1524 case Token::Kind::TK_GT: // fall through
1525 case Token::Kind::TK_LTEQ: // fall through
1526 case Token::Kind::TK_GTEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001527 if (!depth.increase()) {
1528 return ASTNode::ID::Invalid();
1529 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001530 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001531 ASTNode::ID right = this->shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001532 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001533 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001534 }
Brian Osmancc914522021-09-24 18:58:37 +00001535 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001536 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001537 getNode(newResult).addChild(result);
1538 getNode(newResult).addChild(right);
1539 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001540 break;
1541 }
1542 default:
1543 return result;
1544 }
1545 }
1546}
1547
1548/* additiveExpression ((SHL | SHR) additiveExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001549ASTNode::ID Parser::shiftExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001550 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001551 ASTNode::ID result = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001552 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001553 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001554 }
1555 for (;;) {
1556 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001557 case Token::Kind::TK_SHL: // fall through
1558 case Token::Kind::TK_SHR: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001559 if (!depth.increase()) {
1560 return ASTNode::ID::Invalid();
1561 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001562 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001563 ASTNode::ID right = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001564 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001565 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001566 }
Brian Osmancc914522021-09-24 18:58:37 +00001567 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001568 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001569 getNode(newResult).addChild(result);
1570 getNode(newResult).addChild(right);
1571 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001572 break;
1573 }
1574 default:
1575 return result;
1576 }
1577 }
1578}
1579
1580/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001581ASTNode::ID Parser::additiveExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001582 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001583 ASTNode::ID result = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001584 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001585 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001586 }
1587 for (;;) {
1588 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001589 case Token::Kind::TK_PLUS: // fall through
1590 case Token::Kind::TK_MINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001591 if (!depth.increase()) {
1592 return ASTNode::ID::Invalid();
1593 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001594 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001595 ASTNode::ID right = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001596 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001597 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001598 }
Brian Osmancc914522021-09-24 18:58:37 +00001599 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001600 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001601 getNode(newResult).addChild(result);
1602 getNode(newResult).addChild(right);
1603 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001604 break;
1605 }
1606 default:
1607 return result;
1608 }
1609 }
1610}
1611
1612/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001613ASTNode::ID Parser::multiplicativeExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001614 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001615 ASTNode::ID result = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001616 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001617 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001618 }
1619 for (;;) {
1620 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001621 case Token::Kind::TK_STAR: // fall through
1622 case Token::Kind::TK_SLASH: // fall through
1623 case Token::Kind::TK_PERCENT: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001624 if (!depth.increase()) {
1625 return ASTNode::ID::Invalid();
1626 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001627 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001628 ASTNode::ID right = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001629 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001630 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001631 }
Brian Osmancc914522021-09-24 18:58:37 +00001632 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001633 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001634 getNode(newResult).addChild(result);
1635 getNode(newResult).addChild(right);
1636 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001637 break;
1638 }
1639 default:
1640 return result;
1641 }
1642 }
1643}
1644
1645/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001646ASTNode::ID Parser::unaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001647 AutoDepth depth(this);
ethannicholasb3058bd2016-07-01 08:22:01 -07001648 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001649 case Token::Kind::TK_PLUS: // fall through
1650 case Token::Kind::TK_MINUS: // fall through
1651 case Token::Kind::TK_LOGICALNOT: // fall through
1652 case Token::Kind::TK_BITWISENOT: // fall through
1653 case Token::Kind::TK_PLUSPLUS: // fall through
1654 case Token::Kind::TK_MINUSMINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001655 if (!depth.increase()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001656 return ASTNode::ID::Invalid();
Ethan Nicholas6dcc3252019-02-20 15:18:36 -05001657 }
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001658 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001659 ASTNode::ID expr = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001660 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001661 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001662 }
Brian Osmancc914522021-09-24 18:58:37 +00001663 ASTNode::ID result = this->createNode(t.fOffset, ASTNode::Kind::kPrefix,
John Stiles45990502021-02-16 10:55:27 -05001664 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001665 getNode(result).addChild(expr);
1666 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001667 }
1668 default:
1669 return this->postfixExpression();
1670 }
1671}
1672
1673/* term suffix* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001674ASTNode::ID Parser::postfixExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001675 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001676 ASTNode::ID result = this->term();
ethannicholasb3058bd2016-07-01 08:22:01 -07001677 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001678 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001679 }
1680 for (;;) {
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001681 Token t = this->peek();
1682 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001683 case Token::Kind::TK_FLOAT_LITERAL:
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001684 if (this->text(t)[0] != '.') {
1685 return result;
1686 }
John Stiles30212b72020-06-11 17:55:07 -04001687 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001688 case Token::Kind::TK_LBRACKET:
1689 case Token::Kind::TK_DOT:
1690 case Token::Kind::TK_LPAREN:
1691 case Token::Kind::TK_PLUSPLUS:
1692 case Token::Kind::TK_MINUSMINUS:
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001693 if (!depth.increase()) {
1694 return ASTNode::ID::Invalid();
1695 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001696 result = this->suffix(result);
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001697 if (!result) {
1698 return ASTNode::ID::Invalid();
1699 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001700 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001701 default:
1702 return result;
1703 }
1704 }
1705}
1706
Ethan Nicholas11d53972016-11-28 11:23:23 -05001707/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
Brian Osmanc9145f32021-07-08 13:40:10 -04001708 PLUSPLUS | MINUSMINUS | FLOAT_LITERAL [IDENTIFIER] */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001709ASTNode::ID Parser::suffix(ASTNode::ID base) {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001710 SkASSERT(base);
ethannicholasb3058bd2016-07-01 08:22:01 -07001711 Token next = this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001712 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001713 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001714 return ASTNode::ID::Invalid();
1715 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001716 switch (next.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001717 case Token::Kind::TK_LBRACKET: {
1718 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
Brian Osmancc914522021-09-24 18:58:37 +00001719 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kIndex);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001720 getNode(result).addChild(base);
1721 return result;
ethannicholas5961bc92016-10-12 06:39:56 -07001722 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001723 ASTNode::ID e = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001724 if (!e) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001725 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001726 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001727 this->expect(Token::Kind::TK_RBRACKET, "']' to complete array access expression");
Brian Osmancc914522021-09-24 18:58:37 +00001728 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kIndex);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001729 getNode(result).addChild(base);
1730 getNode(result).addChild(e);
1731 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001732 }
Brian Osman6518d772020-09-10 16:50:06 -04001733 case Token::Kind::TK_DOT: {
Brian Osmancc914522021-09-24 18:58:37 +00001734 int offset = this->peek().fOffset;
Ethan Nicholas962dec42021-06-10 13:06:39 -04001735 skstd::string_view text;
Brian Osman6518d772020-09-10 16:50:06 -04001736 if (this->identifier(&text)) {
Brian Osmancc914522021-09-24 18:58:37 +00001737 ASTNode::ID result = this->createNode(offset, ASTNode::Kind::kField,
John Stiles3b209362020-11-16 17:03:10 -05001738 std::move(text));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001739 getNode(result).addChild(base);
1740 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001741 }
Brian Osman6518d772020-09-10 16:50:06 -04001742 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04001743 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001744 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholase455f652019-09-13 12:52:55 -04001745 // Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
1746 // floating point literals, possibly followed by an identifier. Handle that here.
Ethan Nicholas962dec42021-06-10 13:06:39 -04001747 skstd::string_view field = this->text(next);
Ethan Nicholasd2e09602021-06-10 11:21:59 -04001748 SkASSERT(field[0] == '.');
1749 field.remove_prefix(1);
1750 for (auto iter = field.begin(); iter != field.end(); ++iter) {
1751 if (*iter != '0' && *iter != '1') {
Ethan Nicholase455f652019-09-13 12:52:55 -04001752 this->error(next, "invalid swizzle");
1753 return ASTNode::ID::Invalid();
1754 }
1755 }
1756 // use the next *raw* token so we don't ignore whitespace - we only care about
1757 // identifiers that directly follow the float
1758 Token id = this->nextRawToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001759 if (id.fKind == Token::Kind::TK_IDENTIFIER) {
Ethan Nicholas962dec42021-06-10 13:06:39 -04001760 field = skstd::string_view(field.data(), field.length() + id.fLength);
Ethan Nicholase455f652019-09-13 12:52:55 -04001761 } else {
1762 this->pushback(id);
1763 }
Brian Osmancc914522021-09-24 18:58:37 +00001764 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kField, field);
Ethan Nicholase455f652019-09-13 12:52:55 -04001765 getNode(result).addChild(base);
1766 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001767 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001768 case Token::Kind::TK_LPAREN: {
Brian Osmancc914522021-09-24 18:58:37 +00001769 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kCall);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001770 getNode(result).addChild(base);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001771 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001772 for (;;) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001773 ASTNode::ID expr = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001774 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001775 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001776 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001777 getNode(result).addChild(expr);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001778 if (!this->checkNext(Token::Kind::TK_COMMA)) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001779 break;
1780 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001781 }
1782 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001783 this->expect(Token::Kind::TK_RPAREN, "')' to complete function parameters");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001784 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001785 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001786 case Token::Kind::TK_PLUSPLUS: // fall through
1787 case Token::Kind::TK_MINUSMINUS: {
Brian Osmancc914522021-09-24 18:58:37 +00001788 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kPostfix,
John Stiles45990502021-02-16 10:55:27 -05001789 Operator(next.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001790 getNode(result).addChild(base);
1791 return result;
1792 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001793 default: {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001794 this->error(next, "expected expression suffix, but found '" + this->text(next) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001795 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001796 }
1797 }
1798}
1799
Brian Osman33c64a42020-12-23 10:26:38 -05001800/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001801ASTNode::ID Parser::term() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001802 Token t = this->peek();
1803 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001804 case Token::Kind::TK_IDENTIFIER: {
Ethan Nicholas962dec42021-06-10 13:06:39 -04001805 skstd::string_view text;
ethannicholasb3058bd2016-07-01 08:22:01 -07001806 if (this->identifier(&text)) {
Brian Osmancc914522021-09-24 18:58:37 +00001807 return this->createNode(t.fOffset, ASTNode::Kind::kIdentifier, std::move(text));
ethannicholasb3058bd2016-07-01 08:22:01 -07001808 }
John Stiles30212b72020-06-11 17:55:07 -04001809 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001810 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001811 case Token::Kind::TK_INT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001812 SKSL_INT i;
ethannicholasb3058bd2016-07-01 08:22:01 -07001813 if (this->intLiteral(&i)) {
Brian Osmancc914522021-09-24 18:58:37 +00001814 return this->createNode(t.fOffset, ASTNode::Kind::kInt, i);
ethannicholasb3058bd2016-07-01 08:22:01 -07001815 }
1816 break;
1817 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001818 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001819 SKSL_FLOAT f;
ethannicholasb3058bd2016-07-01 08:22:01 -07001820 if (this->floatLiteral(&f)) {
Brian Osmancc914522021-09-24 18:58:37 +00001821 return this->createNode(t.fOffset, ASTNode::Kind::kFloat, f);
ethannicholasb3058bd2016-07-01 08:22:01 -07001822 }
1823 break;
1824 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001825 case Token::Kind::TK_TRUE_LITERAL: // fall through
1826 case Token::Kind::TK_FALSE_LITERAL: {
ethannicholasb3058bd2016-07-01 08:22:01 -07001827 bool b;
1828 if (this->boolLiteral(&b)) {
Brian Osmancc914522021-09-24 18:58:37 +00001829 return this->createNode(t.fOffset, ASTNode::Kind::kBool, b);
ethannicholasb3058bd2016-07-01 08:22:01 -07001830 }
1831 break;
1832 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001833 case Token::Kind::TK_LPAREN: {
ethannicholasb3058bd2016-07-01 08:22:01 -07001834 this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001835 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001836 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001837 return ASTNode::ID::Invalid();
1838 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001839 ASTNode::ID result = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001840 if (result) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001841 this->expect(Token::Kind::TK_RPAREN, "')' to complete expression");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001842 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001843 }
1844 break;
1845 }
1846 default:
1847 this->nextToken();
Brian Osmancc914522021-09-24 18:58:37 +00001848 this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001849 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001850 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001851}
1852
1853/* INT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001854bool Parser::intLiteral(SKSL_INT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001855 Token t;
John Stilesf94348f2020-12-23 18:58:43 -05001856 if (!this->expect(Token::Kind::TK_INT_LITERAL, "integer literal", &t)) {
1857 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001858 }
Ethan Nicholas962dec42021-06-10 13:06:39 -04001859 skstd::string_view s = this->text(t);
John Stilesf94348f2020-12-23 18:58:43 -05001860 if (!SkSL::stoi(s, dest)) {
1861 this->error(t, "integer is too large: " + s);
1862 return false;
1863 }
1864 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001865}
1866
John Stilesf94348f2020-12-23 18:58:43 -05001867
ethannicholasb3058bd2016-07-01 08:22:01 -07001868/* FLOAT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001869bool Parser::floatLiteral(SKSL_FLOAT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001870 Token t;
John Stilesf94348f2020-12-23 18:58:43 -05001871 if (!this->expect(Token::Kind::TK_FLOAT_LITERAL, "float literal", &t)) {
1872 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001873 }
Ethan Nicholas962dec42021-06-10 13:06:39 -04001874 skstd::string_view s = this->text(t);
John Stilesf94348f2020-12-23 18:58:43 -05001875 if (!SkSL::stod(s, dest)) {
1876 this->error(t, "floating-point value is too large: " + s);
1877 return false;
1878 }
1879 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001880}
1881
1882/* TRUE_LITERAL | FALSE_LITERAL */
1883bool Parser::boolLiteral(bool* dest) {
1884 Token t = this->nextToken();
1885 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001886 case Token::Kind::TK_TRUE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07001887 *dest = true;
1888 return true;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001889 case Token::Kind::TK_FALSE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07001890 *dest = false;
1891 return true;
1892 default:
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001893 this->error(t, "expected 'true' or 'false', but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001894 return false;
1895 }
1896}
1897
1898/* IDENTIFIER */
Ethan Nicholas962dec42021-06-10 13:06:39 -04001899bool Parser::identifier(skstd::string_view* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001900 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001901 if (this->expect(Token::Kind::TK_IDENTIFIER, "identifier", &t)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001902 *dest = this->text(t);
ethannicholasb3058bd2016-07-01 08:22:01 -07001903 return true;
1904 }
1905 return false;
1906}
1907
John Stilesa6841be2020-08-06 14:11:56 -04001908} // namespace SkSL