blob: 3f7df7997fdfaee18ab89287d08df91eee52810d [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 }
1072 // fall through
1073 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 }
ethannicholasa54401d2016-10-14 08:37:32 -07001373 } // fall through
ethannicholasb3058bd2016-07-01 08:22:01 -07001374 default:
1375 initializer = this->expressionStatement();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001376 if (!initializer) {
1377 return ASTNode::ID::Invalid();
1378 }
1379 getNode(result).addChild(initializer);
ethannicholasb3058bd2016-07-01 08:22:01 -07001380 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001381 ASTNode::ID test;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001382 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001383 test = this->expression();
1384 if (!test) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001385 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001386 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001387 getNode(result).addChild(test);
1388 } else {
1389 CREATE_EMPTY_CHILD(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001390 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001391 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001392 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001393 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001394 ASTNode::ID next;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001395 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001396 next = this->expression();
1397 if (!next) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001398 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001399 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001400 getNode(result).addChild(next);
1401 } else {
1402 CREATE_EMPTY_CHILD(result);
ethannicholasb3058bd2016-07-01 08:22:01 -07001403 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001404 if (!this->expect(Token::Kind::TK_RPAREN, "')'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001405 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001406 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001407 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001408 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001409 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001410 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001411 getNode(result).addChild(statement);
1412 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001413}
1414
1415/* RETURN expression? SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001416ASTNode::ID Parser::returnStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001417 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001418 if (!this->expect(Token::Kind::TK_RETURN, "'return'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001419 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001420 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001421 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kReturn);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001422 if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001423 ASTNode::ID expression = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001424 if (!expression) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001425 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001426 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001427 getNode(result).addChild(expression);
ethannicholasb3058bd2016-07-01 08:22:01 -07001428 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001429 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001430 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001431 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001432 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001433}
1434
1435/* BREAK SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001436ASTNode::ID Parser::breakStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001437 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001438 if (!this->expect(Token::Kind::TK_BREAK, "'break'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001439 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001440 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001441 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001442 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001443 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001444 RETURN_NODE(start.fOffset, ASTNode::Kind::kBreak);
ethannicholasb3058bd2016-07-01 08:22:01 -07001445}
1446
1447/* CONTINUE SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001448ASTNode::ID Parser::continueStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001449 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001450 if (!this->expect(Token::Kind::TK_CONTINUE, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001451 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001452 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001453 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001454 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001455 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001456 RETURN_NODE(start.fOffset, ASTNode::Kind::kContinue);
ethannicholasb3058bd2016-07-01 08:22:01 -07001457}
1458
1459/* DISCARD SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001460ASTNode::ID Parser::discardStatement() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001461 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001462 if (!this->expect(Token::Kind::TK_DISCARD, "'continue'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001463 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001464 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001465 if (!this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001466 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001467 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001468 RETURN_NODE(start.fOffset, ASTNode::Kind::kDiscard);
ethannicholasb3058bd2016-07-01 08:22:01 -07001469}
1470
1471/* LBRACE statement* RBRACE */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001472ASTNode::ID Parser::block() {
ethannicholasb3058bd2016-07-01 08:22:01 -07001473 Token start;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001474 if (!this->expect(Token::Kind::TK_LBRACE, "'{'", &start)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001475 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001476 }
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001477 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001478 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001479 return ASTNode::ID::Invalid();
1480 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001481 CREATE_NODE(result, start.fOffset, ASTNode::Kind::kBlock);
ethannicholasb3058bd2016-07-01 08:22:01 -07001482 for (;;) {
1483 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001484 case Token::Kind::TK_RBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -07001485 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001486 return result;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001487 case Token::Kind::TK_END_OF_FILE:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001488 this->error(this->peek(), "expected '}', but found end of file");
Ethan Nicholasfc994162019-06-06 10:04:27 -04001489 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001490 default: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001491 ASTNode::ID statement = this->statement();
ethannicholasb3058bd2016-07-01 08:22:01 -07001492 if (!statement) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001493 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001494 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001495 getNode(result).addChild(statement);
ethannicholasb3058bd2016-07-01 08:22:01 -07001496 }
1497 }
1498 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001499 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001500}
1501
1502/* expression SEMICOLON */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001503ASTNode::ID Parser::expressionStatement() {
1504 ASTNode::ID expr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001505 if (expr) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001506 if (this->expect(Token::Kind::TK_SEMICOLON, "';'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001507 return expr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001508 }
1509 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001510 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001511}
1512
1513/* assignmentExpression (COMMA assignmentExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001514ASTNode::ID Parser::expression() {
1515 ASTNode::ID result = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001516 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001517 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001518 }
1519 Token t;
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001520 AutoDepth depth(this);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001521 while (this->checkNext(Token::Kind::TK_COMMA, &t)) {
Ethan Nicholasb67d0562020-04-30 16:10:00 -04001522 if (!depth.increase()) {
1523 return ASTNode::ID::Invalid();
1524 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001525 ASTNode::ID right = this->assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001526 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001527 return ASTNode::ID::Invalid();
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001528 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001529 CREATE_NODE(newResult, t.fOffset, ASTNode::Kind::kBinary, std::move(t));
1530 getNode(newResult).addChild(result);
1531 getNode(newResult).addChild(right);
1532 result = newResult;
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001533 }
1534 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001535}
1536
1537/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1538 BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1539 assignmentExpression)*
1540 */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001541ASTNode::ID Parser::assignmentExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001542 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001543 ASTNode::ID result = this->ternaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001544 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001545 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001546 }
1547 for (;;) {
1548 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001549 case Token::Kind::TK_EQ: // fall through
1550 case Token::Kind::TK_STAREQ: // fall through
1551 case Token::Kind::TK_SLASHEQ: // fall through
1552 case Token::Kind::TK_PERCENTEQ: // fall through
1553 case Token::Kind::TK_PLUSEQ: // fall through
1554 case Token::Kind::TK_MINUSEQ: // fall through
1555 case Token::Kind::TK_SHLEQ: // fall through
1556 case Token::Kind::TK_SHREQ: // fall through
1557 case Token::Kind::TK_BITWISEANDEQ: // fall through
1558 case Token::Kind::TK_BITWISEXOREQ: // fall through
1559 case Token::Kind::TK_BITWISEOREQ: // fall through
1560 case Token::Kind::TK_LOGICALANDEQ: // fall through
1561 case Token::Kind::TK_LOGICALXOREQ: // fall through
1562 case Token::Kind::TK_LOGICALOREQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001563 if (!depth.increase()) {
1564 return ASTNode::ID::Invalid();
1565 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001566 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001567 ASTNode::ID right = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001568 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001569 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001570 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001571 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1572 std::move(t));
1573 getNode(newResult).addChild(result);
1574 getNode(newResult).addChild(right);
1575 result = newResult;
1576 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001577 }
1578 default:
1579 return result;
1580 }
1581 }
1582}
1583
1584/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001585ASTNode::ID Parser::ternaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001586 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001587 ASTNode::ID base = this->logicalOrExpression();
1588 if (!base) {
1589 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001590 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001591 if (this->checkNext(Token::Kind::TK_QUESTION)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001592 if (!depth.increase()) {
1593 return ASTNode::ID::Invalid();
1594 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001595 ASTNode::ID trueExpr = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001596 if (!trueExpr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001597 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001598 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001599 if (this->expect(Token::Kind::TK_COLON, "':'")) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001600 ASTNode::ID falseExpr = this->assignmentExpression();
1601 if (!falseExpr) {
1602 return ASTNode::ID::Invalid();
1603 }
1604 CREATE_NODE(ternary, getNode(base).fOffset, ASTNode::Kind::kTernary);
1605 getNode(ternary).addChild(base);
1606 getNode(ternary).addChild(trueExpr);
1607 getNode(ternary).addChild(falseExpr);
1608 return ternary;
ethannicholasb3058bd2016-07-01 08:22:01 -07001609 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001610 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001611 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001612 return base;
ethannicholasb3058bd2016-07-01 08:22:01 -07001613}
1614
1615/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001616ASTNode::ID Parser::logicalOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001617 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001618 ASTNode::ID result = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001619 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001620 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001621 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001622 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001623 while (this->checkNext(Token::Kind::TK_LOGICALOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001624 if (!depth.increase()) {
1625 return ASTNode::ID::Invalid();
1626 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001627 ASTNode::ID right = this->logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001628 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001629 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001630 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001631 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1632 getNode(newResult).addChild(result);
1633 getNode(newResult).addChild(right);
1634 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001635 }
1636 return result;
1637}
1638
1639/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001640ASTNode::ID Parser::logicalXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001641 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001642 ASTNode::ID result = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001643 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001644 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001645 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001646 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001647 while (this->checkNext(Token::Kind::TK_LOGICALXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001648 if (!depth.increase()) {
1649 return ASTNode::ID::Invalid();
1650 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001651 ASTNode::ID right = this->logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001652 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001653 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001654 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001655 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1656 getNode(newResult).addChild(result);
1657 getNode(newResult).addChild(right);
1658 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001659 }
1660 return result;
1661}
1662
1663/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001664ASTNode::ID Parser::logicalAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001665 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001666 ASTNode::ID result = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001667 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001668 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001669 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001670 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001671 while (this->checkNext(Token::Kind::TK_LOGICALAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001672 if (!depth.increase()) {
1673 return ASTNode::ID::Invalid();
1674 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001675 ASTNode::ID right = this->bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001676 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001677 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001678 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001679 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1680 getNode(newResult).addChild(result);
1681 getNode(newResult).addChild(right);
1682 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001683 }
1684 return result;
1685}
1686
1687/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001688ASTNode::ID Parser::bitwiseOrExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001689 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001690 ASTNode::ID result = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001691 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001692 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001693 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001694 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001695 while (this->checkNext(Token::Kind::TK_BITWISEOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001696 if (!depth.increase()) {
1697 return ASTNode::ID::Invalid();
1698 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001699 ASTNode::ID right = this->bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001700 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001701 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001702 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001703 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1704 getNode(newResult).addChild(result);
1705 getNode(newResult).addChild(right);
1706 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001707 }
1708 return result;
1709}
1710
1711/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001712ASTNode::ID Parser::bitwiseXorExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001713 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001714 ASTNode::ID result = this->bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001715 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001716 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001717 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001718 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001719 while (this->checkNext(Token::Kind::TK_BITWISEXOR, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001720 if (!depth.increase()) {
1721 return ASTNode::ID::Invalid();
1722 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001723 ASTNode::ID right = this->bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001724 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001725 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001726 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001727 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1728 getNode(newResult).addChild(result);
1729 getNode(newResult).addChild(right);
1730 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001731 }
1732 return result;
1733}
1734
1735/* equalityExpression (BITWISEAND equalityExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001736ASTNode::ID Parser::bitwiseAndExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001737 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001738 ASTNode::ID result = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001739 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001740 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001741 }
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -04001742 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001743 while (this->checkNext(Token::Kind::TK_BITWISEAND, &t)) {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001744 if (!depth.increase()) {
1745 return ASTNode::ID::Invalid();
1746 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001747 ASTNode::ID right = this->equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001748 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001749 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001750 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001751 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
1752 getNode(newResult).addChild(result);
1753 getNode(newResult).addChild(right);
1754 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001755 }
1756 return result;
1757}
1758
1759/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001760ASTNode::ID Parser::equalityExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001761 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001762 ASTNode::ID result = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001763 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001764 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001765 }
1766 for (;;) {
1767 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001768 case Token::Kind::TK_EQEQ: // fall through
1769 case Token::Kind::TK_NEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001770 if (!depth.increase()) {
1771 return ASTNode::ID::Invalid();
1772 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001773 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001774 ASTNode::ID right = this->relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001775 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001776 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001777 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001778 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1779 std::move(t));
1780 getNode(newResult).addChild(result);
1781 getNode(newResult).addChild(right);
1782 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001783 break;
1784 }
1785 default:
1786 return result;
1787 }
1788 }
1789}
1790
1791/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001792ASTNode::ID Parser::relationalExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001793 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001794 ASTNode::ID result = this->shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001795 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001796 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001797 }
1798 for (;;) {
1799 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001800 case Token::Kind::TK_LT: // fall through
1801 case Token::Kind::TK_GT: // fall through
1802 case Token::Kind::TK_LTEQ: // fall through
1803 case Token::Kind::TK_GTEQ: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001804 if (!depth.increase()) {
1805 return ASTNode::ID::Invalid();
1806 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001807 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001808 ASTNode::ID right = this->shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001809 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001810 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001811 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001812 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1813 std::move(t));
1814 getNode(newResult).addChild(result);
1815 getNode(newResult).addChild(right);
1816 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001817 break;
1818 }
1819 default:
1820 return result;
1821 }
1822 }
1823}
1824
1825/* additiveExpression ((SHL | SHR) additiveExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001826ASTNode::ID Parser::shiftExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001827 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001828 ASTNode::ID result = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001829 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001830 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001831 }
1832 for (;;) {
1833 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001834 case Token::Kind::TK_SHL: // fall through
1835 case Token::Kind::TK_SHR: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001836 if (!depth.increase()) {
1837 return ASTNode::ID::Invalid();
1838 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001839 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001840 ASTNode::ID right = this->additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001841 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001842 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001843 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001844 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1845 std::move(t));
1846 getNode(newResult).addChild(result);
1847 getNode(newResult).addChild(right);
1848 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001849 break;
1850 }
1851 default:
1852 return result;
1853 }
1854 }
1855}
1856
1857/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001858ASTNode::ID Parser::additiveExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001859 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001860 ASTNode::ID result = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001861 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001862 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001863 }
1864 for (;;) {
1865 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001866 case Token::Kind::TK_PLUS: // fall through
1867 case Token::Kind::TK_MINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001868 if (!depth.increase()) {
1869 return ASTNode::ID::Invalid();
1870 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001871 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001872 ASTNode::ID right = this->multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001873 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001874 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001875 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001876 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1877 std::move(t));
1878 getNode(newResult).addChild(result);
1879 getNode(newResult).addChild(right);
1880 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001881 break;
1882 }
1883 default:
1884 return result;
1885 }
1886 }
1887}
1888
1889/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001890ASTNode::ID Parser::multiplicativeExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001891 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001892 ASTNode::ID result = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001893 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001894 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001895 }
1896 for (;;) {
1897 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001898 case Token::Kind::TK_STAR: // fall through
1899 case Token::Kind::TK_SLASH: // fall through
1900 case Token::Kind::TK_PERCENT: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001901 if (!depth.increase()) {
1902 return ASTNode::ID::Invalid();
1903 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001904 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001905 ASTNode::ID right = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001906 if (!right) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001907 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001908 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001909 CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
1910 std::move(t));
1911 getNode(newResult).addChild(result);
1912 getNode(newResult).addChild(right);
1913 result = newResult;
ethannicholasb3058bd2016-07-01 08:22:01 -07001914 break;
1915 }
1916 default:
1917 return result;
1918 }
1919 }
1920}
1921
1922/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001923ASTNode::ID Parser::unaryExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001924 AutoDepth depth(this);
ethannicholasb3058bd2016-07-01 08:22:01 -07001925 switch (this->peek().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001926 case Token::Kind::TK_PLUS: // fall through
1927 case Token::Kind::TK_MINUS: // fall through
1928 case Token::Kind::TK_LOGICALNOT: // fall through
1929 case Token::Kind::TK_BITWISENOT: // fall through
1930 case Token::Kind::TK_PLUSPLUS: // fall through
1931 case Token::Kind::TK_MINUSMINUS: {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001932 if (!depth.increase()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001933 return ASTNode::ID::Invalid();
Ethan Nicholas6dcc3252019-02-20 15:18:36 -05001934 }
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001935 Token t = this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001936 ASTNode::ID expr = this->unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07001937 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001938 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001939 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001940 CREATE_NODE(result, t.fOffset, ASTNode::Kind::kPrefix, std::move(t));
1941 getNode(result).addChild(expr);
1942 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001943 }
1944 default:
1945 return this->postfixExpression();
1946 }
1947}
1948
1949/* term suffix* */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001950ASTNode::ID Parser::postfixExpression() {
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001951 AutoDepth depth(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001952 ASTNode::ID result = this->term();
ethannicholasb3058bd2016-07-01 08:22:01 -07001953 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001954 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07001955 }
1956 for (;;) {
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001957 Token t = this->peek();
1958 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001959 case Token::Kind::TK_FLOAT_LITERAL:
Ethan Nicholas5a9a0b32019-09-17 16:18:22 -04001960 if (this->text(t)[0] != '.') {
1961 return result;
1962 }
1963 // fall through
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001964 case Token::Kind::TK_LBRACKET:
1965 case Token::Kind::TK_DOT:
1966 case Token::Kind::TK_LPAREN:
1967 case Token::Kind::TK_PLUSPLUS:
1968 case Token::Kind::TK_MINUSMINUS:
1969 case Token::Kind::TK_COLONCOLON:
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001970 if (!depth.increase()) {
1971 return ASTNode::ID::Invalid();
1972 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001973 result = this->suffix(result);
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001974 if (!result) {
1975 return ASTNode::ID::Invalid();
1976 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001977 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001978 default:
1979 return result;
1980 }
1981 }
1982}
1983
Ethan Nicholas11d53972016-11-28 11:23:23 -05001984/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
Ethan Nicholase455f652019-09-13 12:52:55 -04001985 PLUSPLUS | MINUSMINUS | COLONCOLON IDENTIFIER | FLOAT_LITERAL [IDENTIFIER] */
Ethan Nicholasfc994162019-06-06 10:04:27 -04001986ASTNode::ID Parser::suffix(ASTNode::ID base) {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04001987 SkASSERT(base);
ethannicholasb3058bd2016-07-01 08:22:01 -07001988 Token next = this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001989 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04001990 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04001991 return ASTNode::ID::Invalid();
1992 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001993 switch (next.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001994 case Token::Kind::TK_LBRACKET: {
1995 if (this->checkNext(Token::Kind::TK_RBRACKET)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001996 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kIndex);
1997 getNode(result).addChild(base);
1998 return result;
ethannicholas5961bc92016-10-12 06:39:56 -07001999 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002000 ASTNode::ID e = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07002001 if (!e) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002002 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07002003 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002004 this->expect(Token::Kind::TK_RBRACKET, "']' to complete array access expression");
Ethan Nicholasfc994162019-06-06 10:04:27 -04002005 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kIndex);
2006 getNode(result).addChild(base);
2007 getNode(result).addChild(e);
2008 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07002009 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002010 case Token::Kind::TK_DOT: // fall through
2011 case Token::Kind::TK_COLONCOLON: {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002012 int offset = this->peek().fOffset;
2013 StringFragment text;
ethannicholasb3058bd2016-07-01 08:22:01 -07002014 if (this->identifier(&text)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002015 CREATE_NODE(result, offset, ASTNode::Kind::kField, std::move(text));
2016 getNode(result).addChild(base);
2017 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07002018 }
Ethan Nicholase455f652019-09-13 12:52:55 -04002019 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002020 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholase455f652019-09-13 12:52:55 -04002021 // Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
2022 // floating point literals, possibly followed by an identifier. Handle that here.
2023 StringFragment field = this->text(next);
2024 SkASSERT(field.fChars[0] == '.');
2025 ++field.fChars;
2026 --field.fLength;
2027 for (size_t i = 0; i < field.fLength; ++i) {
2028 if (field.fChars[i] != '0' && field.fChars[i] != '1') {
2029 this->error(next, "invalid swizzle");
2030 return ASTNode::ID::Invalid();
2031 }
2032 }
2033 // use the next *raw* token so we don't ignore whitespace - we only care about
2034 // identifiers that directly follow the float
2035 Token id = this->nextRawToken();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002036 if (id.fKind == Token::Kind::TK_IDENTIFIER) {
Ethan Nicholase455f652019-09-13 12:52:55 -04002037 field.fLength += id.fLength;
2038 } else {
2039 this->pushback(id);
2040 }
2041 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kField, field);
2042 getNode(result).addChild(base);
2043 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07002044 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002045 case Token::Kind::TK_LPAREN: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002046 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kCall);
2047 getNode(result).addChild(base);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002048 if (this->peek().fKind != Token::Kind::TK_RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002049 for (;;) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002050 ASTNode::ID expr = this->assignmentExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -07002051 if (!expr) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002052 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07002053 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002054 getNode(result).addChild(expr);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002055 if (!this->checkNext(Token::Kind::TK_COMMA)) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002056 break;
2057 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002058 }
2059 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002060 this->expect(Token::Kind::TK_RPAREN, "')' to complete function parameters");
Ethan Nicholasfc994162019-06-06 10:04:27 -04002061 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07002062 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002063 case Token::Kind::TK_PLUSPLUS: // fall through
2064 case Token::Kind::TK_MINUSMINUS: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002065 CREATE_NODE(result, next.fOffset, ASTNode::Kind::kPostfix, next);
2066 getNode(result).addChild(base);
2067 return result;
2068 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002069 default: {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04002070 this->error(next, "expected expression suffix, but found '" + this->text(next) + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04002071 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07002072 }
2073 }
2074}
2075
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05002076/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | NULL_LITERAL | '(' expression ')' */
Ethan Nicholasfc994162019-06-06 10:04:27 -04002077ASTNode::ID Parser::term() {
ethannicholasb3058bd2016-07-01 08:22:01 -07002078 Token t = this->peek();
2079 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002080 case Token::Kind::TK_IDENTIFIER: {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002081 StringFragment text;
ethannicholasb3058bd2016-07-01 08:22:01 -07002082 if (this->identifier(&text)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002083 RETURN_NODE(t.fOffset, ASTNode::Kind::kIdentifier, std::move(text));
ethannicholasb3058bd2016-07-01 08:22:01 -07002084 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002085 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002086 case Token::Kind::TK_INT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002087 SKSL_INT i;
ethannicholasb3058bd2016-07-01 08:22:01 -07002088 if (this->intLiteral(&i)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002089 RETURN_NODE(t.fOffset, ASTNode::Kind::kInt, i);
ethannicholasb3058bd2016-07-01 08:22:01 -07002090 }
2091 break;
2092 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002093 case Token::Kind::TK_FLOAT_LITERAL: {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002094 SKSL_FLOAT f;
ethannicholasb3058bd2016-07-01 08:22:01 -07002095 if (this->floatLiteral(&f)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002096 RETURN_NODE(t.fOffset, ASTNode::Kind::kFloat, f);
ethannicholasb3058bd2016-07-01 08:22:01 -07002097 }
2098 break;
2099 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002100 case Token::Kind::TK_TRUE_LITERAL: // fall through
2101 case Token::Kind::TK_FALSE_LITERAL: {
ethannicholasb3058bd2016-07-01 08:22:01 -07002102 bool b;
2103 if (this->boolLiteral(&b)) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002104 RETURN_NODE(t.fOffset, ASTNode::Kind::kBool, b);
ethannicholasb3058bd2016-07-01 08:22:01 -07002105 }
2106 break;
2107 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002108 case Token::Kind::TK_NULL_LITERAL:
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05002109 this->nextToken();
Ethan Nicholasfc994162019-06-06 10:04:27 -04002110 RETURN_NODE(t.fOffset, ASTNode::Kind::kNull);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002111 case Token::Kind::TK_LPAREN: {
ethannicholasb3058bd2016-07-01 08:22:01 -07002112 this->nextToken();
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04002113 AutoDepth depth(this);
Ethan Nicholascf4deab2019-09-13 16:28:14 -04002114 if (!depth.increase()) {
Ethan Nicholas4e3b0112019-06-07 16:49:07 -04002115 return ASTNode::ID::Invalid();
2116 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002117 ASTNode::ID result = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -07002118 if (result) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002119 this->expect(Token::Kind::TK_RPAREN, "')' to complete expression");
Ethan Nicholasfc994162019-06-06 10:04:27 -04002120 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07002121 }
2122 break;
2123 }
2124 default:
2125 this->nextToken();
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04002126 this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002127 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002128 return ASTNode::ID::Invalid();
ethannicholasb3058bd2016-07-01 08:22:01 -07002129}
2130
2131/* INT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04002132bool Parser::intLiteral(SKSL_INT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002133 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002134 if (this->expect(Token::Kind::TK_INT_LITERAL, "integer literal", &t)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002135 *dest = SkSL::stol(this->text(t));
ethannicholasb3058bd2016-07-01 08:22:01 -07002136 return true;
2137 }
2138 return false;
2139}
2140
2141/* FLOAT_LITERAL */
Ethan Nicholasfc994162019-06-06 10:04:27 -04002142bool Parser::floatLiteral(SKSL_FLOAT* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002143 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002144 if (this->expect(Token::Kind::TK_FLOAT_LITERAL, "float literal", &t)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002145 *dest = SkSL::stod(this->text(t));
ethannicholasb3058bd2016-07-01 08:22:01 -07002146 return true;
2147 }
2148 return false;
2149}
2150
2151/* TRUE_LITERAL | FALSE_LITERAL */
2152bool Parser::boolLiteral(bool* dest) {
2153 Token t = this->nextToken();
2154 switch (t.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002155 case Token::Kind::TK_TRUE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07002156 *dest = true;
2157 return true;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002158 case Token::Kind::TK_FALSE_LITERAL:
ethannicholasb3058bd2016-07-01 08:22:01 -07002159 *dest = false;
2160 return true;
2161 default:
Ethan Nicholas0c8582e2019-07-19 09:26:46 -04002162 this->error(t, "expected 'true' or 'false', but found '" + this->text(t) + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002163 return false;
2164 }
2165}
2166
2167/* IDENTIFIER */
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002168bool Parser::identifier(StringFragment* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002169 Token t;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002170 if (this->expect(Token::Kind::TK_IDENTIFIER, "identifier", &t)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002171 *dest = this->text(t);
ethannicholasb3058bd2016-07-01 08:22:01 -07002172 return true;
2173 }
2174 return false;
2175}
2176
2177} // namespace