blob: 6c922327ba43073cd25eeb67e528eee06adf33f0 [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05007
Mike Klein4b432fa2019-06-06 11:44:05 -05008#include "src/sksl/SkSLParser.h"
John Stilesfbd050b2020-08-03 13:21:46 -04009
10#include <memory>
11#include "stdio.h"
12
Ethan Nicholasdaed2592021-03-04 14:30:25 -050013#include "include/private/SkSLModifiers.h"
John Stilesfbd050b2020-08-03 13:21:46 -040014#include "src/sksl/SkSLASTNode.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/sksl/ir/SkSLSymbolTable.h"
16#include "src/sksl/ir/SkSLType.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070017
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040018#ifndef SKSL_STANDALONE
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "include/private/SkOnce.h"
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040020#endif
21
ethannicholasb3058bd2016-07-01 08:22:01 -070022namespace SkSL {
23
John Stiles8d056592020-11-10 10:03:50 -050024static constexpr int kMaxParseDepth = 50;
John Stilesd39aec92020-12-03 14:37:16 -050025static constexpr int kMaxStructDepth = 8;
John Stilesa695d622020-11-10 10:04:26 -050026
27static bool struct_is_too_deeply_nested(const Type& type, int limit) {
28 if (limit < 0) {
29 return true;
30 }
31
John Stilesc0c51062020-12-03 17:16:29 -050032 if (type.isStruct()) {
John Stilesa695d622020-11-10 10:04:26 -050033 for (const Type::Field& f : type.fields()) {
34 if (struct_is_too_deeply_nested(*f.fType, limit - 1)) {
35 return true;
36 }
37 }
38 }
39
40 return false;
41}
ethannicholascad64162016-10-27 10:54:02 -070042
John Stiles7d5b90a2021-01-21 14:26:51 -050043static int parse_modifier_token(Token::Kind token) {
44 switch (token) {
45 case Token::Kind::TK_UNIFORM: return Modifiers::kUniform_Flag;
46 case Token::Kind::TK_CONST: return Modifiers::kConst_Flag;
47 case Token::Kind::TK_IN: return Modifiers::kIn_Flag;
48 case Token::Kind::TK_OUT: return Modifiers::kOut_Flag;
49 case Token::Kind::TK_INOUT: return Modifiers::kIn_Flag | Modifiers::kOut_Flag;
50 case Token::Kind::TK_FLAT: return Modifiers::kFlat_Flag;
51 case Token::Kind::TK_NOPERSPECTIVE: return Modifiers::kNoPerspective_Flag;
John Stiles7d5b90a2021-01-21 14:26:51 -050052 case Token::Kind::TK_HASSIDEEFFECTS: return Modifiers::kHasSideEffects_Flag;
John Stiles7d5b90a2021-01-21 14:26:51 -050053 case Token::Kind::TK_INLINE: return Modifiers::kInline_Flag;
John Stiles0dd1a772021-03-09 22:14:27 -050054 case Token::Kind::TK_NOINLINE: return Modifiers::kNoInline_Flag;
John Stiles7d5b90a2021-01-21 14:26:51 -050055 default: return 0;
56 }
57}
58
ethannicholascad64162016-10-27 10:54:02 -070059class AutoDepth {
60public:
61 AutoDepth(Parser* p)
Ethan Nicholascf4deab2019-09-13 16:28:14 -040062 : fParser(p)
63 , fDepth(0) {}
ethannicholascad64162016-10-27 10:54:02 -070064
65 ~AutoDepth() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -040066 fParser->fDepth -= fDepth;
ethannicholascad64162016-10-27 10:54:02 -070067 }
68
Ethan Nicholascf4deab2019-09-13 16:28:14 -040069 bool increase() {
70 ++fDepth;
71 ++fParser->fDepth;
John Stiles8d056592020-11-10 10:03:50 -050072 if (fParser->fDepth > kMaxParseDepth) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070073 fParser->error(fParser->peek(), String("exceeded max parse depth"));
ethannicholascad64162016-10-27 10:54:02 -070074 return false;
75 }
76 return true;
77 }
78
79private:
80 Parser* fParser;
Ethan Nicholascf4deab2019-09-13 16:28:14 -040081 int fDepth;
ethannicholascad64162016-10-27 10:54:02 -070082};
83
Brian Salomon140f3da2018-08-23 13:51:27 +000084std::unordered_map<String, Parser::LayoutToken>* Parser::layoutTokens;
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040085
86void Parser::InitLayoutMap() {
Brian Salomon140f3da2018-08-23 13:51:27 +000087 layoutTokens = new std::unordered_map<String, LayoutToken>;
Brian Salomon23356442018-11-30 15:33:19 -050088 #define TOKEN(name, text) (*layoutTokens)[text] = LayoutToken::name
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040089 TOKEN(LOCATION, "location");
90 TOKEN(OFFSET, "offset");
91 TOKEN(BINDING, "binding");
92 TOKEN(INDEX, "index");
93 TOKEN(SET, "set");
94 TOKEN(BUILTIN, "builtin");
95 TOKEN(INPUT_ATTACHMENT_INDEX, "input_attachment_index");
96 TOKEN(ORIGIN_UPPER_LEFT, "origin_upper_left");
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040097 TOKEN(BLEND_SUPPORT_ALL_EQUATIONS, "blend_support_all_equations");
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040098 TOKEN(PUSH_CONSTANT, "push_constant");
99 TOKEN(POINTS, "points");
100 TOKEN(LINES, "lines");
101 TOKEN(LINE_STRIP, "line_strip");
102 TOKEN(LINES_ADJACENCY, "lines_adjacency");
103 TOKEN(TRIANGLES, "triangles");
104 TOKEN(TRIANGLE_STRIP, "triangle_strip");
105 TOKEN(TRIANGLES_ADJACENCY, "triangles_adjacency");
106 TOKEN(MAX_VERTICES, "max_vertices");
107 TOKEN(INVOCATIONS, "invocations");
Brian Osmanb32d66b2020-04-30 17:12:03 -0400108 TOKEN(SRGB_UNPREMUL, "srgb_unpremul");
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400109 #undef TOKEN
110}
111
Ethan Nicholas6823b502021-06-15 11:42:07 -0400112Parser::Parser(skstd::string_view text, SymbolTable& symbols, ErrorReporter& errors)
113: fText(text)
John Stiles7cbb09c22021-01-07 16:07:00 -0500114, fPushback(Token::Kind::TK_NONE, -1, -1)
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400115, fSymbols(symbols)
ethannicholasb3058bd2016-07-01 08:22:01 -0700116, fErrors(errors) {
Ethan Nicholas6823b502021-06-15 11:42:07 -0400117 fLexer.start(text);
Brian Salomon3b83afe2018-08-23 11:04:36 -0400118 static const bool layoutMapInitialized = []{ return (void)InitLayoutMap(), true; }();
119 (void) layoutMapInitialized;
ethannicholasb3058bd2016-07-01 08:22:01 -0700120}
121
John Stiles3b209362020-11-16 17:03:10 -0500122template <typename... Args>
123ASTNode::ID Parser::createNode(Args&&... args) {
124 ASTNode::ID result(fFile->fNodes.size());
125 fFile->fNodes.emplace_back(&fFile->fNodes, std::forward<Args>(args)...);
126 return result;
127}
Ethan Nicholasfc994162019-06-06 10:04:27 -0400128
John Stiles3b209362020-11-16 17:03:10 -0500129ASTNode::ID Parser::addChild(ASTNode::ID target, ASTNode::ID child) {
130 fFile->fNodes[target.fValue].addChild(child);
131 return child;
132}
Ethan Nicholasfc994162019-06-06 10:04:27 -0400133
John Stiles3b209362020-11-16 17:03:10 -0500134void Parser::createEmptyChild(ASTNode::ID target) {
135 ASTNode::ID child(fFile->fNodes.size());
136 fFile->fNodes.emplace_back();
137 fFile->fNodes[target.fValue].addChild(child);
138}
Ethan Nicholasfc994162019-06-06 10:04:27 -0400139
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400140/* (directive | section | declaration)* END_OF_FILE */
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500141std::unique_ptr<ASTFile> Parser::compilationUnit() {
John Stilesfbd050b2020-08-03 13:21:46 -0400142 fFile = std::make_unique<ASTFile>();
John Stiles18a45b32021-03-29 18:07:32 -0400143 fFile->fNodes.reserve(fText.size() / 10); // a typical program is approx 10:1 for chars:nodes
John Stiles3b209362020-11-16 17:03:10 -0500144 ASTNode::ID result = this->createNode(/*offset=*/0, ASTNode::Kind::kFile);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400145 fFile->fRoot = result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700146 for (;;) {
147 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400148 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholasfc994162019-06-06 10:04:27 -0400149 return std::move(fFile);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400150 case Token::Kind::TK_DIRECTIVE: {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400151 ASTNode::ID dir = this->directive();
152 if (fErrors.errorCount()) {
153 return nullptr;
154 }
155 if (dir) {
156 getNode(result).addChild(dir);
ethannicholasb3058bd2016-07-01 08:22:01 -0700157 }
158 break;
159 }
John Stiles7cbb09c22021-01-07 16:07:00 -0500160 case Token::Kind::TK_INVALID: {
161 this->error(this->peek(), String("invalid token"));
162 return nullptr;
163 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700164 default: {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400165 ASTNode::ID decl = this->declaration();
166 if (fErrors.errorCount()) {
167 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700168 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400169 if (decl) {
170 getNode(result).addChild(decl);
171 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700172 }
173 }
174 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400175 return std::move(fFile);
ethannicholasb3058bd2016-07-01 08:22:01 -0700176}
177
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700178Token Parser::nextRawToken() {
John Stiles7cbb09c22021-01-07 16:07:00 -0500179 if (fPushback.fKind != Token::Kind::TK_NONE) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700180 Token result = fPushback;
John Stiles7cbb09c22021-01-07 16:07:00 -0500181 fPushback.fKind = Token::Kind::TK_NONE;
ethannicholasb3058bd2016-07-01 08:22:01 -0700182 return result;
183 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700184 Token result = fLexer.next();
185 return result;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400186}
187
188Token Parser::nextToken() {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700189 Token token = this->nextRawToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400190 while (token.fKind == Token::Kind::TK_WHITESPACE ||
191 token.fKind == Token::Kind::TK_LINE_COMMENT ||
192 token.fKind == Token::Kind::TK_BLOCK_COMMENT) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700193 token = this->nextRawToken();
194 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400195 return token;
ethannicholasb3058bd2016-07-01 08:22:01 -0700196}
197
198void Parser::pushback(Token t) {
John Stiles7cbb09c22021-01-07 16:07:00 -0500199 SkASSERT(fPushback.fKind == Token::Kind::TK_NONE);
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400200 fPushback = std::move(t);
ethannicholasb3058bd2016-07-01 08:22:01 -0700201}
202
203Token Parser::peek() {
John Stiles7cbb09c22021-01-07 16:07:00 -0500204 if (fPushback.fKind == Token::Kind::TK_NONE) {
Brian Osman634624a2017-08-15 11:14:30 -0400205 fPushback = this->nextToken();
206 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700207 return fPushback;
208}
209
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400210bool Parser::checkNext(Token::Kind kind, Token* result) {
John Stiles7cbb09c22021-01-07 16:07:00 -0500211 if (fPushback.fKind != Token::Kind::TK_NONE && fPushback.fKind != kind) {
Brian Osman634624a2017-08-15 11:14:30 -0400212 return false;
213 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400214 Token next = this->nextToken();
215 if (next.fKind == kind) {
216 if (result) {
217 *result = next;
218 }
219 return true;
220 }
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400221 this->pushback(std::move(next));
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400222 return false;
223}
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500224
225bool Parser::expect(Token::Kind kind, const char* expected, Token* result) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700226 Token next = this->nextToken();
227 if (next.fKind == kind) {
228 if (result) {
Brian Osman634624a2017-08-15 11:14:30 -0400229 *result = std::move(next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700230 }
231 return true;
232 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700233 this->error(next, "expected " + String(expected) + ", but found '" +
234 this->text(next) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700235 return false;
236 }
237}
238
John Stiles2630ea32020-12-04 10:51:21 -0500239bool Parser::expectIdentifier(Token* result) {
240 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", result)) {
241 return false;
242 }
243 if (this->isType(this->text(*result))) {
244 this->error(*result, "expected an identifier, but found type '" +
245 this->text(*result) + "'");
246 return false;
247 }
248 return true;
249}
250
Ethan Nicholas962dec42021-06-10 13:06:39 -0400251skstd::string_view Parser::text(Token token) {
252 return skstd::string_view(fText.begin() + token.fOffset, token.fLength);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500253}
254
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700255void Parser::error(Token token, String msg) {
256 this->error(token.fOffset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -0700257}
258
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700259void Parser::error(int offset, String msg) {
260 fErrors.error(offset, msg);
261}
262
Ethan Nicholas962dec42021-06-10 13:06:39 -0400263bool Parser::isType(skstd::string_view name) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400264 const Symbol* s = fSymbols[name];
John Stiles2630ea32020-12-04 10:51:21 -0500265 return s && s->is<Type>();
ethannicholasb3058bd2016-07-01 08:22:01 -0700266}
267
John Stiles80b02af2021-02-12 17:07:51 -0500268bool Parser::isArrayType(ASTNode::ID type) {
269 const ASTNode& node = this->getNode(type);
270 SkASSERT(node.fKind == ASTNode::Kind::kType);
271 return node.begin() != node.end();
272}
273
Ethan Nicholas11d53972016-11-28 11:23:23 -0500274/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
ethannicholas5961bc92016-10-12 06:39:56 -0700275 DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400276ASTNode::ID Parser::directive() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700277 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400278 if (!this->expect(Token::Kind::TK_DIRECTIVE, "a directive", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400279 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700280 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400281 skstd::string_view text = this->text(start);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400282 if (text == "#extension") {
ethannicholasb3058bd2016-07-01 08:22:01 -0700283 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500284 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400285 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700286 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400287 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400288 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700289 }
290 // FIXME: need to start paying attention to this token
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400291 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400292 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700293 }
John Stiles3b209362020-11-16 17:03:10 -0500294 return this->createNode(start.fOffset, ASTNode::Kind::kExtension, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700295 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700296 this->error(start, "unsupported directive '" + this->text(start) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400297 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700298 }
299}
300
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500301/* ENUM CLASS IDENTIFIER LBRACE (IDENTIFIER (EQ expression)? (COMMA IDENTIFIER (EQ expression))*)?
302 RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400303ASTNode::ID Parser::enumDeclaration() {
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500304 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400305 if (!this->expect(Token::Kind::TK_ENUM, "'enum'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400306 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500307 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400308 if (!this->expect(Token::Kind::TK_CLASS, "'class'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400309 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500310 }
311 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500312 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400313 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500314 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400315 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400316 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500317 }
Ethan Nicholasd2e09602021-06-10 11:21:59 -0400318 fSymbols.add(Type::MakeEnumType(String(this->text(name))));
John Stiles3b209362020-11-16 17:03:10 -0500319 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kEnum, this->text(name));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400320 if (!this->checkNext(Token::Kind::TK_RBRACE)) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500321 Token id;
John Stiles2630ea32020-12-04 10:51:21 -0500322 if (!this->expectIdentifier(&id)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400323 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500324 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400325 if (this->checkNext(Token::Kind::TK_EQ)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400326 ASTNode::ID value = this->assignmentExpression();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500327 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400328 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500329 }
John Stiles3b209362020-11-16 17:03:10 -0500330 ASTNode::ID child = this->addChild(
331 result, this->createNode(id.fOffset, ASTNode::Kind::kEnumCase, this->text(id)));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400332 getNode(child).addChild(value);
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500333 } else {
John Stiles3b209362020-11-16 17:03:10 -0500334 this->addChild(result,
335 this->createNode(id.fOffset, ASTNode::Kind::kEnumCase, this->text(id)));
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500336 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400337 while (!this->checkNext(Token::Kind::TK_RBRACE)) {
338 if (!this->expect(Token::Kind::TK_COMMA, "','")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400339 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500340 }
John Stiles2630ea32020-12-04 10:51:21 -0500341 if (!this->expectIdentifier(&id)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400342 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500343 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400344 if (this->checkNext(Token::Kind::TK_EQ)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400345 ASTNode::ID value = this->assignmentExpression();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500346 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400347 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500348 }
John Stiles3b209362020-11-16 17:03:10 -0500349 ASTNode::ID child = this->addChild(
350 result,
351 this->createNode(id.fOffset, ASTNode::Kind::kEnumCase, this->text(id)));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400352 getNode(child).addChild(value);
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500353 } else {
John Stiles3b209362020-11-16 17:03:10 -0500354 this->addChild(
355 result,
356 this->createNode(id.fOffset, ASTNode::Kind::kEnumCase, this->text(id)));
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500357 }
358 }
359 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400360 this->expect(Token::Kind::TK_SEMICOLON, "';'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400361 return result;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500362}
363
John Stiles147cfda2021-05-21 14:11:38 -0400364/* enumDeclaration | modifiers (interfaceBlock | structVarDeclaration | SEMICOLON |
365 type IDENTIFIER (varDeclarationEnd | LPAREN functionDeclarationEnd))) */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400366ASTNode::ID Parser::declaration() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700367 Token lookahead = this->peek();
Ethan Nicholasda6320c2020-09-02 14:08:23 -0400368 switch (lookahead.fKind) {
369 case Token::Kind::TK_ENUM:
370 return this->enumDeclaration();
371 case Token::Kind::TK_SEMICOLON:
372 this->error(lookahead.fOffset, "expected a declaration, but found ';'");
373 return ASTNode::ID::Invalid();
374 default:
375 break;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500376 }
377 Modifiers modifiers = this->modifiers();
378 lookahead = this->peek();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400379 if (lookahead.fKind == Token::Kind::TK_IDENTIFIER && !this->isType(this->text(lookahead))) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700380 // we have an identifier that's not a type, could be the start of an interface block
381 return this->interfaceBlock(modifiers);
382 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400383 if (lookahead.fKind == Token::Kind::TK_STRUCT) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700384 return this->structVarDeclaration(modifiers);
385 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400386 if (lookahead.fKind == Token::Kind::TK_SEMICOLON) {
ethannicholas5961bc92016-10-12 06:39:56 -0700387 this->nextToken();
John Stiles3b209362020-11-16 17:03:10 -0500388 return this->createNode(lookahead.fOffset, ASTNode::Kind::kModifiers, modifiers);
ethannicholas5961bc92016-10-12 06:39:56 -0700389 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400390 ASTNode::ID type = this->type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700391 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400392 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700393 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700394 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500395 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400396 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700397 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400398 if (this->checkNext(Token::Kind::TK_LPAREN)) {
John Stiles147cfda2021-05-21 14:11:38 -0400399 return this->functionDeclarationEnd(modifiers, type, name);
ethannicholasb3058bd2016-07-01 08:22:01 -0700400 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400401 return this->varDeclarationEnd(modifiers, type, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700402 }
403}
404
John Stiles147cfda2021-05-21 14:11:38 -0400405/* (RPAREN | VOID RPAREN | parameter (COMMA parameter)* RPAREN) (block | SEMICOLON) */
406ASTNode::ID Parser::functionDeclarationEnd(Modifiers modifiers,
407 ASTNode::ID type,
408 const Token& name) {
409 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kFunction);
410 ASTNode::FunctionData fd(modifiers, this->text(name), 0);
411 getNode(result).addChild(type);
412 Token lookahead = this->peek();
413 if (lookahead.fKind == Token::Kind::TK_RPAREN) {
414 // `()` means no parameters at all.
415 } else if (lookahead.fKind == Token::Kind::TK_IDENTIFIER && this->text(lookahead) == "void") {
416 // `(void)` also means no parameters at all.
417 this->nextToken();
418 } else {
419 for (;;) {
420 ASTNode::ID parameter = this->parameter();
421 if (!parameter) {
422 return ASTNode::ID::Invalid();
423 }
424 ++fd.fParameterCount;
425 getNode(result).addChild(parameter);
426 if (!this->checkNext(Token::Kind::TK_COMMA)) {
427 break;
428 }
429 }
430 }
431 getNode(result).setFunctionData(fd);
432 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
433 return ASTNode::ID::Invalid();
434 }
435 ASTNode::ID body;
436 if (!this->checkNext(Token::Kind::TK_SEMICOLON)) {
437 body = this->block();
438 if (!body) {
439 return ASTNode::ID::Invalid();
440 }
441 getNode(result).addChild(body);
442 }
443 return result;
444}
445
John Stiles76389b72021-01-25 13:49:05 -0500446/* (varDeclarations | expressionStatement) */
447ASTNode::ID Parser::varDeclarationsOrExpressionStatement() {
John Stiles89b484a2021-04-19 14:57:27 -0400448 Token nextToken = this->peek();
449 if (nextToken.fKind == Token::Kind::TK_CONST) {
450 // Statements that begin with `const` might be variable declarations, but can't be legal
451 // SkSL expression-statements. (SkSL constructors don't take a `const` modifier.)
452 return this->varDeclarations();
453 }
454
455 if (this->isType(this->text(nextToken))) {
John Stiles76389b72021-01-25 13:49:05 -0500456 // Statements that begin with a typename are most often variable declarations, but
457 // occasionally the type is part of a constructor, and these are actually expression-
458 // statements in disguise. First, attempt the common case: parse it as a vardecl.
459 Checkpoint checkpoint(this);
John Stiles8dabeac2021-02-12 16:05:00 -0500460 VarDeclarationsPrefix prefix;
461 if (this->varDeclarationsPrefix(&prefix)) {
462 return this->varDeclarationEnd(prefix.modifiers, prefix.type, this->text(prefix.name));
John Stiles76389b72021-01-25 13:49:05 -0500463 }
464
465 // If this statement wasn't actually a vardecl after all, rewind and try parsing it as an
466 // expression-statement instead.
467 checkpoint.rewind();
468 }
469
470 return this->expressionStatement();
471}
472
John Stiles8dabeac2021-02-12 16:05:00 -0500473// Helper function for varDeclarations(). If this function succeeds, we assume that the rest of the
474// statement is a variable-declaration statement, not an expression-statement.
475bool Parser::varDeclarationsPrefix(VarDeclarationsPrefix* prefixData) {
476 prefixData->modifiers = this->modifiers();
477 prefixData->type = this->type();
478 if (!prefixData->type) {
479 return false;
480 }
481 return this->expectIdentifier(&prefixData->name);
482}
483
ethannicholasb3058bd2016-07-01 08:22:01 -0700484/* modifiers type IDENTIFIER varDeclarationEnd */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400485ASTNode::ID Parser::varDeclarations() {
John Stiles8dabeac2021-02-12 16:05:00 -0500486 VarDeclarationsPrefix prefix;
487 if (!this->varDeclarationsPrefix(&prefix)) {
John Stiles76389b72021-01-25 13:49:05 -0500488 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700489 }
John Stiles8dabeac2021-02-12 16:05:00 -0500490 return this->varDeclarationEnd(prefix.modifiers, prefix.type, this->text(prefix.name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700491}
492
493/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400494ASTNode::ID Parser::structDeclaration() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400495 if (!this->expect(Token::Kind::TK_STRUCT, "'struct'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400496 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700497 }
498 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500499 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400500 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700501 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400502 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400503 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700504 }
505 std::vector<Type::Field> fields;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400506 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400507 ASTNode::ID decls = this->varDeclarations();
508 if (!decls) {
509 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700510 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400511 ASTNode& declsNode = getNode(decls);
John Stilesece1bf02021-03-08 11:15:55 -0500512 const Modifiers& modifiers = declsNode.begin()->getModifiers();
John Stiles13fc2602020-10-09 17:42:31 -0400513 if (modifiers.fFlags != Modifiers::kNo_Flag) {
514 String desc = modifiers.description();
515 desc.pop_back(); // remove trailing space
516 this->error(declsNode.fOffset,
517 "modifier '" + desc + "' is not permitted on a struct field");
518 }
519
Ethan Nicholas962dec42021-06-10 13:06:39 -0400520 const Symbol* symbol = fSymbols[(declsNode.begin() + 1)->getStringView()];
John Stiles13fc2602020-10-09 17:42:31 -0400521 SkASSERT(symbol);
522 const Type* type = &symbol->as<Type>();
John Stiles1d757782020-11-17 09:43:22 -0500523 if (type->isOpaque()) {
524 this->error(declsNode.fOffset,
525 "opaque type '" + type->name() + "' is not permitted in a struct");
526 }
John Stiles13fc2602020-10-09 17:42:31 -0400527
Ethan Nicholasfc994162019-06-06 10:04:27 -0400528 for (auto iter = declsNode.begin() + 2; iter != declsNode.end(); ++iter) {
529 ASTNode& var = *iter;
John Stilesece1bf02021-03-08 11:15:55 -0500530 const ASTNode::VarData& vd = var.getVarData();
John Stiles6bef6a72020-12-02 14:26:04 -0500531
John Stilesd39aec92020-12-03 14:37:16 -0500532 // Read array size if one is present.
533 if (vd.fIsArray) {
534 const ASTNode& size = *var.begin();
Ethan Nicholasfc994162019-06-06 10:04:27 -0400535 if (!size || size.fKind != ASTNode::Kind::kInt) {
536 this->error(declsNode.fOffset, "array size in struct field must be a constant");
537 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700538 }
John Stiles6bef6a72020-12-02 14:26:04 -0500539 if (size.getInt() <= 0 || size.getInt() > INT_MAX) {
540 this->error(declsNode.fOffset, "array size is invalid");
541 return ASTNode::ID::Invalid();
542 }
John Stilesd39aec92020-12-03 14:37:16 -0500543 // Add the array dimensions to our type.
544 int arraySize = size.getInt();
John Stilesa2179502020-12-03 14:37:57 -0500545 type = fSymbols.addArrayDimension(type, arraySize);
ethannicholasb3058bd2016-07-01 08:22:01 -0700546 }
John Stiles13fc2602020-10-09 17:42:31 -0400547
548 fields.push_back(Type::Field(modifiers, vd.fName, type));
John Stilesd39aec92020-12-03 14:37:16 -0500549 if (vd.fIsArray ? var.begin()->fNext : var.fFirstChild) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400550 this->error(declsNode.fOffset, "initializers are not permitted on struct fields");
ethannicholasb3058bd2016-07-01 08:22:01 -0700551 }
552 }
553 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400554 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400555 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700556 }
Brian Osman6c3b23f2021-02-12 13:09:58 -0500557 if (fields.empty()) {
558 this->error(name.fOffset,
559 "struct '" + this->text(name) + "' must contain at least one field");
560 return ASTNode::ID::Invalid();
561 }
Ethan Nicholasd2e09602021-06-10 11:21:59 -0400562 std::unique_ptr<Type> newType = Type::MakeStructType(name.fOffset, String(this->text(name)),
563 fields);
John Stilesa695d622020-11-10 10:04:26 -0500564 if (struct_is_too_deeply_nested(*newType, kMaxStructDepth)) {
565 this->error(name.fOffset, "struct '" + this->text(name) + "' is too deeply nested");
566 return ASTNode::ID::Invalid();
567 }
568 fSymbols.add(std::move(newType));
Brian Osman00fea5b2021-01-28 09:46:30 -0500569 return this->createNode(name.fOffset, ASTNode::Kind::kType, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700570}
571
572/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400573ASTNode::ID Parser::structVarDeclaration(Modifiers modifiers) {
574 ASTNode::ID type = this->structDeclaration();
ethannicholasb3058bd2016-07-01 08:22:01 -0700575 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400576 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700577 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400578 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400579 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400580 return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700581 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400582 this->expect(Token::Kind::TK_SEMICOLON, "';'");
John Stilesdc75a972020-11-25 16:24:55 -0500583 return type;
ethannicholasb3058bd2016-07-01 08:22:01 -0700584}
585
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400586/* (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)? (COMMA IDENTIFER
587 (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
Ethan Nicholas962dec42021-06-10 13:06:39 -0400588ASTNode::ID Parser::varDeclarationEnd(Modifiers mods, ASTNode::ID type, skstd::string_view name) {
John Stiles08070f62020-11-17 10:45:49 -0500589 int offset = this->peek().fOffset;
590 ASTNode::ID result = this->createNode(offset, ASTNode::Kind::kVarDeclarations);
591 this->addChild(result, this->createNode(offset, ASTNode::Kind::kModifiers, mods));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400592 getNode(result).addChild(type);
John Stilesd39aec92020-12-03 14:37:16 -0500593
John Stiles80b02af2021-02-12 17:07:51 -0500594 auto parseArrayDimensions = [&](ASTNode::ID currentVar, ASTNode::VarData* vd) -> bool {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400595 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stiles80b02af2021-02-12 17:07:51 -0500596 if (vd->fIsArray || this->isArrayType(type)) {
John Stilesd39aec92020-12-03 14:37:16 -0500597 this->error(this->peek(), "multi-dimensional arrays are not supported");
598 return false;
599 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400600 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
John Stiles3b209362020-11-16 17:03:10 -0500601 this->createEmptyChild(currentVar);
ethannicholasb3058bd2016-07-01 08:22:01 -0700602 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400603 ASTNode::ID size = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700604 if (!size) {
John Stilesd39aec92020-12-03 14:37:16 -0500605 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700606 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400607 getNode(currentVar).addChild(size);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400608 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
John Stilesd39aec92020-12-03 14:37:16 -0500609 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700610 }
611 }
John Stilesd39aec92020-12-03 14:37:16 -0500612 vd->fIsArray = true;
ethannicholasb3058bd2016-07-01 08:22:01 -0700613 }
John Stilesd39aec92020-12-03 14:37:16 -0500614 return true;
615 };
616
617 auto parseInitializer = [this](ASTNode::ID currentVar) -> bool {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400618 if (this->checkNext(Token::Kind::TK_EQ)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400619 ASTNode::ID value = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700620 if (!value) {
John Stilesd39aec92020-12-03 14:37:16 -0500621 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700622 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400623 getNode(currentVar).addChild(value);
ethannicholasb3058bd2016-07-01 08:22:01 -0700624 }
John Stilesd39aec92020-12-03 14:37:16 -0500625 return true;
626 };
627
628 ASTNode::ID currentVar = this->createNode(offset, ASTNode::Kind::kVarDeclaration);
629 ASTNode::VarData vd{name, /*isArray=*/false};
630
631 getNode(result).addChild(currentVar);
632 if (!parseArrayDimensions(currentVar, &vd)) {
633 return ASTNode::ID::Invalid();
634 }
635 getNode(currentVar).setVarData(vd);
636 if (!parseInitializer(currentVar)) {
637 return ASTNode::ID::Invalid();
638 }
639
640 while (this->checkNext(Token::Kind::TK_COMMA)) {
641 Token identifierName;
John Stiles2630ea32020-12-04 10:51:21 -0500642 if (!this->expectIdentifier(&identifierName)) {
John Stilesd39aec92020-12-03 14:37:16 -0500643 return ASTNode::ID::Invalid();
644 }
645
646 currentVar = ASTNode::ID(fFile->fNodes.size());
647 vd = ASTNode::VarData{this->text(identifierName), /*isArray=*/false};
648 fFile->fNodes.emplace_back(&fFile->fNodes, offset, ASTNode::Kind::kVarDeclaration);
649
650 getNode(result).addChild(currentVar);
651 if (!parseArrayDimensions(currentVar, &vd)) {
652 return ASTNode::ID::Invalid();
653 }
654 getNode(currentVar).setVarData(vd);
655 if (!parseInitializer(currentVar)) {
656 return ASTNode::ID::Invalid();
657 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700658 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400659 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400660 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700661 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400662 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700663}
664
665/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400666ASTNode::ID Parser::parameter() {
Ethan Nicholasc6f5e102017-03-31 14:53:17 -0400667 Modifiers modifiers = this->modifiersWithDefaults(0);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400668 ASTNode::ID type = this->type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700669 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400670 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700671 }
672 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500673 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400674 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700675 }
John Stiles3b209362020-11-16 17:03:10 -0500676 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kParameter);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400677 ASTNode::ParameterData pd(modifiers, this->text(name), 0);
678 getNode(result).addChild(type);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400679 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stiles80b02af2021-02-12 17:07:51 -0500680 if (pd.fIsArray || this->isArrayType(type)) {
John Stilesd39aec92020-12-03 14:37:16 -0500681 this->error(this->peek(), "multi-dimensional arrays are not supported");
682 return ASTNode::ID::Invalid();
683 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700684 Token sizeToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400685 if (!this->expect(Token::Kind::TK_INT_LITERAL, "a positive integer", &sizeToken)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400686 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700687 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400688 skstd::string_view arraySizeFrag = this->text(sizeToken);
John Stilesf94348f2020-12-23 18:58:43 -0500689 SKSL_INT arraySize;
690 if (!SkSL::stoi(arraySizeFrag, &arraySize)) {
691 this->error(sizeToken, "array size is too large: " + arraySizeFrag);
692 return ASTNode::ID::Invalid();
693 }
694 this->addChild(result, this->createNode(sizeToken.fOffset, ASTNode::Kind::kInt, arraySize));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400695 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400696 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700697 }
John Stilesd39aec92020-12-03 14:37:16 -0500698 pd.fIsArray = true;
ethannicholasb3058bd2016-07-01 08:22:01 -0700699 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400700 getNode(result).setParameterData(pd);
701 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700702}
703
Ethan Nicholasd608c092017-10-26 09:30:08 -0400704/** EQ INT_LITERAL */
ethannicholasb3058bd2016-07-01 08:22:01 -0700705int Parser::layoutInt() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400706 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700707 return -1;
708 }
709 Token resultToken;
John Stilesf94348f2020-12-23 18:58:43 -0500710 if (!this->expect(Token::Kind::TK_INT_LITERAL, "a non-negative integer", &resultToken)) {
711 return -1;
ethannicholasb3058bd2016-07-01 08:22:01 -0700712 }
Ethan Nicholas962dec42021-06-10 13:06:39 -0400713 skstd::string_view resultFrag = this->text(resultToken);
John Stilesf94348f2020-12-23 18:58:43 -0500714 SKSL_INT resultValue;
715 if (!SkSL::stoi(resultFrag, &resultValue)) {
716 this->error(resultToken, "value in layout is too large: " + resultFrag);
717 return -1;
718 }
719 return resultValue;
ethannicholasb3058bd2016-07-01 08:22:01 -0700720}
721
Ethan Nicholasd608c092017-10-26 09:30:08 -0400722/** EQ IDENTIFIER */
Ethan Nicholas962dec42021-06-10 13:06:39 -0400723skstd::string_view Parser::layoutIdentifier() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400724 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
Ethan Nicholas962dec42021-06-10 13:06:39 -0400725 return skstd::string_view();
Ethan Nicholasd608c092017-10-26 09:30:08 -0400726 }
727 Token resultToken;
John Stiles2630ea32020-12-04 10:51:21 -0500728 if (!this->expectIdentifier(&resultToken)) {
Ethan Nicholas962dec42021-06-10 13:06:39 -0400729 return skstd::string_view();
Ethan Nicholasd608c092017-10-26 09:30:08 -0400730 }
731 return this->text(resultToken);
732}
733
ethannicholas8ac838d2016-11-22 08:39:36 -0800734/* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500735Layout Parser::layout() {
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500736 int flags = 0;
ethannicholasb3058bd2016-07-01 08:22:01 -0700737 int location = -1;
Ethan Nicholas19671772016-11-28 16:30:17 -0500738 int offset = -1;
ethannicholasb3058bd2016-07-01 08:22:01 -0700739 int binding = -1;
740 int index = -1;
741 int set = -1;
742 int builtin = -1;
Greg Daniel64773e62016-11-22 09:44:03 -0500743 int inputAttachmentIndex = -1;
Ethan Nicholas52cad152017-02-16 16:37:32 -0500744 Layout::Primitive primitive = Layout::kUnspecified_Primitive;
745 int maxVertices = -1;
746 int invocations = -1;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400747 if (this->checkNext(Token::Kind::TK_LAYOUT)) {
748 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500749 return Layout(flags, location, offset, binding, index, set, builtin,
Brian Osman8c264792021-07-01 16:41:27 -0400750 inputAttachmentIndex, primitive, maxVertices, invocations);
ethannicholasb3058bd2016-07-01 08:22:01 -0700751 }
752 for (;;) {
753 Token t = this->nextToken();
Ethan Nicholasd2e09602021-06-10 11:21:59 -0400754 String text(this->text(t));
Brian Osmana77ed8b2021-02-23 12:54:22 -0500755 auto setFlag = [&](Layout::Flag f) {
756 if (flags & f) {
757 this->error(t, "layout qualifier '" + text + "' appears more than once");
758 }
759 flags |= f;
760 };
761 auto setPrimitive = [&](Layout::Primitive p) {
762 if (flags & Layout::kPrimitive_Flag) {
763 this->error(t, "only one primitive-type layout qualifier is allowed");
764 }
765 flags |= Layout::kPrimitive_Flag;
766 primitive = p;
767 };
768
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400769 auto found = layoutTokens->find(text);
770 if (found != layoutTokens->end()) {
771 switch (found->second) {
Brian Osmana77ed8b2021-02-23 12:54:22 -0500772 case LayoutToken::ORIGIN_UPPER_LEFT:
773 setFlag(Layout::kOriginUpperLeft_Flag);
774 break;
Brian Osmana77ed8b2021-02-23 12:54:22 -0500775 case LayoutToken::PUSH_CONSTANT:
776 setFlag(Layout::kPushConstant_Flag);
777 break;
778 case LayoutToken::BLEND_SUPPORT_ALL_EQUATIONS:
779 setFlag(Layout::kBlendSupportAllEquations_Flag);
780 break;
Brian Osmana77ed8b2021-02-23 12:54:22 -0500781 case LayoutToken::SRGB_UNPREMUL:
782 setFlag(Layout::kSRGBUnpremul_Flag);
783 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700784 case LayoutToken::LOCATION:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500785 setFlag(Layout::kLocation_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500786 location = this->layoutInt();
787 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700788 case LayoutToken::OFFSET:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500789 setFlag(Layout::kOffset_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500790 offset = this->layoutInt();
791 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700792 case LayoutToken::BINDING:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500793 setFlag(Layout::kBinding_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500794 binding = this->layoutInt();
795 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700796 case LayoutToken::INDEX:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500797 setFlag(Layout::kIndex_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500798 index = this->layoutInt();
799 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700800 case LayoutToken::SET:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500801 setFlag(Layout::kSet_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500802 set = this->layoutInt();
803 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700804 case LayoutToken::BUILTIN:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500805 setFlag(Layout::kBuiltin_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500806 builtin = this->layoutInt();
807 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700808 case LayoutToken::INPUT_ATTACHMENT_INDEX:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500809 setFlag(Layout::kInputAttachmentIndex_Flag);
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500810 inputAttachmentIndex = this->layoutInt();
811 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700812 case LayoutToken::POINTS:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500813 setPrimitive(Layout::kPoints_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500814 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700815 case LayoutToken::LINES:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500816 setPrimitive(Layout::kLines_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500817 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700818 case LayoutToken::LINE_STRIP:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500819 setPrimitive(Layout::kLineStrip_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500820 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700821 case LayoutToken::LINES_ADJACENCY:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500822 setPrimitive(Layout::kLinesAdjacency_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500823 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700824 case LayoutToken::TRIANGLES:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500825 setPrimitive(Layout::kTriangles_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500826 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700827 case LayoutToken::TRIANGLE_STRIP:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500828 setPrimitive(Layout::kTriangleStrip_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500829 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700830 case LayoutToken::TRIANGLES_ADJACENCY:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500831 setPrimitive(Layout::kTrianglesAdjacency_Primitive);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500832 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700833 case LayoutToken::MAX_VERTICES:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500834 setFlag(Layout::kMaxVertices_Flag);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500835 maxVertices = this->layoutInt();
836 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700837 case LayoutToken::INVOCATIONS:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500838 setFlag(Layout::kInvocations_Flag);
Ethan Nicholas52cad152017-02-16 16:37:32 -0500839 invocations = this->layoutInt();
840 break;
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400841 default:
Brian Osmana77ed8b2021-02-23 12:54:22 -0500842 this->error(t, "'" + text + "' is not a valid layout qualifier");
Ethan Nicholasd608c092017-10-26 09:30:08 -0400843 break;
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500844 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700845 } else {
Brian Osmana77ed8b2021-02-23 12:54:22 -0500846 this->error(t, "'" + text + "' is not a valid layout qualifier");
ethannicholasb3058bd2016-07-01 08:22:01 -0700847 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400848 if (this->checkNext(Token::Kind::TK_RPAREN)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700849 break;
850 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400851 if (!this->expect(Token::Kind::TK_COMMA, "','")) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700852 break;
853 }
854 }
855 }
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500856 return Layout(flags, location, offset, binding, index, set, builtin, inputAttachmentIndex,
Brian Osman8c264792021-07-01 16:41:27 -0400857 primitive, maxVertices, invocations);
ethannicholasb3058bd2016-07-01 08:22:01 -0700858}
859
Brian Osmane49703f2021-04-19 11:15:24 -0400860/* layout? (UNIFORM | CONST | IN | OUT | INOUT | FLAT | NOPERSPECTIVE | INLINE)* */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500861Modifiers Parser::modifiers() {
862 Layout layout = this->layout();
ethannicholasb3058bd2016-07-01 08:22:01 -0700863 int flags = 0;
864 for (;;) {
865 // TODO: handle duplicate / incompatible flags
John Stiles7d5b90a2021-01-21 14:26:51 -0500866 int tokenFlag = parse_modifier_token(peek().fKind);
867 if (!tokenFlag) {
868 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700869 }
John Stiles7d5b90a2021-01-21 14:26:51 -0500870 flags |= tokenFlag;
871 this->nextToken();
ethannicholasb3058bd2016-07-01 08:22:01 -0700872 }
John Stiles7d5b90a2021-01-21 14:26:51 -0500873 return Modifiers(layout, flags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700874}
875
Ethan Nicholas11d53972016-11-28 11:23:23 -0500876Modifiers Parser::modifiersWithDefaults(int defaultFlags) {
877 Modifiers result = this->modifiers();
ethannicholasb3058bd2016-07-01 08:22:01 -0700878 if (!result.fFlags) {
Ethan Nicholas11d53972016-11-28 11:23:23 -0500879 return Modifiers(result.fLayout, defaultFlags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700880 }
881 return result;
882}
883
884/* ifStatement | forStatement | doStatement | whileStatement | block | expression */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400885ASTNode::ID Parser::statement() {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -0400886 Token start = this->nextToken();
887 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -0400888 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -0400889 return ASTNode::ID::Invalid();
890 }
891 this->pushback(start);
ethannicholasb3058bd2016-07-01 08:22:01 -0700892 switch (start.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400893 case Token::Kind::TK_IF: // fall through
894 case Token::Kind::TK_STATIC_IF:
ethannicholasb3058bd2016-07-01 08:22:01 -0700895 return this->ifStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400896 case Token::Kind::TK_FOR:
ethannicholasb3058bd2016-07-01 08:22:01 -0700897 return this->forStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400898 case Token::Kind::TK_DO:
ethannicholasb3058bd2016-07-01 08:22:01 -0700899 return this->doStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400900 case Token::Kind::TK_WHILE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700901 return this->whileStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400902 case Token::Kind::TK_SWITCH: // fall through
903 case Token::Kind::TK_STATIC_SWITCH:
Ethan Nicholasaf197692017-02-27 13:26:45 -0500904 return this->switchStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400905 case Token::Kind::TK_RETURN:
ethannicholasb3058bd2016-07-01 08:22:01 -0700906 return this->returnStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400907 case Token::Kind::TK_BREAK:
ethannicholasb3058bd2016-07-01 08:22:01 -0700908 return this->breakStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400909 case Token::Kind::TK_CONTINUE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700910 return this->continueStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400911 case Token::Kind::TK_DISCARD:
ethannicholasb3058bd2016-07-01 08:22:01 -0700912 return this->discardStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400913 case Token::Kind::TK_LBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -0700914 return this->block();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400915 case Token::Kind::TK_SEMICOLON:
Ethan Nicholas11d53972016-11-28 11:23:23 -0500916 this->nextToken();
John Stiles3b209362020-11-16 17:03:10 -0500917 return this->createNode(start.fOffset, ASTNode::Kind::kBlock);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400918 case Token::Kind::TK_CONST:
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400919 case Token::Kind::TK_IDENTIFIER:
John Stiles76389b72021-01-25 13:49:05 -0500920 return this->varDeclarationsOrExpressionStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700921 default:
922 return this->expressionStatement();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500923 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700924}
925
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500926/* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* QUESTION? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400927ASTNode::ID Parser::type() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700928 Token type;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400929 if (!this->expect(Token::Kind::TK_IDENTIFIER, "a type", &type)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400930 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700931 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700932 if (!this->isType(this->text(type))) {
933 this->error(type, ("no type named '" + this->text(type) + "'").c_str());
Ethan Nicholasfc994162019-06-06 10:04:27 -0400934 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700935 }
Brian Osman00fea5b2021-01-28 09:46:30 -0500936 ASTNode::ID result = this->createNode(type.fOffset, ASTNode::Kind::kType, this->text(type));
John Stilesd39aec92020-12-03 14:37:16 -0500937 bool isArray = false;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400938 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stilesd39aec92020-12-03 14:37:16 -0500939 if (isArray) {
940 this->error(this->peek(), "multi-dimensional arrays are not supported");
941 return ASTNode::ID::Invalid();
942 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400943 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400944 SKSL_INT i;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500945 if (this->intLiteral(&i)) {
John Stiles08070f62020-11-17 10:45:49 -0500946 this->addChild(result, this->createNode(this->peek().fOffset,
947 ASTNode::Kind::kInt, i));
Ethan Nicholas50afc172017-02-16 14:49:57 -0500948 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400949 return ASTNode::ID::Invalid();
Ethan Nicholas50afc172017-02-16 14:49:57 -0500950 }
951 } else {
John Stiles3b209362020-11-16 17:03:10 -0500952 this->createEmptyChild(result);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500953 }
John Stilesd39aec92020-12-03 14:37:16 -0500954 isArray = true;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400955 this->expect(Token::Kind::TK_RBRACKET, "']'");
Ethan Nicholas50afc172017-02-16 14:49:57 -0500956 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400957 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700958}
959
John Stiles57a996b2020-04-19 19:05:12 -0700960/* IDENTIFIER LBRACE
961 varDeclaration+
962 RBRACE (IDENTIFIER (LBRACKET expression? RBRACKET)*)? SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400963ASTNode::ID Parser::interfaceBlock(Modifiers mods) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700964 Token name;
John Stiles2630ea32020-12-04 10:51:21 -0500965 if (!this->expectIdentifier(&name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400966 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700967 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400968 if (peek().fKind != Token::Kind::TK_LBRACE) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700969 // we only get into interfaceBlock if we found a top-level identifier which was not a type.
Ethan Nicholas11d53972016-11-28 11:23:23 -0500970 // 99% of the time, the user was not actually intending to create an interface block, so
ethannicholasb3058bd2016-07-01 08:22:01 -0700971 // it's better to report it as an unknown type
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700972 this->error(name, "no type named '" + this->text(name) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400973 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700974 }
John Stiles3b209362020-11-16 17:03:10 -0500975 ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kInterfaceBlock);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400976 ASTNode::InterfaceBlockData id(mods, this->text(name), 0, "", 0);
ethannicholasb3058bd2016-07-01 08:22:01 -0700977 this->nextToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400978 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400979 ASTNode::ID decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700980 if (!decl) {
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(decl);
984 ++id.fDeclarationCount;
ethannicholasb3058bd2016-07-01 08:22:01 -0700985 }
John Stiles57a996b2020-04-19 19:05:12 -0700986 if (id.fDeclarationCount == 0) {
987 this->error(name, "interface block '" + this->text(name) +
988 "' must contain at least one member");
989 return ASTNode::ID::Invalid();
990 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700991 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -0400992 std::vector<ASTNode> sizes;
Ethan Nicholas962dec42021-06-10 13:06:39 -0400993 skstd::string_view instanceName;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700994 Token instanceNameToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400995 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &instanceNameToken)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400996 id.fInstanceName = this->text(instanceNameToken);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400997 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
John Stilesd39aec92020-12-03 14:37:16 -0500998 if (id.fIsArray) {
999 this->error(this->peek(), "multi-dimensional arrays are not supported");
1000 return false;
1001 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001002 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001003 ASTNode::ID size = this->expression();
Ethan Nicholas50afc172017-02-16 14:49:57 -05001004 if (!size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001005 return ASTNode::ID::Invalid();
Ethan Nicholas50afc172017-02-16 14:49:57 -05001006 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001007 getNode(result).addChild(size);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001008 } else {
John Stiles3b209362020-11-16 17:03:10 -05001009 this->createEmptyChild(result);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001010 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001011 this->expect(Token::Kind::TK_RBRACKET, "']'");
John Stilesd39aec92020-12-03 14:37:16 -05001012 id.fIsArray = true;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001013 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001014 instanceName = this->text(instanceNameToken);
ethannicholasb3058bd2016-07-01 08:22:01 -07001015 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001016 getNode(result).setInterfaceBlockData(id);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001017 this->expect(Token::Kind::TK_SEMICOLON, "';'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001018 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001019}
1020
1021/* IF LPAREN expression RPAREN statement (ELSE statement)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001022ASTNode::ID Parser::ifStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001023 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001024 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_IF, &start);
1025 if (!isStatic && !this->expect(Token::Kind::TK_IF, "'if'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001026 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001027 }
John Stiles3b209362020-11-16 17:03:10 -05001028 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kIf, isStatic);
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();
ethannicholasb3058bd2016-07-01 08:22:01 -07001031 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001032 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001033 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001034 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001035 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001036 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001037 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001038 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001039 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001040 ASTNode::ID ifTrue = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001041 if (!ifTrue) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001042 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001043 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001044 getNode(result).addChild(ifTrue);
1045 ASTNode::ID ifFalse;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001046 if (this->checkNext(Token::Kind::TK_ELSE)) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001047 ifFalse = this->statement();
1048 if (!ifFalse) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001049 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001050 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001051 getNode(result).addChild(ifFalse);
ethannicholasb3058bd2016-07-01 08:22:01 -07001052 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001053 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001054}
1055
1056/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001057ASTNode::ID Parser::doStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001058 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001059 if (!this->expect(Token::Kind::TK_DO, "'do'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001060 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001061 }
John Stiles3b209362020-11-16 17:03:10 -05001062 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kDo);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001063 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001064 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001065 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001066 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001067 getNode(result).addChild(statement);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001068 if (!this->expect(Token::Kind::TK_WHILE, "'while'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001069 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001070 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001071 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001072 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001073 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001074 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001075 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001076 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001077 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001078 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001079 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001080 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001081 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001082 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001083 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001084 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001085 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001086}
1087
1088/* WHILE LPAREN expression RPAREN STATEMENT */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001089ASTNode::ID Parser::whileStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001090 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001091 if (!this->expect(Token::Kind::TK_WHILE, "'while'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001092 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001093 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001094 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001095 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001096 }
John Stiles3b209362020-11-16 17:03:10 -05001097 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kWhile);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001098 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001099 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001100 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001101 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001102 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001103 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
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 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001107 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001108 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001109 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001110 getNode(result).addChild(statement);
1111 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001112}
1113
Ethan Nicholasaf197692017-02-27 13:26:45 -05001114/* CASE expression COLON statement* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001115ASTNode::ID Parser::switchCase() {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001116 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001117 if (!this->expect(Token::Kind::TK_CASE, "'case'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001118 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001119 }
John Stiles3b209362020-11-16 17:03:10 -05001120 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kSwitchCase);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001121 ASTNode::ID value = this->expression();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001122 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001123 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001124 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001125 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001126 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001127 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001128 getNode(result).addChild(value);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001129 while (this->peek().fKind != Token::Kind::TK_RBRACE &&
1130 this->peek().fKind != Token::Kind::TK_CASE &&
1131 this->peek().fKind != Token::Kind::TK_DEFAULT) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001132 ASTNode::ID s = this->statement();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001133 if (!s) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001134 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001135 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001136 getNode(result).addChild(s);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001137 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001138 return result;
Ethan Nicholasaf197692017-02-27 13:26:45 -05001139}
1140
1141/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001142ASTNode::ID Parser::switchStatement() {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001143 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001144 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_SWITCH, &start);
1145 if (!isStatic && !this->expect(Token::Kind::TK_SWITCH, "'switch'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001146 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001147 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001148 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001149 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001150 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001151 ASTNode::ID value = this->expression();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001152 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001153 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001154 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001155 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001156 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001157 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001158 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001159 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001160 }
John Stiles3b209362020-11-16 17:03:10 -05001161 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kSwitch, isStatic);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001162 getNode(result).addChild(value);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001163 while (this->peek().fKind == Token::Kind::TK_CASE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001164 ASTNode::ID c = this->switchCase();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001165 if (!c) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001166 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001167 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001168 getNode(result).addChild(c);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001169 }
1170 // Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
1171 // parts of the compiler may rely upon this assumption.
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001172 if (this->peek().fKind == Token::Kind::TK_DEFAULT) {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001173 Token defaultStart;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001174 SkAssertResult(this->expect(Token::Kind::TK_DEFAULT, "'default'", &defaultStart));
1175 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001176 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001177 }
John Stiles3b209362020-11-16 17:03:10 -05001178 ASTNode::ID defaultCase = this->addChild(
1179 result, this->createNode(defaultStart.fOffset, ASTNode::Kind::kSwitchCase));
1180 this->createEmptyChild(defaultCase); // empty test to signify default case
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001181 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001182 ASTNode::ID s = this->statement();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001183 if (!s) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001184 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001185 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001186 getNode(defaultCase).addChild(s);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001187 }
Ethan Nicholasaf197692017-02-27 13:26:45 -05001188 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001189 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001190 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001191 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001192 return result;
Ethan Nicholasaf197692017-02-27 13:26:45 -05001193}
1194
Ethan Nicholas11d53972016-11-28 11:23:23 -05001195/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
ethannicholasb3058bd2016-07-01 08:22:01 -07001196 STATEMENT */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001197ASTNode::ID Parser::forStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001198 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001199 if (!this->expect(Token::Kind::TK_FOR, "'for'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001200 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001201 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001202 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001203 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001204 }
John Stiles3b209362020-11-16 17:03:10 -05001205 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kFor);
ethannicholasb3058bd2016-07-01 08:22:01 -07001206 Token nextToken = this->peek();
John Stiles89b484a2021-04-19 14:57:27 -04001207 if (nextToken.fKind == Token::Kind::TK_SEMICOLON) {
1208 // An empty init-statement.
1209 this->nextToken();
1210 this->createEmptyChild(result);
1211 } else {
1212 // The init-statement must be an expression or variable declaration.
1213 ASTNode::ID initializer = this->varDeclarationsOrExpressionStatement();
1214 if (!initializer) {
1215 return ASTNode::ID::Invalid();
ethannicholasa54401d2016-10-14 08:37:32 -07001216 }
John Stiles89b484a2021-04-19 14:57:27 -04001217 getNode(result).addChild(initializer);
ethannicholasb3058bd2016-07-01 08:22:01 -07001218 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001219 ASTNode::ID test;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001220 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001221 test = this->expression();
1222 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001223 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001224 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001225 getNode(result).addChild(test);
1226 } else {
John Stiles3b209362020-11-16 17:03:10 -05001227 this->createEmptyChild(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001228 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001229 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001230 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001231 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001232 ASTNode::ID next;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001233 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001234 next = this->expression();
1235 if (!next) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001236 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001237 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001238 getNode(result).addChild(next);
1239 } else {
John Stiles3b209362020-11-16 17:03:10 -05001240 this->createEmptyChild(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001241 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001242 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001243 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001244 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001245 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001246 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001247 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001248 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001249 getNode(result).addChild(statement);
1250 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001251}
1252
1253/* RETURN expression? SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001254ASTNode::ID Parser::returnStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001255 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001256 if (!this->expect(Token::Kind::TK_RETURN, "'return'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001257 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001258 }
John Stiles3b209362020-11-16 17:03:10 -05001259 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kReturn);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001260 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001261 ASTNode::ID expression = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001262 if (!expression) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001263 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001264 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001265 getNode(result).addChild(expression);
ethannicholasb3058bd2016-07-01 08:22:01 -07001266 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001267 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001268 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001269 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001270 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001271}
1272
1273/* BREAK SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001274ASTNode::ID Parser::breakStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001275 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001276 if (!this->expect(Token::Kind::TK_BREAK, "'break'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001277 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001278 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001279 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001280 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001281 }
John Stiles3b209362020-11-16 17:03:10 -05001282 return this->createNode(start.fOffset, ASTNode::Kind::kBreak);
ethannicholasb3058bd2016-07-01 08:22:01 -07001283}
1284
1285/* CONTINUE SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001286ASTNode::ID Parser::continueStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001287 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001288 if (!this->expect(Token::Kind::TK_CONTINUE, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001289 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001290 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001291 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001292 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001293 }
John Stiles3b209362020-11-16 17:03:10 -05001294 return this->createNode(start.fOffset, ASTNode::Kind::kContinue);
ethannicholasb3058bd2016-07-01 08:22:01 -07001295}
1296
1297/* DISCARD SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001298ASTNode::ID Parser::discardStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001299 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001300 if (!this->expect(Token::Kind::TK_DISCARD, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001301 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001302 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001303 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001304 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001305 }
John Stiles3b209362020-11-16 17:03:10 -05001306 return this->createNode(start.fOffset, ASTNode::Kind::kDiscard);
ethannicholasb3058bd2016-07-01 08:22:01 -07001307}
1308
1309/* LBRACE statement* RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001310ASTNode::ID Parser::block() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001311 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001312 if (!this->expect(Token::Kind::TK_LBRACE, "'{'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001313 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001314 }
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001315 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001316 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001317 return ASTNode::ID::Invalid();
1318 }
John Stiles3b209362020-11-16 17:03:10 -05001319 ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kBlock);
ethannicholasb3058bd2016-07-01 08:22:01 -07001320 for (;;) {
1321 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001322 case Token::Kind::TK_RBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -07001323 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001324 return result;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001325 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001326 this->error(this->peek(), "expected '}', but found end of file");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001327 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001328 default: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001329 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001330 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001331 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001332 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001333 getNode(result).addChild(statement);
ethannicholasb3058bd2016-07-01 08:22:01 -07001334 }
1335 }
1336 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001337 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001338}
1339
1340/* expression SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001341ASTNode::ID Parser::expressionStatement() {
1342 ASTNode::ID expr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001343 if (expr) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001344 if (this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001345 return expr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001346 }
1347 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001348 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001349}
1350
1351/* assignmentExpression (COMMA assignmentExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001352ASTNode::ID Parser::expression() {
1353 ASTNode::ID result = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001354 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001355 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001356 }
1357 Token t;
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001358 AutoDepth depth(this);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001359 while (this->checkNext(Token::Kind::TK_COMMA, &t)) {
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001360 if (!depth.increase()) {
1361 return ASTNode::ID::Invalid();
1362 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001363 ASTNode::ID right = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001364 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001365 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001366 }
John Stiles45990502021-02-16 10:55:27 -05001367 ASTNode::ID newResult = this->createNode(t.fOffset, ASTNode::Kind::kBinary,
1368 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001369 getNode(newResult).addChild(result);
1370 getNode(newResult).addChild(right);
1371 result = newResult;
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001372 }
1373 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001374}
1375
1376/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1377 BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1378 assignmentExpression)*
1379 */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001380ASTNode::ID Parser::assignmentExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001381 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001382 ASTNode::ID result = this->ternaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001383 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001384 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001385 }
1386 for (;;) {
1387 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001388 case Token::Kind::TK_EQ: // fall through
1389 case Token::Kind::TK_STAREQ: // fall through
1390 case Token::Kind::TK_SLASHEQ: // fall through
1391 case Token::Kind::TK_PERCENTEQ: // fall through
1392 case Token::Kind::TK_PLUSEQ: // fall through
1393 case Token::Kind::TK_MINUSEQ: // fall through
1394 case Token::Kind::TK_SHLEQ: // fall through
1395 case Token::Kind::TK_SHREQ: // fall through
1396 case Token::Kind::TK_BITWISEANDEQ: // fall through
1397 case Token::Kind::TK_BITWISEXOREQ: // fall through
John Stiles8b3b1592020-11-23 11:06:44 -05001398 case Token::Kind::TK_BITWISEOREQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001399 if (!depth.increase()) {
1400 return ASTNode::ID::Invalid();
1401 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001402 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001403 ASTNode::ID right = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001404 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001405 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001406 }
John Stiles3b209362020-11-16 17:03:10 -05001407 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001408 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001409 getNode(newResult).addChild(result);
1410 getNode(newResult).addChild(right);
1411 result = newResult;
1412 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001413 }
1414 default:
1415 return result;
1416 }
1417 }
1418}
1419
1420/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001421ASTNode::ID Parser::ternaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001422 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001423 ASTNode::ID base = this->logicalOrExpression();
1424 if (!base) {
1425 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001426 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001427 if (this->checkNext(Token::Kind::TK_QUESTION)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001428 if (!depth.increase()) {
1429 return ASTNode::ID::Invalid();
1430 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001431 ASTNode::ID trueExpr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001432 if (!trueExpr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001433 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001434 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001435 if (this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001436 ASTNode::ID falseExpr = this->assignmentExpression();
1437 if (!falseExpr) {
1438 return ASTNode::ID::Invalid();
1439 }
John Stiles3b209362020-11-16 17:03:10 -05001440 ASTNode::ID ternary = this->createNode(getNode(base).fOffset, ASTNode::Kind::kTernary);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001441 getNode(ternary).addChild(base);
1442 getNode(ternary).addChild(trueExpr);
1443 getNode(ternary).addChild(falseExpr);
1444 return ternary;
ethannicholasb3058bd2016-07-01 08:22:01 -07001445 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001446 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001447 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001448 return base;
ethannicholasb3058bd2016-07-01 08:22:01 -07001449}
1450
1451/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001452ASTNode::ID Parser::logicalOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001453 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001454 ASTNode::ID result = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001455 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001456 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001457 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001458 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001459 while (this->checkNext(Token::Kind::TK_LOGICALOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001460 if (!depth.increase()) {
1461 return ASTNode::ID::Invalid();
1462 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001463 ASTNode::ID right = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001464 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001465 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001466 }
John Stiles3b209362020-11-16 17:03:10 -05001467 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001468 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001469 getNode(newResult).addChild(result);
1470 getNode(newResult).addChild(right);
1471 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001472 }
1473 return result;
1474}
1475
1476/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001477ASTNode::ID Parser::logicalXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001478 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001479 ASTNode::ID result = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001480 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001481 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001482 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001483 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001484 while (this->checkNext(Token::Kind::TK_LOGICALXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001485 if (!depth.increase()) {
1486 return ASTNode::ID::Invalid();
1487 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001488 ASTNode::ID right = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001489 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001490 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001491 }
John Stiles3b209362020-11-16 17:03:10 -05001492 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001493 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001494 getNode(newResult).addChild(result);
1495 getNode(newResult).addChild(right);
1496 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001497 }
1498 return result;
1499}
1500
1501/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001502ASTNode::ID Parser::logicalAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001503 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001504 ASTNode::ID result = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001505 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001506 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001507 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001508 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001509 while (this->checkNext(Token::Kind::TK_LOGICALAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001510 if (!depth.increase()) {
1511 return ASTNode::ID::Invalid();
1512 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001513 ASTNode::ID right = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001514 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001515 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001516 }
John Stiles3b209362020-11-16 17:03:10 -05001517 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001518 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001519 getNode(newResult).addChild(result);
1520 getNode(newResult).addChild(right);
1521 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001522 }
1523 return result;
1524}
1525
1526/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001527ASTNode::ID Parser::bitwiseOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001528 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001529 ASTNode::ID result = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001530 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001531 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001532 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001533 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001534 while (this->checkNext(Token::Kind::TK_BITWISEOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001535 if (!depth.increase()) {
1536 return ASTNode::ID::Invalid();
1537 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001538 ASTNode::ID right = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001539 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001540 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001541 }
John Stiles45990502021-02-16 10:55:27 -05001542 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
1543 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001544 getNode(newResult).addChild(result);
1545 getNode(newResult).addChild(right);
1546 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001547 }
1548 return result;
1549}
1550
1551/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001552ASTNode::ID Parser::bitwiseXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001553 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001554 ASTNode::ID result = this->bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001555 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001556 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001557 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001558 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001559 while (this->checkNext(Token::Kind::TK_BITWISEXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001560 if (!depth.increase()) {
1561 return ASTNode::ID::Invalid();
1562 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001563 ASTNode::ID right = this->bitwiseAndExpression();
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 }
John Stiles45990502021-02-16 10:55:27 -05001567 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
1568 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 }
1573 return result;
1574}
1575
1576/* equalityExpression (BITWISEAND equalityExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001577ASTNode::ID Parser::bitwiseAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001578 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001579 ASTNode::ID result = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001580 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001581 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001582 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001583 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001584 while (this->checkNext(Token::Kind::TK_BITWISEAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001585 if (!depth.increase()) {
1586 return ASTNode::ID::Invalid();
1587 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001588 ASTNode::ID right = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001589 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001590 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001591 }
John Stiles3b209362020-11-16 17:03:10 -05001592 ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
John Stiles45990502021-02-16 10:55:27 -05001593 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001594 getNode(newResult).addChild(result);
1595 getNode(newResult).addChild(right);
1596 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001597 }
1598 return result;
1599}
1600
1601/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001602ASTNode::ID Parser::equalityExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001603 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001604 ASTNode::ID result = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001605 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001606 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001607 }
1608 for (;;) {
1609 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001610 case Token::Kind::TK_EQEQ: // fall through
1611 case Token::Kind::TK_NEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001612 if (!depth.increase()) {
1613 return ASTNode::ID::Invalid();
1614 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001615 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001616 ASTNode::ID right = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001617 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001618 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001619 }
John Stiles3b209362020-11-16 17:03:10 -05001620 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001621 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001622 getNode(newResult).addChild(result);
1623 getNode(newResult).addChild(right);
1624 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001625 break;
1626 }
1627 default:
1628 return result;
1629 }
1630 }
1631}
1632
1633/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001634ASTNode::ID Parser::relationalExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001635 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001636 ASTNode::ID result = this->shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001637 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001638 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001639 }
1640 for (;;) {
1641 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001642 case Token::Kind::TK_LT: // fall through
1643 case Token::Kind::TK_GT: // fall through
1644 case Token::Kind::TK_LTEQ: // fall through
1645 case Token::Kind::TK_GTEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001646 if (!depth.increase()) {
1647 return ASTNode::ID::Invalid();
1648 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001649 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001650 ASTNode::ID right = this->shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001651 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001652 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001653 }
John Stiles3b209362020-11-16 17:03:10 -05001654 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001655 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001656 getNode(newResult).addChild(result);
1657 getNode(newResult).addChild(right);
1658 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001659 break;
1660 }
1661 default:
1662 return result;
1663 }
1664 }
1665}
1666
1667/* additiveExpression ((SHL | SHR) additiveExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001668ASTNode::ID Parser::shiftExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001669 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001670 ASTNode::ID result = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001671 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001672 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001673 }
1674 for (;;) {
1675 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001676 case Token::Kind::TK_SHL: // fall through
1677 case Token::Kind::TK_SHR: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001678 if (!depth.increase()) {
1679 return ASTNode::ID::Invalid();
1680 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001681 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001682 ASTNode::ID right = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001683 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001684 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001685 }
John Stiles3b209362020-11-16 17:03:10 -05001686 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001687 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001688 getNode(newResult).addChild(result);
1689 getNode(newResult).addChild(right);
1690 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001691 break;
1692 }
1693 default:
1694 return result;
1695 }
1696 }
1697}
1698
1699/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001700ASTNode::ID Parser::additiveExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001701 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001702 ASTNode::ID result = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001703 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001704 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001705 }
1706 for (;;) {
1707 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001708 case Token::Kind::TK_PLUS: // fall through
1709 case Token::Kind::TK_MINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001710 if (!depth.increase()) {
1711 return ASTNode::ID::Invalid();
1712 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001713 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001714 ASTNode::ID right = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001715 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001716 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001717 }
John Stiles3b209362020-11-16 17:03:10 -05001718 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001719 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001720 getNode(newResult).addChild(result);
1721 getNode(newResult).addChild(right);
1722 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001723 break;
1724 }
1725 default:
1726 return result;
1727 }
1728 }
1729}
1730
1731/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001732ASTNode::ID Parser::multiplicativeExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001733 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001734 ASTNode::ID result = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001735 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001736 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001737 }
1738 for (;;) {
1739 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001740 case Token::Kind::TK_STAR: // fall through
1741 case Token::Kind::TK_SLASH: // fall through
1742 case Token::Kind::TK_PERCENT: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001743 if (!depth.increase()) {
1744 return ASTNode::ID::Invalid();
1745 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001746 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001747 ASTNode::ID right = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001748 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001749 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001750 }
John Stiles3b209362020-11-16 17:03:10 -05001751 ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
John Stiles45990502021-02-16 10:55:27 -05001752 ASTNode::Kind::kBinary, Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001753 getNode(newResult).addChild(result);
1754 getNode(newResult).addChild(right);
1755 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001756 break;
1757 }
1758 default:
1759 return result;
1760 }
1761 }
1762}
1763
1764/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001765ASTNode::ID Parser::unaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001766 AutoDepth depth(this);
ethannicholasb3058bd2016-07-01 08:22:01 -07001767 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001768 case Token::Kind::TK_PLUS: // fall through
1769 case Token::Kind::TK_MINUS: // fall through
1770 case Token::Kind::TK_LOGICALNOT: // fall through
1771 case Token::Kind::TK_BITWISENOT: // fall through
1772 case Token::Kind::TK_PLUSPLUS: // fall through
1773 case Token::Kind::TK_MINUSMINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001774 if (!depth.increase()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001775 return ASTNode::ID::Invalid();
Ethan Nicholas6dcc3252019-02-20 15:18:36 -05001776 }
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001777 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001778 ASTNode::ID expr = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001779 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001780 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001781 }
John Stiles45990502021-02-16 10:55:27 -05001782 ASTNode::ID result = this->createNode(t.fOffset, ASTNode::Kind::kPrefix,
1783 Operator(t.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001784 getNode(result).addChild(expr);
1785 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001786 }
1787 default:
1788 return this->postfixExpression();
1789 }
1790}
1791
1792/* term suffix* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001793ASTNode::ID Parser::postfixExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001794 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001795 ASTNode::ID result = this->term();
ethannicholasb3058bd2016-07-01 08:22:01 -07001796 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001797 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001798 }
1799 for (;;) {
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001800 Token t = this->peek();
1801 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001802 case Token::Kind::TK_FLOAT_LITERAL:
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001803 if (this->text(t)[0] != '.') {
1804 return result;
1805 }
John Stiles30212b72020-06-11 17:55:07 -04001806 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001807 case Token::Kind::TK_LBRACKET:
1808 case Token::Kind::TK_DOT:
1809 case Token::Kind::TK_LPAREN:
1810 case Token::Kind::TK_PLUSPLUS:
1811 case Token::Kind::TK_MINUSMINUS:
1812 case Token::Kind::TK_COLONCOLON:
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001813 if (!depth.increase()) {
1814 return ASTNode::ID::Invalid();
1815 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001816 result = this->suffix(result);
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001817 if (!result) {
1818 return ASTNode::ID::Invalid();
1819 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001820 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001821 default:
1822 return result;
1823 }
1824 }
1825}
1826
Ethan Nicholas11d53972016-11-28 11:23:23 -05001827/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
Ethan Nicholase455f652019-09-13 12:52:55 -04001828 PLUSPLUS | MINUSMINUS | COLONCOLON IDENTIFIER | FLOAT_LITERAL [IDENTIFIER] */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001829ASTNode::ID Parser::suffix(ASTNode::ID base) {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001830 SkASSERT(base);
ethannicholasb3058bd2016-07-01 08:22:01 -07001831 Token next = this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001832 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001833 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001834 return ASTNode::ID::Invalid();
1835 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001836 switch (next.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001837 case Token::Kind::TK_LBRACKET: {
1838 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
John Stiles3b209362020-11-16 17:03:10 -05001839 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kIndex);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001840 getNode(result).addChild(base);
1841 return result;
ethannicholas5961bc92016-10-12 06:39:56 -07001842 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001843 ASTNode::ID e = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001844 if (!e) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001845 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001846 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001847 this->expect(Token::Kind::TK_RBRACKET, "']' to complete array access expression");
John Stiles3b209362020-11-16 17:03:10 -05001848 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kIndex);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001849 getNode(result).addChild(base);
1850 getNode(result).addChild(e);
1851 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001852 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001853 case Token::Kind::TK_COLONCOLON: {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001854 int offset = this->peek().fOffset;
Ethan Nicholas962dec42021-06-10 13:06:39 -04001855 skstd::string_view text;
ethannicholasb3058bd2016-07-01 08:22:01 -07001856 if (this->identifier(&text)) {
John Stiles3b209362020-11-16 17:03:10 -05001857 ASTNode::ID result = this->createNode(offset, ASTNode::Kind::kScope,
1858 std::move(text));
Brian Osman6518d772020-09-10 16:50:06 -04001859 getNode(result).addChild(base);
1860 return result;
1861 }
1862 return ASTNode::ID::Invalid();
1863 }
1864 case Token::Kind::TK_DOT: {
1865 int offset = this->peek().fOffset;
Ethan Nicholas962dec42021-06-10 13:06:39 -04001866 skstd::string_view text;
Brian Osman6518d772020-09-10 16:50:06 -04001867 if (this->identifier(&text)) {
John Stiles3b209362020-11-16 17:03:10 -05001868 ASTNode::ID result = this->createNode(offset, ASTNode::Kind::kField,
1869 std::move(text));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001870 getNode(result).addChild(base);
1871 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001872 }
Brian Osman6518d772020-09-10 16:50:06 -04001873 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04001874 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001875 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholase455f652019-09-13 12:52:55 -04001876 // Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
1877 // floating point literals, possibly followed by an identifier. Handle that here.
Ethan Nicholas962dec42021-06-10 13:06:39 -04001878 skstd::string_view field = this->text(next);
Ethan Nicholasd2e09602021-06-10 11:21:59 -04001879 SkASSERT(field[0] == '.');
1880 field.remove_prefix(1);
1881 for (auto iter = field.begin(); iter != field.end(); ++iter) {
1882 if (*iter != '0' && *iter != '1') {
Ethan Nicholase455f652019-09-13 12:52:55 -04001883 this->error(next, "invalid swizzle");
1884 return ASTNode::ID::Invalid();
1885 }
1886 }
1887 // use the next *raw* token so we don't ignore whitespace - we only care about
1888 // identifiers that directly follow the float
1889 Token id = this->nextRawToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001890 if (id.fKind == Token::Kind::TK_IDENTIFIER) {
Ethan Nicholas962dec42021-06-10 13:06:39 -04001891 field = skstd::string_view(field.data(), field.length() + id.fLength);
Ethan Nicholase455f652019-09-13 12:52:55 -04001892 } else {
1893 this->pushback(id);
1894 }
John Stiles3b209362020-11-16 17:03:10 -05001895 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kField, field);
Ethan Nicholase455f652019-09-13 12:52:55 -04001896 getNode(result).addChild(base);
1897 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001898 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001899 case Token::Kind::TK_LPAREN: {
John Stiles3b209362020-11-16 17:03:10 -05001900 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kCall);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001901 getNode(result).addChild(base);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001902 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001903 for (;;) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001904 ASTNode::ID expr = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001905 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001906 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001907 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001908 getNode(result).addChild(expr);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001909 if (!this->checkNext(Token::Kind::TK_COMMA)) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001910 break;
1911 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001912 }
1913 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001914 this->expect(Token::Kind::TK_RPAREN, "')' to complete function parameters");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001915 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001916 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001917 case Token::Kind::TK_PLUSPLUS: // fall through
1918 case Token::Kind::TK_MINUSMINUS: {
John Stiles45990502021-02-16 10:55:27 -05001919 ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kPostfix,
1920 Operator(next.fKind));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001921 getNode(result).addChild(base);
1922 return result;
1923 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001924 default: {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001925 this->error(next, "expected expression suffix, but found '" + this->text(next) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001926 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001927 }
1928 }
1929}
1930
Brian Osman33c64a42020-12-23 10:26:38 -05001931/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001932ASTNode::ID Parser::term() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001933 Token t = this->peek();
1934 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001935 case Token::Kind::TK_IDENTIFIER: {
Ethan Nicholas962dec42021-06-10 13:06:39 -04001936 skstd::string_view text;
ethannicholasb3058bd2016-07-01 08:22:01 -07001937 if (this->identifier(&text)) {
John Stiles3b209362020-11-16 17:03:10 -05001938 return this->createNode(t.fOffset, ASTNode::Kind::kIdentifier, std::move(text));
ethannicholasb3058bd2016-07-01 08:22:01 -07001939 }
John Stiles30212b72020-06-11 17:55:07 -04001940 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001941 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001942 case Token::Kind::TK_INT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001943 SKSL_INT i;
ethannicholasb3058bd2016-07-01 08:22:01 -07001944 if (this->intLiteral(&i)) {
John Stiles3b209362020-11-16 17:03:10 -05001945 return this->createNode(t.fOffset, ASTNode::Kind::kInt, i);
ethannicholasb3058bd2016-07-01 08:22:01 -07001946 }
1947 break;
1948 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001949 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001950 SKSL_FLOAT f;
ethannicholasb3058bd2016-07-01 08:22:01 -07001951 if (this->floatLiteral(&f)) {
John Stiles3b209362020-11-16 17:03:10 -05001952 return this->createNode(t.fOffset, ASTNode::Kind::kFloat, f);
ethannicholasb3058bd2016-07-01 08:22:01 -07001953 }
1954 break;
1955 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001956 case Token::Kind::TK_TRUE_LITERAL: // fall through
1957 case Token::Kind::TK_FALSE_LITERAL: {
ethannicholasb3058bd2016-07-01 08:22:01 -07001958 bool b;
1959 if (this->boolLiteral(&b)) {
John Stiles3b209362020-11-16 17:03:10 -05001960 return this->createNode(t.fOffset, ASTNode::Kind::kBool, b);
ethannicholasb3058bd2016-07-01 08:22:01 -07001961 }
1962 break;
1963 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001964 case Token::Kind::TK_LPAREN: {
ethannicholasb3058bd2016-07-01 08:22:01 -07001965 this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001966 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001967 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001968 return ASTNode::ID::Invalid();
1969 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001970 ASTNode::ID result = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001971 if (result) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001972 this->expect(Token::Kind::TK_RPAREN, "')' to complete expression");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001973 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001974 }
1975 break;
1976 }
1977 default:
1978 this->nextToken();
John Stilesf94348f2020-12-23 18:58:43 -05001979 this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001980 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001981 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001982}
1983
1984/* INT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001985bool Parser::intLiteral(SKSL_INT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001986 Token t;
John Stilesf94348f2020-12-23 18:58:43 -05001987 if (!this->expect(Token::Kind::TK_INT_LITERAL, "integer literal", &t)) {
1988 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001989 }
Ethan Nicholas962dec42021-06-10 13:06:39 -04001990 skstd::string_view s = this->text(t);
John Stilesf94348f2020-12-23 18:58:43 -05001991 if (!SkSL::stoi(s, dest)) {
1992 this->error(t, "integer is too large: " + s);
1993 return false;
1994 }
1995 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001996}
1997
John Stilesf94348f2020-12-23 18:58:43 -05001998
ethannicholasb3058bd2016-07-01 08:22:01 -07001999/* FLOAT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04002000bool Parser::floatLiteral(SKSL_FLOAT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002001 Token t;
John Stilesf94348f2020-12-23 18:58:43 -05002002 if (!this->expect(Token::Kind::TK_FLOAT_LITERAL, "float literal", &t)) {
2003 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07002004 }
Ethan Nicholas962dec42021-06-10 13:06:39 -04002005 skstd::string_view s = this->text(t);
John Stilesf94348f2020-12-23 18:58:43 -05002006 if (!SkSL::stod(s, dest)) {
2007 this->error(t, "floating-point value is too large: " + s);
2008 return false;
2009 }
2010 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07002011}
2012
2013/* TRUE_LITERAL | FALSE_LITERAL */
2014bool Parser::boolLiteral(bool* dest) {
2015 Token t = this->nextToken();
2016 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002017 case Token::Kind::TK_TRUE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07002018 *dest = true;
2019 return true;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002020 case Token::Kind::TK_FALSE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07002021 *dest = false;
2022 return true;
2023 default:
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04002024 this->error(t, "expected 'true' or 'false', but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002025 return false;
2026 }
2027}
2028
2029/* IDENTIFIER */
Ethan Nicholas962dec42021-06-10 13:06:39 -04002030bool Parser::identifier(skstd::string_view* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002031 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002032 if (this->expect(Token::Kind::TK_IDENTIFIER, "identifier", &t)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002033 *dest = this->text(t);
ethannicholasb3058bd2016-07-01 08:22:01 -07002034 return true;
2035 }
2036 return false;
2037}
2038
John Stilesa6841be2020-08-06 14:11:56 -04002039} // namespace SkSL