blob: afa9e3dab1beb2fd5a9382ba41fcbcbe4ba4b82a [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
ethannicholasb3058bd2016-07-01 08:22:01 -07008#include "stdio.h"
Ethan Nicholasfc994162019-06-06 10:04:27 -04009#include "src/sksl/SkSLASTNode.h"
Mike Klein4b432fa2019-06-06 11:44:05 -050010#include "src/sksl/SkSLParser.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/sksl/ir/SkSLModifiers.h"
12#include "src/sksl/ir/SkSLSymbolTable.h"
13#include "src/sksl/ir/SkSLType.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070014
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040015#ifndef SKSL_STANDALONE
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "include/private/SkOnce.h"
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040017#endif
18
ethannicholasb3058bd2016-07-01 08:22:01 -070019namespace SkSL {
20
ethannicholascad64162016-10-27 10:54:02 -070021#define MAX_PARSE_DEPTH 50
22
23class AutoDepth {
24public:
25 AutoDepth(Parser* p)
Ethan Nicholascf4deab2019-09-13 16:28:14 -040026 : fParser(p)
27 , fDepth(0) {}
ethannicholascad64162016-10-27 10:54:02 -070028
29 ~AutoDepth() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -040030 fParser->fDepth -= fDepth;
ethannicholascad64162016-10-27 10:54:02 -070031 }
32
Ethan Nicholascf4deab2019-09-13 16:28:14 -040033 bool increase() {
34 ++fDepth;
35 ++fParser->fDepth;
ethannicholascad64162016-10-27 10:54:02 -070036 if (fParser->fDepth > MAX_PARSE_DEPTH) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070037 fParser->error(fParser->peek(), String("exceeded max parse depth"));
ethannicholascad64162016-10-27 10:54:02 -070038 return false;
39 }
40 return true;
41 }
42
43private:
44 Parser* fParser;
Ethan Nicholascf4deab2019-09-13 16:28:14 -040045 int fDepth;
ethannicholascad64162016-10-27 10:54:02 -070046};
47
Brian Salomon140f3da2018-08-23 13:51:27 +000048std::unordered_map<String, Parser::LayoutToken>* Parser::layoutTokens;
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040049
50void Parser::InitLayoutMap() {
Brian Salomon140f3da2018-08-23 13:51:27 +000051 layoutTokens = new std::unordered_map<String, LayoutToken>;
Brian Salomon23356442018-11-30 15:33:19 -050052 #define TOKEN(name, text) (*layoutTokens)[text] = LayoutToken::name
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040053 TOKEN(LOCATION, "location");
54 TOKEN(OFFSET, "offset");
55 TOKEN(BINDING, "binding");
56 TOKEN(INDEX, "index");
57 TOKEN(SET, "set");
58 TOKEN(BUILTIN, "builtin");
59 TOKEN(INPUT_ATTACHMENT_INDEX, "input_attachment_index");
60 TOKEN(ORIGIN_UPPER_LEFT, "origin_upper_left");
61 TOKEN(OVERRIDE_COVERAGE, "override_coverage");
62 TOKEN(BLEND_SUPPORT_ALL_EQUATIONS, "blend_support_all_equations");
63 TOKEN(BLEND_SUPPORT_MULTIPLY, "blend_support_multiply");
64 TOKEN(BLEND_SUPPORT_SCREEN, "blend_support_screen");
65 TOKEN(BLEND_SUPPORT_OVERLAY, "blend_support_overlay");
66 TOKEN(BLEND_SUPPORT_DARKEN, "blend_support_darken");
67 TOKEN(BLEND_SUPPORT_LIGHTEN, "blend_support_lighten");
68 TOKEN(BLEND_SUPPORT_COLORDODGE, "blend_support_colordodge");
69 TOKEN(BLEND_SUPPORT_COLORBURN, "blend_support_colorburn");
70 TOKEN(BLEND_SUPPORT_HARDLIGHT, "blend_support_hardlight");
71 TOKEN(BLEND_SUPPORT_SOFTLIGHT, "blend_support_softlight");
72 TOKEN(BLEND_SUPPORT_DIFFERENCE, "blend_support_difference");
73 TOKEN(BLEND_SUPPORT_EXCLUSION, "blend_support_exclusion");
74 TOKEN(BLEND_SUPPORT_HSL_HUE, "blend_support_hsl_hue");
75 TOKEN(BLEND_SUPPORT_HSL_SATURATION, "blend_support_hsl_saturation");
76 TOKEN(BLEND_SUPPORT_HSL_COLOR, "blend_support_hsl_color");
77 TOKEN(BLEND_SUPPORT_HSL_LUMINOSITY, "blend_support_hsl_luminosity");
78 TOKEN(PUSH_CONSTANT, "push_constant");
79 TOKEN(POINTS, "points");
80 TOKEN(LINES, "lines");
81 TOKEN(LINE_STRIP, "line_strip");
82 TOKEN(LINES_ADJACENCY, "lines_adjacency");
83 TOKEN(TRIANGLES, "triangles");
84 TOKEN(TRIANGLE_STRIP, "triangle_strip");
85 TOKEN(TRIANGLES_ADJACENCY, "triangles_adjacency");
86 TOKEN(MAX_VERTICES, "max_vertices");
87 TOKEN(INVOCATIONS, "invocations");
Brian Osmanf59a9612020-04-15 14:18:13 -040088 TOKEN(MARKER, "marker");
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040089 TOKEN(WHEN, "when");
90 TOKEN(KEY, "key");
Michael Ludwiga4275592018-08-31 10:52:47 -040091 TOKEN(TRACKED, "tracked");
Brian Osmanb32d66b2020-04-30 17:12:03 -040092 TOKEN(SRGB_UNPREMUL, "srgb_unpremul");
Ethan Nicholas78aceb22018-08-31 16:13:58 -040093 TOKEN(CTYPE, "ctype");
Brian Osmanf28e55d2018-10-03 16:35:54 -040094 TOKEN(SKPMCOLOR4F, "SkPMColor4f");
Mike Reedb26b4e72020-01-22 14:31:21 -050095 TOKEN(SKV4, "SkV4");
Ethan Nicholas78aceb22018-08-31 16:13:58 -040096 TOKEN(SKRECT, "SkRect");
97 TOKEN(SKIRECT, "SkIRect");
98 TOKEN(SKPMCOLOR, "SkPMColor");
Mike Reedb26b4e72020-01-22 14:31:21 -050099 TOKEN(SKM44, "SkM44");
Ethan Nicholasc1c686b2019-04-02 17:30:23 -0400100 TOKEN(BOOL, "bool");
101 TOKEN(INT, "int");
102 TOKEN(FLOAT, "float");
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400103 #undef TOKEN
104}
105
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700106Parser::Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors)
107: fText(text)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400108, fPushback(Token::Kind::TK_INVALID, -1, -1)
ethannicholasb3058bd2016-07-01 08:22:01 -0700109, fTypes(types)
110, fErrors(errors) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700111 fLexer.start(text, length);
Brian Salomon3b83afe2018-08-23 11:04:36 -0400112 static const bool layoutMapInitialized = []{ return (void)InitLayoutMap(), true; }();
113 (void) layoutMapInitialized;
ethannicholasb3058bd2016-07-01 08:22:01 -0700114}
115
Ethan Nicholasfc994162019-06-06 10:04:27 -0400116#define CREATE_NODE(result, ...) \
117 ASTNode::ID result(fFile->fNodes.size()); \
118 fFile->fNodes.emplace_back(&fFile->fNodes, __VA_ARGS__)
119
120#define RETURN_NODE(...) \
121 do { \
122 CREATE_NODE(result, __VA_ARGS__); \
123 return result; \
124 } while (false)
125
126#define CREATE_CHILD(child, target, ...) \
127 CREATE_NODE(child, __VA_ARGS__); \
128 fFile->fNodes[target.fValue].addChild(child)
129
130#define CREATE_EMPTY_CHILD(target) \
131 do { \
132 ASTNode::ID child(fFile->fNodes.size()); \
133 fFile->fNodes.emplace_back(); \
134 fFile->fNodes[target.fValue].addChild(child); \
135 } while (false)
136
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400137/* (directive | section | declaration)* END_OF_FILE */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400138std::unique_ptr<ASTFile> Parser::file() {
139 fFile.reset(new ASTFile());
140 CREATE_NODE(result, 0, ASTNode::Kind::kFile);
141 fFile->fRoot = result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700142 for (;;) {
143 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400144 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholasfc994162019-06-06 10:04:27 -0400145 return std::move(fFile);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400146 case Token::Kind::TK_DIRECTIVE: {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400147 ASTNode::ID dir = this->directive();
148 if (fErrors.errorCount()) {
149 return nullptr;
150 }
151 if (dir) {
152 getNode(result).addChild(dir);
ethannicholasb3058bd2016-07-01 08:22:01 -0700153 }
154 break;
155 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400156 case Token::Kind::TK_SECTION: {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400157 ASTNode::ID section = this->section();
158 if (fErrors.errorCount()) {
159 return nullptr;
160 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400161 if (section) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400162 getNode(result).addChild(section);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400163 }
164 break;
165 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700166 default: {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400167 ASTNode::ID decl = this->declaration();
168 if (fErrors.errorCount()) {
169 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700170 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400171 if (decl) {
172 getNode(result).addChild(decl);
173 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700174 }
175 }
176 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400177 return std::move(fFile);
ethannicholasb3058bd2016-07-01 08:22:01 -0700178}
179
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700180Token Parser::nextRawToken() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400181 if (fPushback.fKind != Token::Kind::TK_INVALID) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700182 Token result = fPushback;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400183 fPushback.fKind = Token::Kind::TK_INVALID;
ethannicholasb3058bd2016-07-01 08:22:01 -0700184 return result;
185 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700186 Token result = fLexer.next();
187 return result;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400188}
189
190Token Parser::nextToken() {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700191 Token token = this->nextRawToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400192 while (token.fKind == Token::Kind::TK_WHITESPACE ||
193 token.fKind == Token::Kind::TK_LINE_COMMENT ||
194 token.fKind == Token::Kind::TK_BLOCK_COMMENT) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700195 token = this->nextRawToken();
196 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400197 return token;
ethannicholasb3058bd2016-07-01 08:22:01 -0700198}
199
200void Parser::pushback(Token t) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400201 SkASSERT(fPushback.fKind == Token::Kind::TK_INVALID);
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400202 fPushback = std::move(t);
ethannicholasb3058bd2016-07-01 08:22:01 -0700203}
204
205Token Parser::peek() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400206 if (fPushback.fKind == Token::Kind::TK_INVALID) {
Brian Osman634624a2017-08-15 11:14:30 -0400207 fPushback = this->nextToken();
208 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700209 return fPushback;
210}
211
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400212bool Parser::checkNext(Token::Kind kind, Token* result) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400213 if (fPushback.fKind != Token::Kind::TK_INVALID && fPushback.fKind != kind) {
Brian Osman634624a2017-08-15 11:14:30 -0400214 return false;
215 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400216 Token next = this->nextToken();
217 if (next.fKind == kind) {
218 if (result) {
219 *result = next;
220 }
221 return true;
222 }
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400223 this->pushback(std::move(next));
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400224 return false;
225}
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500226
227bool Parser::expect(Token::Kind kind, const char* expected, Token* result) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700228 Token next = this->nextToken();
229 if (next.fKind == kind) {
230 if (result) {
Brian Osman634624a2017-08-15 11:14:30 -0400231 *result = std::move(next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700232 }
233 return true;
234 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700235 this->error(next, "expected " + String(expected) + ", but found '" +
236 this->text(next) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700237 return false;
238 }
239}
240
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700241StringFragment Parser::text(Token token) {
242 return StringFragment(fText + token.fOffset, token.fLength);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500243}
244
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700245void Parser::error(Token token, String msg) {
246 this->error(token.fOffset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -0700247}
248
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700249void Parser::error(int offset, String msg) {
250 fErrors.error(offset, msg);
251}
252
253bool Parser::isType(StringFragment name) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700254 return nullptr != fTypes[name];
255}
256
Ethan Nicholas11d53972016-11-28 11:23:23 -0500257/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
ethannicholas5961bc92016-10-12 06:39:56 -0700258 DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400259ASTNode::ID Parser::directive() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700260 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400261 if (!this->expect(Token::Kind::TK_DIRECTIVE, "a directive", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400262 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700263 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700264 StringFragment text = this->text(start);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400265 if (text == "#extension") {
ethannicholasb3058bd2016-07-01 08:22:01 -0700266 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400267 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400268 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700269 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400270 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400271 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700272 }
273 // FIXME: need to start paying attention to this token
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400274 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400275 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700276 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400277 RETURN_NODE(start.fOffset, ASTNode::Kind::kExtension, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700278 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700279 this->error(start, "unsupported directive '" + this->text(start) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400280 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700281 }
282}
283
Ethan Nicholas762466e2017-06-29 10:03:38 -0400284/* SECTION LBRACE (LPAREN IDENTIFIER RPAREN)? <any sequence of tokens with balanced braces>
285 RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400286ASTNode::ID Parser::section() {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400287 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400288 if (!this->expect(Token::Kind::TK_SECTION, "a section token", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400289 return ASTNode::ID::Invalid();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400290 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400291 StringFragment argument;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400292 if (this->peek().fKind == Token::Kind::TK_LPAREN) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400293 this->nextToken();
294 Token argToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400295 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &argToken)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400296 return ASTNode::ID::Invalid();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400297 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700298 argument = this->text(argToken);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400299 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400300 return ASTNode::ID::Invalid();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400301 }
302 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400303 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400304 return ASTNode::ID::Invalid();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400305 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400306 StringFragment text;
307 Token codeStart = this->nextRawToken();
308 size_t startOffset = codeStart.fOffset;
309 this->pushback(codeStart);
310 text.fChars = fText + startOffset;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400311 int level = 1;
312 for (;;) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700313 Token next = this->nextRawToken();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400314 switch (next.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400315 case Token::Kind::TK_LBRACE:
Ethan Nicholas762466e2017-06-29 10:03:38 -0400316 ++level;
317 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400318 case Token::Kind::TK_RBRACE:
Ethan Nicholas762466e2017-06-29 10:03:38 -0400319 --level;
320 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400321 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700322 this->error(start, "reached end of file while parsing section");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400323 return ASTNode::ID::Invalid();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400324 default:
325 break;
326 }
327 if (!level) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400328 text.fLength = next.fOffset - startOffset;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400329 break;
330 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400331 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700332 StringFragment name = this->text(start);
333 ++name.fChars;
334 --name.fLength;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400335 RETURN_NODE(start.fOffset, ASTNode::Kind::kSection,
336 ASTNode::SectionData(name, argument, text));
Ethan Nicholas762466e2017-06-29 10:03:38 -0400337}
338
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500339/* ENUM CLASS IDENTIFIER LBRACE (IDENTIFIER (EQ expression)? (COMMA IDENTIFIER (EQ expression))*)?
340 RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400341ASTNode::ID Parser::enumDeclaration() {
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500342 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400343 if (!this->expect(Token::Kind::TK_ENUM, "'enum'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400344 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500345 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400346 if (!this->expect(Token::Kind::TK_CLASS, "'class'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400347 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500348 }
349 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400350 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400351 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500352 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400353 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400354 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500355 }
356 fTypes.add(this->text(name), std::unique_ptr<Symbol>(new Type(this->text(name),
357 Type::kEnum_Kind)));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400358 CREATE_NODE(result, name.fOffset, ASTNode::Kind::kEnum, this->text(name));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400359 if (!this->checkNext(Token::Kind::TK_RBRACE)) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500360 Token id;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400361 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &id)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400362 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500363 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400364 if (this->checkNext(Token::Kind::TK_EQ)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400365 ASTNode::ID value = this->assignmentExpression();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500366 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400367 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500368 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400369 CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
370 getNode(child).addChild(value);
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500371 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400372 CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500373 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400374 while (!this->checkNext(Token::Kind::TK_RBRACE)) {
375 if (!this->expect(Token::Kind::TK_COMMA, "','")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400376 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500377 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400378 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &id)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400379 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500380 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400381 if (this->checkNext(Token::Kind::TK_EQ)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400382 ASTNode::ID value = this->assignmentExpression();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500383 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400384 return ASTNode::ID::Invalid();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500385 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400386 CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
387 getNode(child).addChild(value);
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500388 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400389 CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500390 }
391 }
392 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400393 this->expect(Token::Kind::TK_SEMICOLON, "';'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400394 return result;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500395}
396
397/* enumDeclaration | modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
ethannicholasb3058bd2016-07-01 08:22:01 -0700398 (COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400399ASTNode::ID Parser::declaration() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700400 Token lookahead = this->peek();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400401 if (lookahead.fKind == Token::Kind::TK_ENUM) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500402 return this->enumDeclaration();
403 }
404 Modifiers modifiers = this->modifiers();
405 lookahead = this->peek();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400406 if (lookahead.fKind == Token::Kind::TK_IDENTIFIER && !this->isType(this->text(lookahead))) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700407 // we have an identifier that's not a type, could be the start of an interface block
408 return this->interfaceBlock(modifiers);
409 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400410 if (lookahead.fKind == Token::Kind::TK_STRUCT) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700411 return this->structVarDeclaration(modifiers);
412 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400413 if (lookahead.fKind == Token::Kind::TK_SEMICOLON) {
ethannicholas5961bc92016-10-12 06:39:56 -0700414 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -0400415 RETURN_NODE(lookahead.fOffset, ASTNode::Kind::kModifiers, modifiers);
ethannicholas5961bc92016-10-12 06:39:56 -0700416 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400417 ASTNode::ID type = this->type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700418 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400419 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700420 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400421 if (getNode(type).getTypeData().fIsStructDeclaration &&
422 this->checkNext(Token::Kind::TK_SEMICOLON)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400423 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700424 }
425 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400426 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400427 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700428 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400429 if (this->checkNext(Token::Kind::TK_LPAREN)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400430 CREATE_NODE(result, name.fOffset, ASTNode::Kind::kFunction);
431 ASTNode::FunctionData fd(modifiers, this->text(name), 0);
432 getNode(result).addChild(type);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400433 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400434 for (;;) {
435 ASTNode::ID parameter = this->parameter();
436 if (!parameter) {
437 return ASTNode::ID::Invalid();
438 }
439 ++fd.fParameterCount;
440 getNode(result).addChild(parameter);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400441 if (!this->checkNext(Token::Kind::TK_COMMA)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400442 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700443 }
444 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700445 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400446 getNode(result).setFunctionData(fd);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400447 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400448 return ASTNode::ID::Invalid();
449 }
450 ASTNode::ID body;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400451 if (!this->checkNext(Token::Kind::TK_SEMICOLON)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700452 body = this->block();
453 if (!body) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400454 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700455 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400456 getNode(result).addChild(body);
ethannicholasb3058bd2016-07-01 08:22:01 -0700457 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400458 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700459 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400460 return this->varDeclarationEnd(modifiers, type, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700461 }
462}
463
464/* modifiers type IDENTIFIER varDeclarationEnd */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400465ASTNode::ID Parser::varDeclarations() {
Ethan Nicholas11d53972016-11-28 11:23:23 -0500466 Modifiers modifiers = this->modifiers();
Ethan Nicholasfc994162019-06-06 10:04:27 -0400467 ASTNode::ID type = this->type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700468 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400469 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700470 }
471 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400472 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400473 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700474 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400475 return this->varDeclarationEnd(modifiers, type, this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700476}
477
478/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400479ASTNode::ID Parser::structDeclaration() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400480 if (!this->expect(Token::Kind::TK_STRUCT, "'struct'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400481 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700482 }
483 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400484 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400485 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700486 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400487 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400488 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700489 }
490 std::vector<Type::Field> fields;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400491 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400492 ASTNode::ID decls = this->varDeclarations();
493 if (!decls) {
494 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700495 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400496 ASTNode& declsNode = getNode(decls);
497 auto type = (const Type*) fTypes[(declsNode.begin() + 1)->getTypeData().fName];
498 for (auto iter = declsNode.begin() + 2; iter != declsNode.end(); ++iter) {
499 ASTNode& var = *iter;
500 ASTNode::VarData vd = var.getVarData();
501 for (int j = vd.fSizeCount - 1; j >= 0; j--) {
502 const ASTNode& size = *(var.begin() + j);
503 if (!size || size.fKind != ASTNode::Kind::kInt) {
504 this->error(declsNode.fOffset, "array size in struct field must be a constant");
505 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700506 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400507 uint64_t columns = size.getInt();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400508 String name = type->name() + "[" + to_string(columns) + "]";
Ethan Nicholas91164d12019-05-15 15:29:54 -0400509 type = (Type*) fTypes.takeOwnership(std::unique_ptr<Symbol>(
510 new Type(name,
511 Type::kArray_Kind,
512 *type,
513 (int) columns)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700514 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400515 fields.push_back(Type::Field(declsNode.begin()->getModifiers(), vd.fName, type));
516 if (vd.fSizeCount ? (var.begin() + (vd.fSizeCount - 1))->fNext : var.fFirstChild) {
517 this->error(declsNode.fOffset, "initializers are not permitted on struct fields");
ethannicholasb3058bd2016-07-01 08:22:01 -0700518 }
519 }
520 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400521 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400522 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700523 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700524 fTypes.add(this->text(name), std::unique_ptr<Type>(new Type(name.fOffset, this->text(name),
525 fields)));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400526 RETURN_NODE(name.fOffset, ASTNode::Kind::kType,
527 ASTNode::TypeData(this->text(name), true, false));
ethannicholasb3058bd2016-07-01 08:22:01 -0700528}
529
530/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400531ASTNode::ID Parser::structVarDeclaration(Modifiers modifiers) {
532 ASTNode::ID type = this->structDeclaration();
ethannicholasb3058bd2016-07-01 08:22:01 -0700533 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400534 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700535 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400536 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400537 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400538 return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700539 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400540 this->expect(Token::Kind::TK_SEMICOLON, "';'");
Ethan Nicholasfc994162019-06-06 10:04:27 -0400541 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700542}
543
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400544/* (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)? (COMMA IDENTIFER
545 (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400546ASTNode::ID Parser::varDeclarationEnd(Modifiers mods, ASTNode::ID type, StringFragment name) {
547 CREATE_NODE(result, -1, ASTNode::Kind::kVarDeclarations);
548 CREATE_CHILD(modifiers, result, -1, ASTNode::Kind::kModifiers, mods);
549 getNode(result).addChild(type);
550 CREATE_NODE(currentVar, -1, ASTNode::Kind::kVarDeclaration);
551 ASTNode::VarData vd(name, 0);
552 getNode(result).addChild(currentVar);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400553 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
554 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400555 CREATE_EMPTY_CHILD(currentVar);
ethannicholasb3058bd2016-07-01 08:22:01 -0700556 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400557 ASTNode::ID size = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700558 if (!size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400559 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700560 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400561 getNode(currentVar).addChild(size);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400562 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400563 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700564 }
565 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400566 ++vd.fSizeCount;
ethannicholasb3058bd2016-07-01 08:22:01 -0700567 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400568 getNode(currentVar).setVarData(vd);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400569 if (this->checkNext(Token::Kind::TK_EQ)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400570 ASTNode::ID value = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700571 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400572 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700573 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400574 getNode(currentVar).addChild(value);
ethannicholasb3058bd2016-07-01 08:22:01 -0700575 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400576 while (this->checkNext(Token::Kind::TK_COMMA)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700577 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400578 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400579 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700580 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400581 currentVar = ASTNode::ID(fFile->fNodes.size());
582 vd = ASTNode::VarData(this->text(name), 0);
583 fFile->fNodes.emplace_back(&fFile->fNodes, -1, ASTNode::Kind::kVarDeclaration);
584 getNode(result).addChild(currentVar);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400585 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
586 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400587 CREATE_EMPTY_CHILD(currentVar);
ethannicholasb3058bd2016-07-01 08:22:01 -0700588 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400589 ASTNode::ID size = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700590 if (!size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400591 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700592 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400593 getNode(currentVar).addChild(size);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400594 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400595 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700596 }
597 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400598 ++vd.fSizeCount;
ethannicholasb3058bd2016-07-01 08:22:01 -0700599 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400600 getNode(currentVar).setVarData(vd);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400601 if (this->checkNext(Token::Kind::TK_EQ)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400602 ASTNode::ID value = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700603 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400604 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700605 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400606 getNode(currentVar).addChild(value);
ethannicholasb3058bd2016-07-01 08:22:01 -0700607 }
608 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400609 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400610 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700611 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400612 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700613}
614
615/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400616ASTNode::ID Parser::parameter() {
Ethan Nicholasc6f5e102017-03-31 14:53:17 -0400617 Modifiers modifiers = this->modifiersWithDefaults(0);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400618 ASTNode::ID type = this->type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700619 if (!type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400620 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700621 }
622 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400623 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400624 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700625 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400626 CREATE_NODE(result, name.fOffset, ASTNode::Kind::kParameter);
627 ASTNode::ParameterData pd(modifiers, this->text(name), 0);
628 getNode(result).addChild(type);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400629 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700630 Token sizeToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400631 if (!this->expect(Token::Kind::TK_INT_LITERAL, "a positive integer", &sizeToken)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400632 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700633 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400634 CREATE_CHILD(child, result, sizeToken.fOffset, ASTNode::Kind::kInt,
635 SkSL::stoi(this->text(sizeToken)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400636 if (!this->expect(Token::Kind::TK_RBRACKET, "']'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400637 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -0700638 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400639 ++pd.fSizeCount;
ethannicholasb3058bd2016-07-01 08:22:01 -0700640 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400641 getNode(result).setParameterData(pd);
642 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700643}
644
Ethan Nicholasd608c092017-10-26 09:30:08 -0400645/** EQ INT_LITERAL */
ethannicholasb3058bd2016-07-01 08:22:01 -0700646int Parser::layoutInt() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400647 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700648 return -1;
649 }
650 Token resultToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400651 if (this->expect(Token::Kind::TK_INT_LITERAL, "a non-negative integer", &resultToken)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700652 return SkSL::stoi(this->text(resultToken));
ethannicholasb3058bd2016-07-01 08:22:01 -0700653 }
654 return -1;
655}
656
Ethan Nicholasd608c092017-10-26 09:30:08 -0400657/** EQ IDENTIFIER */
658StringFragment Parser::layoutIdentifier() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400659 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
Ethan Nicholasd608c092017-10-26 09:30:08 -0400660 return StringFragment();
661 }
662 Token resultToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400663 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &resultToken)) {
Ethan Nicholasd608c092017-10-26 09:30:08 -0400664 return StringFragment();
665 }
666 return this->text(resultToken);
667}
668
669
Ethan Nicholas762466e2017-06-29 10:03:38 -0400670/** EQ <any sequence of tokens with balanced parentheses and no top-level comma> */
Ethan Nicholasfc994162019-06-06 10:04:27 -0400671StringFragment Parser::layoutCode() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400672 if (!this->expect(Token::Kind::TK_EQ, "'='")) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400673 return "";
674 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700675 Token start = this->nextRawToken();
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400676 this->pushback(start);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400677 StringFragment code;
678 code.fChars = fText + start.fOffset;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400679 int level = 1;
680 bool done = false;
681 while (!done) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700682 Token next = this->nextRawToken();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400683 switch (next.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400684 case Token::Kind::TK_LPAREN:
Ethan Nicholas762466e2017-06-29 10:03:38 -0400685 ++level;
686 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400687 case Token::Kind::TK_RPAREN:
Ethan Nicholas762466e2017-06-29 10:03:38 -0400688 --level;
689 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400690 case Token::Kind::TK_COMMA:
Ethan Nicholas762466e2017-06-29 10:03:38 -0400691 if (level == 1) {
692 done = true;
693 }
694 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400695 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700696 this->error(start, "reached end of file while parsing layout");
Ethan Nicholas6d71f492019-06-10 16:58:37 -0400697 return "";
Ethan Nicholas762466e2017-06-29 10:03:38 -0400698 default:
699 break;
700 }
701 if (!level) {
702 done = true;
703 }
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400704 if (done) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400705 code.fLength = next.fOffset - start.fOffset;
Ethan Nicholas08b79b72017-08-14 10:35:37 -0400706 this->pushback(std::move(next));
707 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400708 }
709 return code;
710}
711
712/** (EQ IDENTIFIER('identity'))? */
713Layout::Key Parser::layoutKey() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400714 if (this->peek().fKind == Token::Kind::TK_EQ) {
715 this->expect(Token::Kind::TK_EQ, "'='");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400716 Token key;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400717 if (this->expect(Token::Kind::TK_IDENTIFIER, "an identifer", &key)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700718 if (this->text(key) == "identity") {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400719 return Layout::kIdentity_Key;
720 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700721 this->error(key, "unsupported layout key");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400722 }
723 }
724 }
725 return Layout::kKey_Key;
726}
727
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400728Layout::CType Parser::layoutCType() {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400729 if (this->expect(Token::Kind::TK_EQ, "'='")) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400730 Token t = this->nextToken();
731 String text = this->text(t);
732 auto found = layoutTokens->find(text);
733 if (found != layoutTokens->end()) {
734 switch (found->second) {
Brian Osmanf28e55d2018-10-03 16:35:54 -0400735 case LayoutToken::SKPMCOLOR4F:
736 return Layout::CType::kSkPMColor4f;
Mike Reedb26b4e72020-01-22 14:31:21 -0500737 case LayoutToken::SKV4:
738 return Layout::CType::kSkV4;
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400739 case LayoutToken::SKRECT:
740 return Layout::CType::kSkRect;
741 case LayoutToken::SKIRECT:
742 return Layout::CType::kSkIRect;
743 case LayoutToken::SKPMCOLOR:
744 return Layout::CType::kSkPMColor;
Ethan Nicholasc1c686b2019-04-02 17:30:23 -0400745 case LayoutToken::BOOL:
746 return Layout::CType::kBool;
747 case LayoutToken::INT:
748 return Layout::CType::kInt32;
749 case LayoutToken::FLOAT:
750 return Layout::CType::kFloat;
Mike Reedb26b4e72020-01-22 14:31:21 -0500751 case LayoutToken::SKM44:
752 return Layout::CType::kSkM44;
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400753 default:
754 break;
755 }
756 }
757 this->error(t, "unsupported ctype");
758 }
759 return Layout::CType::kDefault;
760}
761
ethannicholas8ac838d2016-11-22 08:39:36 -0800762/* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500763Layout Parser::layout() {
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500764 int flags = 0;
ethannicholasb3058bd2016-07-01 08:22:01 -0700765 int location = -1;
Ethan Nicholas19671772016-11-28 16:30:17 -0500766 int offset = -1;
ethannicholasb3058bd2016-07-01 08:22:01 -0700767 int binding = -1;
768 int index = -1;
769 int set = -1;
770 int builtin = -1;
Greg Daniel64773e62016-11-22 09:44:03 -0500771 int inputAttachmentIndex = -1;
Ethan Nicholas11d53972016-11-28 11:23:23 -0500772 Layout::Format format = Layout::Format::kUnspecified;
Ethan Nicholas52cad152017-02-16 16:37:32 -0500773 Layout::Primitive primitive = Layout::kUnspecified_Primitive;
774 int maxVertices = -1;
775 int invocations = -1;
Brian Osmanf59a9612020-04-15 14:18:13 -0400776 StringFragment marker;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400777 StringFragment when;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400778 Layout::Key key = Layout::kNo_Key;
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400779 Layout::CType ctype = Layout::CType::kDefault;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400780 if (this->checkNext(Token::Kind::TK_LAYOUT)) {
781 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500782 return Layout(flags, location, offset, binding, index, set, builtin,
Brian Osmanf59a9612020-04-15 14:18:13 -0400783 inputAttachmentIndex, format, primitive, maxVertices, invocations, marker,
784 when, key, ctype);
ethannicholasb3058bd2016-07-01 08:22:01 -0700785 }
786 for (;;) {
787 Token t = this->nextToken();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700788 String text = this->text(t);
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400789 auto found = layoutTokens->find(text);
790 if (found != layoutTokens->end()) {
791 switch (found->second) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700792 case LayoutToken::LOCATION:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500793 location = this->layoutInt();
794 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700795 case LayoutToken::OFFSET:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500796 offset = this->layoutInt();
797 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700798 case LayoutToken::BINDING:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500799 binding = this->layoutInt();
800 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700801 case LayoutToken::INDEX:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500802 index = this->layoutInt();
803 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700804 case LayoutToken::SET:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500805 set = this->layoutInt();
806 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700807 case LayoutToken::BUILTIN:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500808 builtin = this->layoutInt();
809 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700810 case LayoutToken::INPUT_ATTACHMENT_INDEX:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500811 inputAttachmentIndex = this->layoutInt();
812 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700813 case LayoutToken::ORIGIN_UPPER_LEFT:
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500814 flags |= Layout::kOriginUpperLeft_Flag;
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500815 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700816 case LayoutToken::OVERRIDE_COVERAGE:
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500817 flags |= Layout::kOverrideCoverage_Flag;
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500818 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700819 case LayoutToken::BLEND_SUPPORT_ALL_EQUATIONS:
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500820 flags |= Layout::kBlendSupportAllEquations_Flag;
821 break;
822 case LayoutToken::BLEND_SUPPORT_MULTIPLY:
823 flags |= Layout::kBlendSupportMultiply_Flag;
824 break;
825 case LayoutToken::BLEND_SUPPORT_SCREEN:
826 flags |= Layout::kBlendSupportScreen_Flag;
827 break;
828 case LayoutToken::BLEND_SUPPORT_OVERLAY:
829 flags |= Layout::kBlendSupportOverlay_Flag;
830 break;
831 case LayoutToken::BLEND_SUPPORT_DARKEN:
832 flags |= Layout::kBlendSupportDarken_Flag;
833 break;
834 case LayoutToken::BLEND_SUPPORT_LIGHTEN:
835 flags |= Layout::kBlendSupportLighten_Flag;
836 break;
837 case LayoutToken::BLEND_SUPPORT_COLORDODGE:
838 flags |= Layout::kBlendSupportColorDodge_Flag;
839 break;
840 case LayoutToken::BLEND_SUPPORT_COLORBURN:
841 flags |= Layout::kBlendSupportColorBurn_Flag;
842 break;
843 case LayoutToken::BLEND_SUPPORT_HARDLIGHT:
844 flags |= Layout::kBlendSupportHardLight_Flag;
845 break;
846 case LayoutToken::BLEND_SUPPORT_SOFTLIGHT:
847 flags |= Layout::kBlendSupportSoftLight_Flag;
848 break;
849 case LayoutToken::BLEND_SUPPORT_DIFFERENCE:
850 flags |= Layout::kBlendSupportDifference_Flag;
851 break;
852 case LayoutToken::BLEND_SUPPORT_EXCLUSION:
853 flags |= Layout::kBlendSupportExclusion_Flag;
854 break;
855 case LayoutToken::BLEND_SUPPORT_HSL_HUE:
856 flags |= Layout::kBlendSupportHSLHue_Flag;
857 break;
858 case LayoutToken::BLEND_SUPPORT_HSL_SATURATION:
859 flags |= Layout::kBlendSupportHSLSaturation_Flag;
860 break;
861 case LayoutToken::BLEND_SUPPORT_HSL_COLOR:
862 flags |= Layout::kBlendSupportHSLColor_Flag;
863 break;
864 case LayoutToken::BLEND_SUPPORT_HSL_LUMINOSITY:
865 flags |= Layout::kBlendSupportHSLLuminosity_Flag;
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500866 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700867 case LayoutToken::PUSH_CONSTANT:
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500868 flags |= Layout::kPushConstant_Flag;
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500869 break;
Michael Ludwiga4275592018-08-31 10:52:47 -0400870 case LayoutToken::TRACKED:
871 flags |= Layout::kTracked_Flag;
872 break;
Brian Osmanb32d66b2020-04-30 17:12:03 -0400873 case LayoutToken::SRGB_UNPREMUL:
874 flags |= Layout::kSRGBUnpremul_Flag;
875 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700876 case LayoutToken::POINTS:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500877 primitive = Layout::kPoints_Primitive;
878 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700879 case LayoutToken::LINES:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500880 primitive = Layout::kLines_Primitive;
881 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700882 case LayoutToken::LINE_STRIP:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500883 primitive = Layout::kLineStrip_Primitive;
884 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700885 case LayoutToken::LINES_ADJACENCY:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500886 primitive = Layout::kLinesAdjacency_Primitive;
887 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700888 case LayoutToken::TRIANGLES:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500889 primitive = Layout::kTriangles_Primitive;
890 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700891 case LayoutToken::TRIANGLE_STRIP:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500892 primitive = Layout::kTriangleStrip_Primitive;
893 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700894 case LayoutToken::TRIANGLES_ADJACENCY:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500895 primitive = Layout::kTrianglesAdjacency_Primitive;
896 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700897 case LayoutToken::MAX_VERTICES:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500898 maxVertices = this->layoutInt();
899 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700900 case LayoutToken::INVOCATIONS:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500901 invocations = this->layoutInt();
902 break;
Brian Osmanf59a9612020-04-15 14:18:13 -0400903 case LayoutToken::MARKER:
904 marker = this->layoutCode();
905 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700906 case LayoutToken::WHEN:
Ethan Nicholas762466e2017-06-29 10:03:38 -0400907 when = this->layoutCode();
908 break;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700909 case LayoutToken::KEY:
Ethan Nicholas762466e2017-06-29 10:03:38 -0400910 key = this->layoutKey();
911 break;
Ethan Nicholasd608c092017-10-26 09:30:08 -0400912 case LayoutToken::CTYPE:
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400913 ctype = this->layoutCType();
914 break;
915 default:
916 this->error(t, ("'" + text + "' is not a valid layout qualifier").c_str());
Ethan Nicholasd608c092017-10-26 09:30:08 -0400917 break;
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500918 }
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400919 } else if (Layout::ReadFormat(text, &format)) {
Brian Salomon2a51de82016-11-16 12:06:01 -0500920 // AST::ReadFormat stored the result in 'format'.
ethannicholasb3058bd2016-07-01 08:22:01 -0700921 } else {
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400922 this->error(t, ("'" + text + "' is not a valid layout qualifier").c_str());
ethannicholasb3058bd2016-07-01 08:22:01 -0700923 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400924 if (this->checkNext(Token::Kind::TK_RPAREN)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700925 break;
926 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400927 if (!this->expect(Token::Kind::TK_COMMA, "','")) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700928 break;
929 }
930 }
931 }
Ethan Nicholas39204fd2017-11-27 13:12:30 -0500932 return Layout(flags, location, offset, binding, index, set, builtin, inputAttachmentIndex,
Brian Osmanf59a9612020-04-15 14:18:13 -0400933 format, primitive, maxVertices, invocations, marker, when, key, ctype);
ethannicholasb3058bd2016-07-01 08:22:01 -0700934}
935
Brian Salomonf9f45122016-11-29 11:59:17 -0500936/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE |
Ethan Nicholasa7ceb502019-01-11 10:31:48 -0500937 READONLY | WRITEONLY | COHERENT | VOLATILE | RESTRICT | BUFFER | PLS | PLSIN |
Brian Osman3c358422020-03-23 10:44:12 -0400938 PLSOUT | VARYING)* */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500939Modifiers Parser::modifiers() {
940 Layout layout = this->layout();
ethannicholasb3058bd2016-07-01 08:22:01 -0700941 int flags = 0;
942 for (;;) {
943 // TODO: handle duplicate / incompatible flags
944 switch (peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400945 case Token::Kind::TK_UNIFORM:
ethannicholasb3058bd2016-07-01 08:22:01 -0700946 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500947 flags |= Modifiers::kUniform_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700948 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400949 case Token::Kind::TK_CONST:
ethannicholasb3058bd2016-07-01 08:22:01 -0700950 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500951 flags |= Modifiers::kConst_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700952 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400953 case Token::Kind::TK_IN:
ethannicholasb3058bd2016-07-01 08:22:01 -0700954 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500955 flags |= Modifiers::kIn_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700956 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400957 case Token::Kind::TK_OUT:
ethannicholasb3058bd2016-07-01 08:22:01 -0700958 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500959 flags |= Modifiers::kOut_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700960 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400961 case Token::Kind::TK_INOUT:
ethannicholasb3058bd2016-07-01 08:22:01 -0700962 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500963 flags |= Modifiers::kIn_Flag;
964 flags |= Modifiers::kOut_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700965 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400966 case Token::Kind::TK_FLAT:
ethannicholasf789b382016-08-03 12:43:36 -0700967 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500968 flags |= Modifiers::kFlat_Flag;
ethannicholasf789b382016-08-03 12:43:36 -0700969 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400970 case Token::Kind::TK_NOPERSPECTIVE:
ethannicholasf789b382016-08-03 12:43:36 -0700971 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500972 flags |= Modifiers::kNoPerspective_Flag;
ethannicholasf789b382016-08-03 12:43:36 -0700973 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400974 case Token::Kind::TK_READONLY:
Brian Salomonf9f45122016-11-29 11:59:17 -0500975 this->nextToken();
976 flags |= Modifiers::kReadOnly_Flag;
977 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400978 case Token::Kind::TK_WRITEONLY:
Brian Salomonf9f45122016-11-29 11:59:17 -0500979 this->nextToken();
980 flags |= Modifiers::kWriteOnly_Flag;
981 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400982 case Token::Kind::TK_COHERENT:
Brian Salomonf9f45122016-11-29 11:59:17 -0500983 this->nextToken();
984 flags |= Modifiers::kCoherent_Flag;
985 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400986 case Token::Kind::TK_VOLATILE:
Brian Salomonf9f45122016-11-29 11:59:17 -0500987 this->nextToken();
988 flags |= Modifiers::kVolatile_Flag;
989 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400990 case Token::Kind::TK_RESTRICT:
Brian Salomonf9f45122016-11-29 11:59:17 -0500991 this->nextToken();
992 flags |= Modifiers::kRestrict_Flag;
993 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400994 case Token::Kind::TK_BUFFER:
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400995 this->nextToken();
996 flags |= Modifiers::kBuffer_Flag;
997 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400998 case Token::Kind::TK_HASSIDEEFFECTS:
Ethan Nicholascb670962017-04-20 19:31:52 -0400999 this->nextToken();
1000 flags |= Modifiers::kHasSideEffects_Flag;
1001 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001002 case Token::Kind::TK_PLS:
Ethan Nicholasa7ceb502019-01-11 10:31:48 -05001003 this->nextToken();
1004 flags |= Modifiers::kPLS_Flag;
1005 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001006 case Token::Kind::TK_PLSIN:
Ethan Nicholasa7ceb502019-01-11 10:31:48 -05001007 this->nextToken();
1008 flags |= Modifiers::kPLSIn_Flag;
1009 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001010 case Token::Kind::TK_PLSOUT:
Ethan Nicholasa7ceb502019-01-11 10:31:48 -05001011 this->nextToken();
1012 flags |= Modifiers::kPLSOut_Flag;
1013 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001014 case Token::Kind::TK_VARYING:
Brian Osman3c358422020-03-23 10:44:12 -04001015 this->nextToken();
1016 flags |= Modifiers::kVarying_Flag;
1017 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001018 default:
Ethan Nicholas11d53972016-11-28 11:23:23 -05001019 return Modifiers(layout, flags);
ethannicholasb3058bd2016-07-01 08:22:01 -07001020 }
1021 }
1022}
1023
Ethan Nicholas11d53972016-11-28 11:23:23 -05001024Modifiers Parser::modifiersWithDefaults(int defaultFlags) {
1025 Modifiers result = this->modifiers();
ethannicholasb3058bd2016-07-01 08:22:01 -07001026 if (!result.fFlags) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001027 return Modifiers(result.fLayout, defaultFlags);
ethannicholasb3058bd2016-07-01 08:22:01 -07001028 }
1029 return result;
1030}
1031
1032/* ifStatement | forStatement | doStatement | whileStatement | block | expression */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001033ASTNode::ID Parser::statement() {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001034 Token start = this->nextToken();
1035 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001036 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001037 return ASTNode::ID::Invalid();
1038 }
1039 this->pushback(start);
ethannicholasb3058bd2016-07-01 08:22:01 -07001040 switch (start.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001041 case Token::Kind::TK_IF: // fall through
1042 case Token::Kind::TK_STATIC_IF:
ethannicholasb3058bd2016-07-01 08:22:01 -07001043 return this->ifStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001044 case Token::Kind::TK_FOR:
ethannicholasb3058bd2016-07-01 08:22:01 -07001045 return this->forStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001046 case Token::Kind::TK_DO:
ethannicholasb3058bd2016-07-01 08:22:01 -07001047 return this->doStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001048 case Token::Kind::TK_WHILE:
ethannicholasb3058bd2016-07-01 08:22:01 -07001049 return this->whileStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001050 case Token::Kind::TK_SWITCH: // fall through
1051 case Token::Kind::TK_STATIC_SWITCH:
Ethan Nicholasaf197692017-02-27 13:26:45 -05001052 return this->switchStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001053 case Token::Kind::TK_RETURN:
ethannicholasb3058bd2016-07-01 08:22:01 -07001054 return this->returnStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001055 case Token::Kind::TK_BREAK:
ethannicholasb3058bd2016-07-01 08:22:01 -07001056 return this->breakStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001057 case Token::Kind::TK_CONTINUE:
ethannicholasb3058bd2016-07-01 08:22:01 -07001058 return this->continueStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001059 case Token::Kind::TK_DISCARD:
ethannicholasb3058bd2016-07-01 08:22:01 -07001060 return this->discardStatement();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001061 case Token::Kind::TK_LBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -07001062 return this->block();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001063 case Token::Kind::TK_SEMICOLON:
Ethan Nicholas11d53972016-11-28 11:23:23 -05001064 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001065 RETURN_NODE(start.fOffset, ASTNode::Kind::kBlock);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001066 case Token::Kind::TK_CONST:
Ethan Nicholasfc994162019-06-06 10:04:27 -04001067 return this->varDeclarations();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001068 case Token::Kind::TK_IDENTIFIER:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001069 if (this->isType(this->text(start))) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001070 return this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -07001071 }
John Stiles30212b72020-06-11 17:55:07 -04001072 [[fallthrough]];
ethannicholasb3058bd2016-07-01 08:22:01 -07001073 default:
1074 return this->expressionStatement();
Ethan Nicholas11d53972016-11-28 11:23:23 -05001075 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001076}
1077
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001078/* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* QUESTION? */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001079ASTNode::ID Parser::type() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001080 Token type;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001081 if (!this->expect(Token::Kind::TK_IDENTIFIER, "a type", &type)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001082 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001083 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001084 if (!this->isType(this->text(type))) {
1085 this->error(type, ("no type named '" + this->text(type) + "'").c_str());
Ethan Nicholasfc994162019-06-06 10:04:27 -04001086 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001087 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001088 CREATE_NODE(result, type.fOffset, ASTNode::Kind::kType);
1089 ASTNode::TypeData td(this->text(type), false, false);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001090 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
1091 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001092 SKSL_INT i;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001093 if (this->intLiteral(&i)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001094 CREATE_CHILD(child, result, -1, ASTNode::Kind::kInt, i);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001095 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001096 return ASTNode::ID::Invalid();
Ethan Nicholas50afc172017-02-16 14:49:57 -05001097 }
1098 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001099 CREATE_EMPTY_CHILD(result);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001100 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001101 this->expect(Token::Kind::TK_RBRACKET, "']'");
Ethan Nicholas50afc172017-02-16 14:49:57 -05001102 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001103 td.fIsNullable = this->checkNext(Token::Kind::TK_QUESTION);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001104 getNode(result).setTypeData(td);
1105 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001106}
1107
John Stiles57a996b2020-04-19 19:05:12 -07001108/* IDENTIFIER LBRACE
1109 varDeclaration+
1110 RBRACE (IDENTIFIER (LBRACKET expression? RBRACKET)*)? SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001111ASTNode::ID Parser::interfaceBlock(Modifiers mods) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001112 Token name;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001113 if (!this->expect(Token::Kind::TK_IDENTIFIER, "an identifier", &name)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001114 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001115 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001116 if (peek().fKind != Token::Kind::TK_LBRACE) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001117 // we only get into interfaceBlock if we found a top-level identifier which was not a type.
Ethan Nicholas11d53972016-11-28 11:23:23 -05001118 // 99% of the time, the user was not actually intending to create an interface block, so
ethannicholasb3058bd2016-07-01 08:22:01 -07001119 // it's better to report it as an unknown type
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001120 this->error(name, "no type named '" + this->text(name) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001121 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001122 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001123 CREATE_NODE(result, name.fOffset, ASTNode::Kind::kInterfaceBlock);
1124 ASTNode::InterfaceBlockData id(mods, this->text(name), 0, "", 0);
ethannicholasb3058bd2016-07-01 08:22:01 -07001125 this->nextToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001126 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001127 ASTNode::ID decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -07001128 if (!decl) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001129 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001130 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001131 getNode(result).addChild(decl);
1132 ++id.fDeclarationCount;
ethannicholasb3058bd2016-07-01 08:22:01 -07001133 }
John Stiles57a996b2020-04-19 19:05:12 -07001134 if (id.fDeclarationCount == 0) {
1135 this->error(name, "interface block '" + this->text(name) +
1136 "' must contain at least one member");
1137 return ASTNode::ID::Invalid();
1138 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001139 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001140 std::vector<ASTNode> sizes;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001141 StringFragment instanceName;
1142 Token instanceNameToken;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001143 if (this->checkNext(Token::Kind::TK_IDENTIFIER, &instanceNameToken)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001144 id.fInstanceName = this->text(instanceNameToken);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001145 while (this->checkNext(Token::Kind::TK_LBRACKET)) {
1146 if (this->peek().fKind != Token::Kind::TK_RBRACKET) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001147 ASTNode::ID size = this->expression();
Ethan Nicholas50afc172017-02-16 14:49:57 -05001148 if (!size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001149 return ASTNode::ID::Invalid();
Ethan Nicholas50afc172017-02-16 14:49:57 -05001150 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001151 getNode(result).addChild(size);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001152 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001153 CREATE_EMPTY_CHILD(result);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001154 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001155 ++id.fSizeCount;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001156 this->expect(Token::Kind::TK_RBRACKET, "']'");
Ethan Nicholas50afc172017-02-16 14:49:57 -05001157 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001158 instanceName = this->text(instanceNameToken);
ethannicholasb3058bd2016-07-01 08:22:01 -07001159 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001160 getNode(result).setInterfaceBlockData(id);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001161 this->expect(Token::Kind::TK_SEMICOLON, "';'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001162 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001163}
1164
1165/* IF LPAREN expression RPAREN statement (ELSE statement)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001166ASTNode::ID Parser::ifStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001167 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001168 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_IF, &start);
1169 if (!isStatic && !this->expect(Token::Kind::TK_IF, "'if'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001170 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001171 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001172 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kIf, isStatic);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001173 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001174 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001175 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001176 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001177 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001178 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001179 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001180 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001181 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001182 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001183 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001184 ASTNode::ID ifTrue = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001185 if (!ifTrue) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001186 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001187 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001188 getNode(result).addChild(ifTrue);
1189 ASTNode::ID ifFalse;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001190 if (this->checkNext(Token::Kind::TK_ELSE)) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001191 ifFalse = this->statement();
1192 if (!ifFalse) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001193 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001194 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001195 getNode(result).addChild(ifFalse);
ethannicholasb3058bd2016-07-01 08:22:01 -07001196 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001197 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001198}
1199
1200/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001201ASTNode::ID Parser::doStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001202 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001203 if (!this->expect(Token::Kind::TK_DO, "'do'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001204 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001205 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001206 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kDo);
1207 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001208 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001209 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001210 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001211 getNode(result).addChild(statement);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001212 if (!this->expect(Token::Kind::TK_WHILE, "'while'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001213 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001214 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001215 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001216 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001217 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001218 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001219 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001220 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001221 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001222 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001223 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001224 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001225 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001226 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001227 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001228 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001229 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001230}
1231
1232/* WHILE LPAREN expression RPAREN STATEMENT */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001233ASTNode::ID Parser::whileStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001234 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001235 if (!this->expect(Token::Kind::TK_WHILE, "'while'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001236 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001237 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001238 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001239 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001240 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001241 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kWhile);
1242 ASTNode::ID test = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001243 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001244 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001245 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001246 getNode(result).addChild(test);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001247 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001248 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001249 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001250 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001251 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001252 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001253 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001254 getNode(result).addChild(statement);
1255 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001256}
1257
Ethan Nicholasaf197692017-02-27 13:26:45 -05001258/* CASE expression COLON statement* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001259ASTNode::ID Parser::switchCase() {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001260 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001261 if (!this->expect(Token::Kind::TK_CASE, "'case'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001262 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001263 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001264 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kSwitchCase);
1265 ASTNode::ID value = this->expression();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001266 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001267 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001268 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001269 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001270 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001271 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001272 getNode(result).addChild(value);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001273 while (this->peek().fKind != Token::Kind::TK_RBRACE &&
1274 this->peek().fKind != Token::Kind::TK_CASE &&
1275 this->peek().fKind != Token::Kind::TK_DEFAULT) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001276 ASTNode::ID s = this->statement();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001277 if (!s) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001278 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001279 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001280 getNode(result).addChild(s);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001281 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001282 return result;
Ethan Nicholasaf197692017-02-27 13:26:45 -05001283}
1284
1285/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001286ASTNode::ID Parser::switchStatement() {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001287 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001288 bool isStatic = this->checkNext(Token::Kind::TK_STATIC_SWITCH, &start);
1289 if (!isStatic && !this->expect(Token::Kind::TK_SWITCH, "'switch'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001290 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001291 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001292 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001293 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001294 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001295 ASTNode::ID value = this->expression();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001296 if (!value) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001297 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001298 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001299 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001300 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001301 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001302 if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001303 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001304 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001305 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kSwitch, isStatic);
1306 getNode(result).addChild(value);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001307 while (this->peek().fKind == Token::Kind::TK_CASE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001308 ASTNode::ID c = this->switchCase();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001309 if (!c) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001310 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001311 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001312 getNode(result).addChild(c);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001313 }
1314 // Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
1315 // parts of the compiler may rely upon this assumption.
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001316 if (this->peek().fKind == Token::Kind::TK_DEFAULT) {
Ethan Nicholasaf197692017-02-27 13:26:45 -05001317 Token defaultStart;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001318 SkAssertResult(this->expect(Token::Kind::TK_DEFAULT, "'default'", &defaultStart));
1319 if (!this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001320 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001321 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001322 CREATE_CHILD(defaultCase, result, defaultStart.fOffset, ASTNode::Kind::kSwitchCase);
1323 CREATE_EMPTY_CHILD(defaultCase); // empty test to signify default case
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001324 while (this->peek().fKind != Token::Kind::TK_RBRACE) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001325 ASTNode::ID s = this->statement();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001326 if (!s) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001327 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001328 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001329 getNode(defaultCase).addChild(s);
Ethan Nicholasaf197692017-02-27 13:26:45 -05001330 }
Ethan Nicholasaf197692017-02-27 13:26:45 -05001331 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001332 if (!this->expect(Token::Kind::TK_RBRACE, "'}'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001333 return ASTNode::ID::Invalid();
Ethan Nicholasaf197692017-02-27 13:26:45 -05001334 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001335 return result;
Ethan Nicholasaf197692017-02-27 13:26:45 -05001336}
1337
Ethan Nicholas11d53972016-11-28 11:23:23 -05001338/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
ethannicholasb3058bd2016-07-01 08:22:01 -07001339 STATEMENT */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001340ASTNode::ID Parser::forStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001341 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001342 if (!this->expect(Token::Kind::TK_FOR, "'for'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001343 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001344 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001345 if (!this->expect(Token::Kind::TK_LPAREN, "'('")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001346 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001347 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001348 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kFor);
1349 ASTNode::ID initializer;
ethannicholasb3058bd2016-07-01 08:22:01 -07001350 Token nextToken = this->peek();
1351 switch (nextToken.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001352 case Token::Kind::TK_SEMICOLON:
ethannicholas22f939e2016-10-13 13:25:34 -07001353 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001354 CREATE_EMPTY_CHILD(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001355 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001356 case Token::Kind::TK_CONST: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001357 initializer = this->varDeclarations();
1358 if (!initializer) {
1359 return ASTNode::ID::Invalid();
ethannicholasa54401d2016-10-14 08:37:32 -07001360 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001361 getNode(result).addChild(initializer);
ethannicholasb3058bd2016-07-01 08:22:01 -07001362 break;
ethannicholasa54401d2016-10-14 08:37:32 -07001363 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001364 case Token::Kind::TK_IDENTIFIER: {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001365 if (this->isType(this->text(nextToken))) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001366 initializer = this->varDeclarations();
1367 if (!initializer) {
1368 return ASTNode::ID::Invalid();
ethannicholasa54401d2016-10-14 08:37:32 -07001369 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001370 getNode(result).addChild(initializer);
ethannicholasb3058bd2016-07-01 08:22:01 -07001371 break;
1372 }
John Stiles30212b72020-06-11 17:55:07 -04001373 [[fallthrough]];
1374 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001375 default:
1376 initializer = this->expressionStatement();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001377 if (!initializer) {
1378 return ASTNode::ID::Invalid();
1379 }
1380 getNode(result).addChild(initializer);
ethannicholasb3058bd2016-07-01 08:22:01 -07001381 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001382 ASTNode::ID test;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001383 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001384 test = this->expression();
1385 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001386 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001387 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001388 getNode(result).addChild(test);
1389 } else {
1390 CREATE_EMPTY_CHILD(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001391 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001392 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001393 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001394 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001395 ASTNode::ID next;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001396 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001397 next = this->expression();
1398 if (!next) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001399 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001400 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001401 getNode(result).addChild(next);
1402 } else {
1403 CREATE_EMPTY_CHILD(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001404 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001405 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001406 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001407 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001408 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001409 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001410 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001411 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001412 getNode(result).addChild(statement);
1413 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001414}
1415
1416/* RETURN expression? SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001417ASTNode::ID Parser::returnStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001418 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001419 if (!this->expect(Token::Kind::TK_RETURN, "'return'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001420 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001421 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001422 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kReturn);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001423 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001424 ASTNode::ID expression = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001425 if (!expression) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001426 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001427 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001428 getNode(result).addChild(expression);
ethannicholasb3058bd2016-07-01 08:22:01 -07001429 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001430 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001431 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001432 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001433 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001434}
1435
1436/* BREAK SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001437ASTNode::ID Parser::breakStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001438 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001439 if (!this->expect(Token::Kind::TK_BREAK, "'break'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001440 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001441 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001442 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001443 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001444 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001445 RETURN_NODE(start.fOffset, ASTNode::Kind::kBreak);
ethannicholasb3058bd2016-07-01 08:22:01 -07001446}
1447
1448/* CONTINUE SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001449ASTNode::ID Parser::continueStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001450 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001451 if (!this->expect(Token::Kind::TK_CONTINUE, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001452 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001453 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001454 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001455 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001456 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001457 RETURN_NODE(start.fOffset, ASTNode::Kind::kContinue);
ethannicholasb3058bd2016-07-01 08:22:01 -07001458}
1459
1460/* DISCARD SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001461ASTNode::ID Parser::discardStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001462 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001463 if (!this->expect(Token::Kind::TK_DISCARD, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001464 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001465 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001466 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001467 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001468 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001469 RETURN_NODE(start.fOffset, ASTNode::Kind::kDiscard);
ethannicholasb3058bd2016-07-01 08:22:01 -07001470}
1471
1472/* LBRACE statement* RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001473ASTNode::ID Parser::block() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001474 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001475 if (!this->expect(Token::Kind::TK_LBRACE, "'{'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001476 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001477 }
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001478 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001479 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001480 return ASTNode::ID::Invalid();
1481 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001482 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kBlock);
ethannicholasb3058bd2016-07-01 08:22:01 -07001483 for (;;) {
1484 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001485 case Token::Kind::TK_RBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -07001486 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001487 return result;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001488 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001489 this->error(this->peek(), "expected '}', but found end of file");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001490 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001491 default: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001492 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001493 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001494 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001495 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001496 getNode(result).addChild(statement);
ethannicholasb3058bd2016-07-01 08:22:01 -07001497 }
1498 }
1499 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001500 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001501}
1502
1503/* expression SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001504ASTNode::ID Parser::expressionStatement() {
1505 ASTNode::ID expr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001506 if (expr) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001507 if (this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001508 return expr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001509 }
1510 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001511 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001512}
1513
1514/* assignmentExpression (COMMA assignmentExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001515ASTNode::ID Parser::expression() {
1516 ASTNode::ID result = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001517 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001518 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001519 }
1520 Token t;
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001521 AutoDepth depth(this);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001522 while (this->checkNext(Token::Kind::TK_COMMA, &t)) {
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001523 if (!depth.increase()) {
1524 return ASTNode::ID::Invalid();
1525 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001526 ASTNode::ID right = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001527 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001528 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001529 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001530 CREATE_NODE(newResult, t.fOffset, ASTNode::Kind::kBinary, std::move(t));
1531 getNode(newResult).addChild(result);
1532 getNode(newResult).addChild(right);
1533 result = newResult;
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001534 }
1535 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001536}
1537
1538/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1539 BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1540 assignmentExpression)*
1541 */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001542ASTNode::ID Parser::assignmentExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001543 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001544 ASTNode::ID result = this->ternaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001545 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001546 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001547 }
1548 for (;;) {
1549 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001550 case Token::Kind::TK_EQ: // fall through
1551 case Token::Kind::TK_STAREQ: // fall through
1552 case Token::Kind::TK_SLASHEQ: // fall through
1553 case Token::Kind::TK_PERCENTEQ: // fall through
1554 case Token::Kind::TK_PLUSEQ: // fall through
1555 case Token::Kind::TK_MINUSEQ: // fall through
1556 case Token::Kind::TK_SHLEQ: // fall through
1557 case Token::Kind::TK_SHREQ: // fall through
1558 case Token::Kind::TK_BITWISEANDEQ: // fall through
1559 case Token::Kind::TK_BITWISEXOREQ: // fall through
1560 case Token::Kind::TK_BITWISEOREQ: // fall through
1561 case Token::Kind::TK_LOGICALANDEQ: // fall through
1562 case Token::Kind::TK_LOGICALXOREQ: // fall through
1563 case Token::Kind::TK_LOGICALOREQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001564 if (!depth.increase()) {
1565 return ASTNode::ID::Invalid();
1566 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001567 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001568 ASTNode::ID right = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001569 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001570 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001571 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001572 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1573 std::move(t));
1574 getNode(newResult).addChild(result);
1575 getNode(newResult).addChild(right);
1576 result = newResult;
1577 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001578 }
1579 default:
1580 return result;
1581 }
1582 }
1583}
1584
1585/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001586ASTNode::ID Parser::ternaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001587 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001588 ASTNode::ID base = this->logicalOrExpression();
1589 if (!base) {
1590 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001591 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001592 if (this->checkNext(Token::Kind::TK_QUESTION)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001593 if (!depth.increase()) {
1594 return ASTNode::ID::Invalid();
1595 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001596 ASTNode::ID trueExpr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001597 if (!trueExpr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001598 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001599 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001600 if (this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001601 ASTNode::ID falseExpr = this->assignmentExpression();
1602 if (!falseExpr) {
1603 return ASTNode::ID::Invalid();
1604 }
1605 CREATE_NODE(ternary, getNode(base).fOffset, ASTNode::Kind::kTernary);
1606 getNode(ternary).addChild(base);
1607 getNode(ternary).addChild(trueExpr);
1608 getNode(ternary).addChild(falseExpr);
1609 return ternary;
ethannicholasb3058bd2016-07-01 08:22:01 -07001610 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001611 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001612 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001613 return base;
ethannicholasb3058bd2016-07-01 08:22:01 -07001614}
1615
1616/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001617ASTNode::ID Parser::logicalOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001618 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001619 ASTNode::ID result = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001620 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001621 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001622 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001623 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001624 while (this->checkNext(Token::Kind::TK_LOGICALOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001625 if (!depth.increase()) {
1626 return ASTNode::ID::Invalid();
1627 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001628 ASTNode::ID right = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001629 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001630 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001631 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001632 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1633 getNode(newResult).addChild(result);
1634 getNode(newResult).addChild(right);
1635 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001636 }
1637 return result;
1638}
1639
1640/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001641ASTNode::ID Parser::logicalXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001642 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001643 ASTNode::ID result = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001644 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001645 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001646 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001647 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001648 while (this->checkNext(Token::Kind::TK_LOGICALXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001649 if (!depth.increase()) {
1650 return ASTNode::ID::Invalid();
1651 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001652 ASTNode::ID right = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001653 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001654 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001655 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001656 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1657 getNode(newResult).addChild(result);
1658 getNode(newResult).addChild(right);
1659 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001660 }
1661 return result;
1662}
1663
1664/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001665ASTNode::ID Parser::logicalAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001666 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001667 ASTNode::ID result = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001668 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001669 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001670 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001671 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001672 while (this->checkNext(Token::Kind::TK_LOGICALAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001673 if (!depth.increase()) {
1674 return ASTNode::ID::Invalid();
1675 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001676 ASTNode::ID right = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001677 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001678 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001679 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001680 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1681 getNode(newResult).addChild(result);
1682 getNode(newResult).addChild(right);
1683 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001684 }
1685 return result;
1686}
1687
1688/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001689ASTNode::ID Parser::bitwiseOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001690 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001691 ASTNode::ID result = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001692 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001693 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001694 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001695 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001696 while (this->checkNext(Token::Kind::TK_BITWISEOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001697 if (!depth.increase()) {
1698 return ASTNode::ID::Invalid();
1699 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001700 ASTNode::ID right = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001701 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001702 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001703 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001704 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1705 getNode(newResult).addChild(result);
1706 getNode(newResult).addChild(right);
1707 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001708 }
1709 return result;
1710}
1711
1712/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001713ASTNode::ID Parser::bitwiseXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001714 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001715 ASTNode::ID result = this->bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001716 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001717 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001718 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001719 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001720 while (this->checkNext(Token::Kind::TK_BITWISEXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001721 if (!depth.increase()) {
1722 return ASTNode::ID::Invalid();
1723 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001724 ASTNode::ID right = this->bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001725 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001726 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001727 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001728 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1729 getNode(newResult).addChild(result);
1730 getNode(newResult).addChild(right);
1731 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001732 }
1733 return result;
1734}
1735
1736/* equalityExpression (BITWISEAND equalityExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001737ASTNode::ID Parser::bitwiseAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001738 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001739 ASTNode::ID result = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001740 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001741 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001742 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001743 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001744 while (this->checkNext(Token::Kind::TK_BITWISEAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001745 if (!depth.increase()) {
1746 return ASTNode::ID::Invalid();
1747 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001748 ASTNode::ID right = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001749 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001750 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001751 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001752 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1753 getNode(newResult).addChild(result);
1754 getNode(newResult).addChild(right);
1755 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001756 }
1757 return result;
1758}
1759
1760/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001761ASTNode::ID Parser::equalityExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001762 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001763 ASTNode::ID result = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001764 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001765 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001766 }
1767 for (;;) {
1768 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001769 case Token::Kind::TK_EQEQ: // fall through
1770 case Token::Kind::TK_NEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001771 if (!depth.increase()) {
1772 return ASTNode::ID::Invalid();
1773 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001774 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001775 ASTNode::ID right = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001776 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001777 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001778 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001779 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1780 std::move(t));
1781 getNode(newResult).addChild(result);
1782 getNode(newResult).addChild(right);
1783 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001784 break;
1785 }
1786 default:
1787 return result;
1788 }
1789 }
1790}
1791
1792/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001793ASTNode::ID Parser::relationalExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001794 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001795 ASTNode::ID result = this->shiftExpression();
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 (;;) {
1800 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001801 case Token::Kind::TK_LT: // fall through
1802 case Token::Kind::TK_GT: // fall through
1803 case Token::Kind::TK_LTEQ: // fall through
1804 case Token::Kind::TK_GTEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001805 if (!depth.increase()) {
1806 return ASTNode::ID::Invalid();
1807 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001808 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001809 ASTNode::ID right = this->shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001810 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001811 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001812 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001813 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1814 std::move(t));
1815 getNode(newResult).addChild(result);
1816 getNode(newResult).addChild(right);
1817 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001818 break;
1819 }
1820 default:
1821 return result;
1822 }
1823 }
1824}
1825
1826/* additiveExpression ((SHL | SHR) additiveExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001827ASTNode::ID Parser::shiftExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001828 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001829 ASTNode::ID result = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001830 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001831 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001832 }
1833 for (;;) {
1834 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001835 case Token::Kind::TK_SHL: // fall through
1836 case Token::Kind::TK_SHR: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001837 if (!depth.increase()) {
1838 return ASTNode::ID::Invalid();
1839 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001840 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001841 ASTNode::ID right = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001842 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001843 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001844 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001845 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1846 std::move(t));
1847 getNode(newResult).addChild(result);
1848 getNode(newResult).addChild(right);
1849 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001850 break;
1851 }
1852 default:
1853 return result;
1854 }
1855 }
1856}
1857
1858/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001859ASTNode::ID Parser::additiveExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001860 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001861 ASTNode::ID result = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001862 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001863 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001864 }
1865 for (;;) {
1866 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001867 case Token::Kind::TK_PLUS: // fall through
1868 case Token::Kind::TK_MINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001869 if (!depth.increase()) {
1870 return ASTNode::ID::Invalid();
1871 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001872 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001873 ASTNode::ID right = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001874 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001875 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001876 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001877 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1878 std::move(t));
1879 getNode(newResult).addChild(result);
1880 getNode(newResult).addChild(right);
1881 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001882 break;
1883 }
1884 default:
1885 return result;
1886 }
1887 }
1888}
1889
1890/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001891ASTNode::ID Parser::multiplicativeExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001892 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001893 ASTNode::ID result = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001894 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001895 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001896 }
1897 for (;;) {
1898 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001899 case Token::Kind::TK_STAR: // fall through
1900 case Token::Kind::TK_SLASH: // fall through
1901 case Token::Kind::TK_PERCENT: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001902 if (!depth.increase()) {
1903 return ASTNode::ID::Invalid();
1904 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001905 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001906 ASTNode::ID right = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001907 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001908 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001909 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001910 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1911 std::move(t));
1912 getNode(newResult).addChild(result);
1913 getNode(newResult).addChild(right);
1914 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001915 break;
1916 }
1917 default:
1918 return result;
1919 }
1920 }
1921}
1922
1923/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001924ASTNode::ID Parser::unaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001925 AutoDepth depth(this);
ethannicholasb3058bd2016-07-01 08:22:01 -07001926 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001927 case Token::Kind::TK_PLUS: // fall through
1928 case Token::Kind::TK_MINUS: // fall through
1929 case Token::Kind::TK_LOGICALNOT: // fall through
1930 case Token::Kind::TK_BITWISENOT: // fall through
1931 case Token::Kind::TK_PLUSPLUS: // fall through
1932 case Token::Kind::TK_MINUSMINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001933 if (!depth.increase()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001934 return ASTNode::ID::Invalid();
Ethan Nicholas6dcc3252019-02-20 15:18:36 -05001935 }
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001936 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001937 ASTNode::ID expr = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001938 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001939 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001940 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001941 CREATE_NODE(result, t.fOffset, ASTNode::Kind::kPrefix, std::move(t));
1942 getNode(result).addChild(expr);
1943 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001944 }
1945 default:
1946 return this->postfixExpression();
1947 }
1948}
1949
1950/* term suffix* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001951ASTNode::ID Parser::postfixExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001952 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001953 ASTNode::ID result = this->term();
ethannicholasb3058bd2016-07-01 08:22:01 -07001954 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001955 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001956 }
1957 for (;;) {
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001958 Token t = this->peek();
1959 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001960 case Token::Kind::TK_FLOAT_LITERAL:
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001961 if (this->text(t)[0] != '.') {
1962 return result;
1963 }
John Stiles30212b72020-06-11 17:55:07 -04001964 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001965 case Token::Kind::TK_LBRACKET:
1966 case Token::Kind::TK_DOT:
1967 case Token::Kind::TK_LPAREN:
1968 case Token::Kind::TK_PLUSPLUS:
1969 case Token::Kind::TK_MINUSMINUS:
1970 case Token::Kind::TK_COLONCOLON:
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001971 if (!depth.increase()) {
1972 return ASTNode::ID::Invalid();
1973 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001974 result = this->suffix(result);
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001975 if (!result) {
1976 return ASTNode::ID::Invalid();
1977 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001978 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001979 default:
1980 return result;
1981 }
1982 }
1983}
1984
Ethan Nicholas11d53972016-11-28 11:23:23 -05001985/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
Ethan Nicholase455f652019-09-13 12:52:55 -04001986 PLUSPLUS | MINUSMINUS | COLONCOLON IDENTIFIER | FLOAT_LITERAL [IDENTIFIER] */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001987ASTNode::ID Parser::suffix(ASTNode::ID base) {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001988 SkASSERT(base);
ethannicholasb3058bd2016-07-01 08:22:01 -07001989 Token next = this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001990 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001991 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001992 return ASTNode::ID::Invalid();
1993 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001994 switch (next.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001995 case Token::Kind::TK_LBRACKET: {
1996 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001997 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kIndex);
1998 getNode(result).addChild(base);
1999 return result;
ethannicholas5961bc92016-10-12 06:39:56 -07002000 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002001 ASTNode::ID e = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07002002 if (!e) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002003 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07002004 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002005 this->expect(Token::Kind::TK_RBRACKET, "']' to complete array access expression");
Ethan Nicholasfc994162019-06-06 10:04:27 -04002006 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kIndex);
2007 getNode(result).addChild(base);
2008 getNode(result).addChild(e);
2009 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07002010 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002011 case Token::Kind::TK_DOT: // fall through
2012 case Token::Kind::TK_COLONCOLON: {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002013 int offset = this->peek().fOffset;
2014 StringFragment text;
ethannicholasb3058bd2016-07-01 08:22:01 -07002015 if (this->identifier(&text)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002016 CREATE_NODE(result, offset, ASTNode::Kind::kField, std::move(text));
2017 getNode(result).addChild(base);
2018 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07002019 }
John Stiles30212b72020-06-11 17:55:07 -04002020 [[fallthrough]]; // FIXME(ethannicholas)
Ethan Nicholase455f652019-09-13 12:52:55 -04002021 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002022 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholase455f652019-09-13 12:52:55 -04002023 // Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
2024 // floating point literals, possibly followed by an identifier. Handle that here.
2025 StringFragment field = this->text(next);
2026 SkASSERT(field.fChars[0] == '.');
2027 ++field.fChars;
2028 --field.fLength;
2029 for (size_t i = 0; i < field.fLength; ++i) {
2030 if (field.fChars[i] != '0' && field.fChars[i] != '1') {
2031 this->error(next, "invalid swizzle");
2032 return ASTNode::ID::Invalid();
2033 }
2034 }
2035 // use the next *raw* token so we don't ignore whitespace - we only care about
2036 // identifiers that directly follow the float
2037 Token id = this->nextRawToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002038 if (id.fKind == Token::Kind::TK_IDENTIFIER) {
Ethan Nicholase455f652019-09-13 12:52:55 -04002039 field.fLength += id.fLength;
2040 } else {
2041 this->pushback(id);
2042 }
2043 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kField, field);
2044 getNode(result).addChild(base);
2045 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07002046 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002047 case Token::Kind::TK_LPAREN: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002048 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kCall);
2049 getNode(result).addChild(base);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002050 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002051 for (;;) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002052 ASTNode::ID expr = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07002053 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002054 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07002055 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002056 getNode(result).addChild(expr);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002057 if (!this->checkNext(Token::Kind::TK_COMMA)) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002058 break;
2059 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002060 }
2061 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002062 this->expect(Token::Kind::TK_RPAREN, "')' to complete function parameters");
Ethan Nicholasfc994162019-06-06 10:04:27 -04002063 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07002064 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002065 case Token::Kind::TK_PLUSPLUS: // fall through
2066 case Token::Kind::TK_MINUSMINUS: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002067 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kPostfix, next);
2068 getNode(result).addChild(base);
2069 return result;
2070 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002071 default: {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04002072 this->error(next, "expected expression suffix, but found '" + this->text(next) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04002073 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07002074 }
2075 }
2076}
2077
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05002078/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | NULL_LITERAL | '(' expression ')' */
Ethan Nicholasfc994162019-06-06 10:04:27 -04002079ASTNode::ID Parser::term() {
ethannicholasb3058bd2016-07-01 08:22:01 -07002080 Token t = this->peek();
2081 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002082 case Token::Kind::TK_IDENTIFIER: {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002083 StringFragment text;
ethannicholasb3058bd2016-07-01 08:22:01 -07002084 if (this->identifier(&text)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002085 RETURN_NODE(t.fOffset, ASTNode::Kind::kIdentifier, std::move(text));
ethannicholasb3058bd2016-07-01 08:22:01 -07002086 }
John Stiles30212b72020-06-11 17:55:07 -04002087 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07002088 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002089 case Token::Kind::TK_INT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002090 SKSL_INT i;
ethannicholasb3058bd2016-07-01 08:22:01 -07002091 if (this->intLiteral(&i)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002092 RETURN_NODE(t.fOffset, ASTNode::Kind::kInt, i);
ethannicholasb3058bd2016-07-01 08:22:01 -07002093 }
2094 break;
2095 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002096 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002097 SKSL_FLOAT f;
ethannicholasb3058bd2016-07-01 08:22:01 -07002098 if (this->floatLiteral(&f)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002099 RETURN_NODE(t.fOffset, ASTNode::Kind::kFloat, f);
ethannicholasb3058bd2016-07-01 08:22:01 -07002100 }
2101 break;
2102 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002103 case Token::Kind::TK_TRUE_LITERAL: // fall through
2104 case Token::Kind::TK_FALSE_LITERAL: {
ethannicholasb3058bd2016-07-01 08:22:01 -07002105 bool b;
2106 if (this->boolLiteral(&b)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002107 RETURN_NODE(t.fOffset, ASTNode::Kind::kBool, b);
ethannicholasb3058bd2016-07-01 08:22:01 -07002108 }
2109 break;
2110 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002111 case Token::Kind::TK_NULL_LITERAL:
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05002112 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04002113 RETURN_NODE(t.fOffset, ASTNode::Kind::kNull);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002114 case Token::Kind::TK_LPAREN: {
ethannicholasb3058bd2016-07-01 08:22:01 -07002115 this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04002116 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04002117 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04002118 return ASTNode::ID::Invalid();
2119 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002120 ASTNode::ID result = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07002121 if (result) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002122 this->expect(Token::Kind::TK_RPAREN, "')' to complete expression");
Ethan Nicholasfc994162019-06-06 10:04:27 -04002123 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07002124 }
2125 break;
2126 }
2127 default:
2128 this->nextToken();
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04002129 this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002130 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002131 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07002132}
2133
2134/* INT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04002135bool Parser::intLiteral(SKSL_INT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002136 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002137 if (this->expect(Token::Kind::TK_INT_LITERAL, "integer literal", &t)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002138 *dest = SkSL::stol(this->text(t));
ethannicholasb3058bd2016-07-01 08:22:01 -07002139 return true;
2140 }
2141 return false;
2142}
2143
2144/* FLOAT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04002145bool Parser::floatLiteral(SKSL_FLOAT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002146 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002147 if (this->expect(Token::Kind::TK_FLOAT_LITERAL, "float literal", &t)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002148 *dest = SkSL::stod(this->text(t));
ethannicholasb3058bd2016-07-01 08:22:01 -07002149 return true;
2150 }
2151 return false;
2152}
2153
2154/* TRUE_LITERAL | FALSE_LITERAL */
2155bool Parser::boolLiteral(bool* dest) {
2156 Token t = this->nextToken();
2157 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002158 case Token::Kind::TK_TRUE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07002159 *dest = true;
2160 return true;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002161 case Token::Kind::TK_FALSE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07002162 *dest = false;
2163 return true;
2164 default:
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04002165 this->error(t, "expected 'true' or 'false', but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002166 return false;
2167 }
2168}
2169
2170/* IDENTIFIER */
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002171bool Parser::identifier(StringFragment* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002172 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002173 if (this->expect(Token::Kind::TK_IDENTIFIER, "identifier", &t)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002174 *dest = this->text(t);
ethannicholasb3058bd2016-07-01 08:22:01 -07002175 return true;
2176 }
2177 return false;
2178}
2179
2180} // namespace