blob: 0f5b974bc5b5fd5d18ea66625235c6bdab24020b [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"
9#include "SkSLParser.h"
10#include "SkSLToken.h"
11
12#define register
Ethan Nicholasbfe15f62017-03-01 11:46:51 -050013#include "disable_flex_warnings.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070014#include "lex.sksl.c"
Ethan Nicholas0dd30d92017-05-01 16:57:07 -040015static_assert(YY_FLEX_MAJOR_VERSION * 10000 + YY_FLEX_MINOR_VERSION * 100 +
16 YY_FLEX_SUBMINOR_VERSION >= 20601,
Ethan Nicholas94421942017-03-31 17:06:42 -040017 "we require Flex 2.6.1 or better for security reasons");
Ethan Nicholasbfe15f62017-03-01 11:46:51 -050018#undef register
ethannicholasb3058bd2016-07-01 08:22:01 -070019#ifdef __clang__
20#pragma clang diagnostic pop
21#endif
ethannicholasf789b382016-08-03 12:43:36 -070022#ifdef __GNUC__
23#pragma GCC diagnostic pop
24#endif
25#ifdef _MSC_VER
26#pragma warning(pop)
27#endif
ethannicholasb3058bd2016-07-01 08:22:01 -070028
Ethan Nicholasbfe15f62017-03-01 11:46:51 -050029#include "lex.layout.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070030#include "ast/SkSLASTBinaryExpression.h"
31#include "ast/SkSLASTBlock.h"
32#include "ast/SkSLASTBoolLiteral.h"
33#include "ast/SkSLASTBreakStatement.h"
34#include "ast/SkSLASTCallSuffix.h"
35#include "ast/SkSLASTContinueStatement.h"
36#include "ast/SkSLASTDiscardStatement.h"
37#include "ast/SkSLASTDoStatement.h"
38#include "ast/SkSLASTExpression.h"
39#include "ast/SkSLASTExpressionStatement.h"
40#include "ast/SkSLASTExtension.h"
41#include "ast/SkSLASTFieldSuffix.h"
42#include "ast/SkSLASTFloatLiteral.h"
43#include "ast/SkSLASTForStatement.h"
44#include "ast/SkSLASTFunction.h"
45#include "ast/SkSLASTIdentifier.h"
46#include "ast/SkSLASTIfStatement.h"
47#include "ast/SkSLASTIndexSuffix.h"
48#include "ast/SkSLASTInterfaceBlock.h"
49#include "ast/SkSLASTIntLiteral.h"
ethannicholas5961bc92016-10-12 06:39:56 -070050#include "ast/SkSLASTModifiersDeclaration.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070051#include "ast/SkSLASTParameter.h"
ethannicholas5961bc92016-10-12 06:39:56 -070052#include "ast/SkSLASTPrecision.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070053#include "ast/SkSLASTPrefixExpression.h"
54#include "ast/SkSLASTReturnStatement.h"
55#include "ast/SkSLASTStatement.h"
56#include "ast/SkSLASTSuffixExpression.h"
Ethan Nicholasaf197692017-02-27 13:26:45 -050057#include "ast/SkSLASTSwitchCase.h"
58#include "ast/SkSLASTSwitchStatement.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070059#include "ast/SkSLASTTernaryExpression.h"
60#include "ast/SkSLASTType.h"
61#include "ast/SkSLASTVarDeclaration.h"
62#include "ast/SkSLASTVarDeclarationStatement.h"
63#include "ast/SkSLASTWhileStatement.h"
64#include "ir/SkSLSymbolTable.h"
Ethan Nicholas11d53972016-11-28 11:23:23 -050065#include "ir/SkSLModifiers.h"
ethannicholasd598f792016-07-25 10:08:54 -070066#include "ir/SkSLType.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070067
68namespace SkSL {
69
ethannicholascad64162016-10-27 10:54:02 -070070#define MAX_PARSE_DEPTH 50
71
72class AutoDepth {
73public:
74 AutoDepth(Parser* p)
75 : fParser(p) {
76 fParser->fDepth++;
77 }
78
79 ~AutoDepth() {
80 fParser->fDepth--;
81 }
82
83 bool checkValid() {
84 if (fParser->fDepth > MAX_PARSE_DEPTH) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -040085 fParser->error(fParser->peek().fPosition, String("exceeded max parse depth"));
ethannicholascad64162016-10-27 10:54:02 -070086 return false;
87 }
88 return true;
89 }
90
91private:
92 Parser* fParser;
93};
94
Ethan Nicholas0df1b042017-03-31 13:56:23 -040095Parser::Parser(String text, SymbolTable& types, ErrorReporter& errors)
96: fPushback(Position(-1, -1), Token::INVALID_TOKEN, String())
ethannicholasb3058bd2016-07-01 08:22:01 -070097, fTypes(types)
98, fErrors(errors) {
99 sksllex_init(&fScanner);
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500100 layoutlex_init(&fLayoutScanner);
ethannicholasb3058bd2016-07-01 08:22:01 -0700101 fBuffer = sksl_scan_string(text.c_str(), fScanner);
102 skslset_lineno(1, fScanner);
103
104 if (false) {
105 // avoid unused warning
106 yyunput(0, nullptr, fScanner);
107 }
108}
109
110Parser::~Parser() {
111 sksl_delete_buffer(fBuffer, fScanner);
ethannicholas69a7e7c2016-07-01 19:09:27 -0700112 sksllex_destroy(fScanner);
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500113 layoutlex_destroy(fLayoutScanner);
ethannicholasb3058bd2016-07-01 08:22:01 -0700114}
115
116/* (precision | directive | declaration)* END_OF_FILE */
117std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
118 std::vector<std::unique_ptr<ASTDeclaration>> result;
119 for (;;) {
120 switch (this->peek().fKind) {
121 case Token::END_OF_FILE:
122 return result;
ethannicholas5961bc92016-10-12 06:39:56 -0700123 case Token::PRECISION: {
124 std::unique_ptr<ASTDeclaration> precision = this->precision();
125 if (precision) {
126 result.push_back(std::move(precision));
127 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700128 break;
ethannicholas5961bc92016-10-12 06:39:56 -0700129 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700130 case Token::DIRECTIVE: {
131 std::unique_ptr<ASTDeclaration> decl = this->directive();
132 if (decl) {
133 result.push_back(std::move(decl));
134 }
135 break;
136 }
137 default: {
138 std::unique_ptr<ASTDeclaration> decl = this->declaration();
139 if (!decl) {
140 continue;
141 }
142 result.push_back(std::move(decl));
143 }
144 }
145 }
146}
147
148Token Parser::nextToken() {
149 if (fPushback.fKind != Token::INVALID_TOKEN) {
150 Token result = fPushback;
151 fPushback.fKind = Token::INVALID_TOKEN;
152 fPushback.fText = "";
153 return result;
154 }
155 int token = sksllex(fScanner);
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400156 String text;
ethannicholas471e8942016-10-28 09:02:46 -0700157 switch ((Token::Kind) token) {
158 case Token::IDENTIFIER: // fall through
159 case Token::INT_LITERAL: // fall through
160 case Token::FLOAT_LITERAL: // fall through
161 case Token::DIRECTIVE:
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400162 text = String(skslget_text(fScanner));
ethannicholas471e8942016-10-28 09:02:46 -0700163 break;
164 default:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500165#ifdef SK_DEBUG
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400166 text = String(skslget_text(fScanner));
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500167#endif
ethannicholas471e8942016-10-28 09:02:46 -0700168 break;
169 }
170 return Token(Position(skslget_lineno(fScanner), -1), (Token::Kind) token, text);
ethannicholasb3058bd2016-07-01 08:22:01 -0700171}
172
173void Parser::pushback(Token t) {
174 ASSERT(fPushback.fKind == Token::INVALID_TOKEN);
175 fPushback = t;
176}
177
178Token Parser::peek() {
179 fPushback = this->nextToken();
180 return fPushback;
181}
182
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500183
184bool Parser::expect(Token::Kind kind, const char* expected, Token* result) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400185 return this->expect(kind, String(expected), result);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500186}
187
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400188bool Parser::expect(Token::Kind kind, String expected, Token* result) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700189 Token next = this->nextToken();
190 if (next.fKind == kind) {
191 if (result) {
192 *result = next;
193 }
194 return true;
195 } else {
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500196 if (next.fText.size()) {
197 this->error(next.fPosition, "expected " + expected + ", but found '" + next.fText +
198 "'");
199 } else {
200 this->error(next.fPosition, "parse error, recompile in debug mode for details");
201 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700202 return false;
203 }
204}
205
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500206void Parser::error(Position p, const char* msg) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400207 this->error(p, String(msg));
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500208}
209
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400210void Parser::error(Position p, String msg) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700211 fErrors.error(p, msg);
212}
213
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400214bool Parser::isType(String name) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700215 return nullptr != fTypes[name];
216}
217
218/* PRECISION (LOWP | MEDIUMP | HIGHP) type SEMICOLON */
ethannicholas5961bc92016-10-12 06:39:56 -0700219std::unique_ptr<ASTDeclaration> Parser::precision() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700220 if (!this->expect(Token::PRECISION, "'precision'")) {
ethannicholas5961bc92016-10-12 06:39:56 -0700221 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700222 }
ethannicholas5961bc92016-10-12 06:39:56 -0700223 Modifiers::Flag result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700224 Token p = this->nextToken();
225 switch (p.fKind) {
ethannicholas5961bc92016-10-12 06:39:56 -0700226 case Token::LOWP:
227 result = Modifiers::kLowp_Flag;
228 break;
229 case Token::MEDIUMP:
230 result = Modifiers::kMediump_Flag;
231 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700232 case Token::HIGHP:
ethannicholas5961bc92016-10-12 06:39:56 -0700233 result = Modifiers::kHighp_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700234 break;
235 default:
Ethan Nicholas11d53972016-11-28 11:23:23 -0500236 this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" +
ethannicholasb3058bd2016-07-01 08:22:01 -0700237 p.fText + "'");
ethannicholas5961bc92016-10-12 06:39:56 -0700238 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700239 }
ethannicholas5961bc92016-10-12 06:39:56 -0700240 // FIXME handle the type
ethannicholasb3058bd2016-07-01 08:22:01 -0700241 if (!this->type()) {
ethannicholas5961bc92016-10-12 06:39:56 -0700242 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700243 }
244 this->expect(Token::SEMICOLON, "';'");
ethannicholas5961bc92016-10-12 06:39:56 -0700245 return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result));
ethannicholasb3058bd2016-07-01 08:22:01 -0700246}
247
Ethan Nicholas11d53972016-11-28 11:23:23 -0500248/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
ethannicholas5961bc92016-10-12 06:39:56 -0700249 DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
ethannicholasb3058bd2016-07-01 08:22:01 -0700250std::unique_ptr<ASTDeclaration> Parser::directive() {
251 Token start;
252 if (!this->expect(Token::DIRECTIVE, "a directive", &start)) {
253 return nullptr;
254 }
255 if (start.fText == "#version") {
256 this->expect(Token::INT_LITERAL, "a version number");
ethannicholas5961bc92016-10-12 06:39:56 -0700257 Token next = this->peek();
258 if (next.fText == "es" || next.fText == "compatibility") {
259 this->nextToken();
260 }
261 // version is ignored for now; it will eventually become an error when we stop pretending
262 // to be GLSL
ethannicholasb3058bd2016-07-01 08:22:01 -0700263 return nullptr;
264 } else if (start.fText == "#extension") {
265 Token name;
266 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
267 return nullptr;
268 }
269 if (!this->expect(Token::COLON, "':'")) {
270 return nullptr;
271 }
272 // FIXME: need to start paying attention to this token
273 if (!this->expect(Token::IDENTIFIER, "an identifier")) {
274 return nullptr;
275 }
Ethan Nicholas11d53972016-11-28 11:23:23 -0500276 return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700277 std::move(name.fText)));
278 } else {
279 this->error(start.fPosition, "unsupported directive '" + start.fText + "'");
280 return nullptr;
281 }
282}
283
Ethan Nicholas11d53972016-11-28 11:23:23 -0500284/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
ethannicholasb3058bd2016-07-01 08:22:01 -0700285 (COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
286std::unique_ptr<ASTDeclaration> Parser::declaration() {
Ethan Nicholas11d53972016-11-28 11:23:23 -0500287 Modifiers modifiers = this->modifiers();
ethannicholasb3058bd2016-07-01 08:22:01 -0700288 Token lookahead = this->peek();
289 if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) {
290 // we have an identifier that's not a type, could be the start of an interface block
291 return this->interfaceBlock(modifiers);
292 }
293 if (lookahead.fKind == Token::STRUCT) {
294 return this->structVarDeclaration(modifiers);
295 }
ethannicholas5961bc92016-10-12 06:39:56 -0700296 if (lookahead.fKind == Token::SEMICOLON) {
297 this->nextToken();
298 return std::unique_ptr<ASTDeclaration>(new ASTModifiersDeclaration(modifiers));
299 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700300 std::unique_ptr<ASTType> type(this->type());
301 if (!type) {
302 return nullptr;
303 }
304 if (type->fKind == ASTType::kStruct_Kind && peek().fKind == Token::SEMICOLON) {
305 this->nextToken();
306 return nullptr;
307 }
308 Token name;
309 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
310 return nullptr;
311 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400312 if (this->peek().fKind == Token::LPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700313 this->nextToken();
314 std::vector<std::unique_ptr<ASTParameter>> parameters;
315 while (this->peek().fKind != Token::RPAREN) {
316 if (parameters.size() > 0) {
317 if (!this->expect(Token::COMMA, "','")) {
318 return nullptr;
319 }
320 }
321 std::unique_ptr<ASTParameter> parameter = this->parameter();
322 if (!parameter) {
323 return nullptr;
324 }
325 parameters.push_back(std::move(parameter));
326 }
327 this->nextToken();
328 std::unique_ptr<ASTBlock> body;
329 if (this->peek().fKind == Token::SEMICOLON) {
330 this->nextToken();
331 } else {
332 body = this->block();
333 if (!body) {
334 return nullptr;
335 }
336 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400337 return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition,
338 modifiers,
339 std::move(type),
Ethan Nicholas11d53972016-11-28 11:23:23 -0500340 std::move(name.fText),
341 std::move(parameters),
ethannicholasb3058bd2016-07-01 08:22:01 -0700342 std::move(body)));
343 } else {
344 return this->varDeclarationEnd(modifiers, std::move(type), name.fText);
345 }
346}
347
348/* modifiers type IDENTIFIER varDeclarationEnd */
ethannicholas14fe8cc2016-09-07 13:37:16 -0700349std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() {
Ethan Nicholas11d53972016-11-28 11:23:23 -0500350 Modifiers modifiers = this->modifiers();
ethannicholasb3058bd2016-07-01 08:22:01 -0700351 std::unique_ptr<ASTType> type(this->type());
352 if (!type) {
353 return nullptr;
354 }
355 Token name;
356 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
357 return nullptr;
358 }
359 return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText));
360}
361
362/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
363std::unique_ptr<ASTType> Parser::structDeclaration() {
364 if (!this->expect(Token::STRUCT, "'struct'")) {
365 return nullptr;
366 }
367 Token name;
368 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
369 return nullptr;
370 }
371 if (!this->expect(Token::LBRACE, "'{'")) {
372 return nullptr;
373 }
374 std::vector<Type::Field> fields;
375 while (this->peek().fKind != Token::RBRACE) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700376 std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700377 if (!decl) {
378 return nullptr;
379 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700380 for (const auto& var : decl->fVars) {
ethannicholasd598f792016-07-25 10:08:54 -0700381 auto type = (const Type*) fTypes[decl->fType->fName];
ethannicholas14fe8cc2016-09-07 13:37:16 -0700382 for (int i = (int) var.fSizes.size() - 1; i >= 0; i--) {
ethannicholasdd4645b2016-10-14 12:14:46 -0700383 if (!var.fSizes[i] || var.fSizes[i]->fKind != ASTExpression::kInt_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700384 this->error(decl->fPosition, "array size in struct field must be a constant");
ethannicholasdd4645b2016-10-14 12:14:46 -0700385 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700386 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700387 uint64_t columns = ((ASTIntLiteral&) *var.fSizes[i]).fValue;
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400388 String name = type->name() + "[" + to_string(columns) + "]";
ethannicholasd598f792016-07-25 10:08:54 -0700389 type = new Type(name, Type::kArray_Kind, *type, (int) columns);
390 fTypes.takeOwnership((Type*) type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700391 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700392 fields.push_back(Type::Field(decl->fModifiers, var.fName, type));
393 if (var.fValue) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700394 this->error(decl->fPosition, "initializers are not permitted on struct fields");
395 }
396 }
397 }
398 if (!this->expect(Token::RBRACE, "'}'")) {
399 return nullptr;
400 }
Ethan Nicholas19671772016-11-28 16:30:17 -0500401 fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fPosition, name.fText, fields)));
Ethan Nicholas11d53972016-11-28 11:23:23 -0500402 return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText,
Ethan Nicholas50afc172017-02-16 14:49:57 -0500403 ASTType::kStruct_Kind, std::vector<int>()));
ethannicholasb3058bd2016-07-01 08:22:01 -0700404}
405
406/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500407std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(Modifiers modifiers) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700408 std::unique_ptr<ASTType> type = this->structDeclaration();
409 if (!type) {
410 return nullptr;
411 }
412 if (peek().fKind == Token::IDENTIFIER) {
413 Token name = this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500414 std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers,
415 std::move(type),
ethannicholas14fe8cc2016-09-07 13:37:16 -0700416 std::move(name.fText));
ethannicholasb3058bd2016-07-01 08:22:01 -0700417 if (result) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700418 for (const auto& var : result->fVars) {
419 if (var.fValue) {
Ethan Nicholas11d53972016-11-28 11:23:23 -0500420 this->error(var.fValue->fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700421 "struct variables cannot be initialized");
422 }
423 }
424 }
425 return result;
426 }
427 this->expect(Token::SEMICOLON, "';'");
428 return nullptr;
429}
430
Ethan Nicholas11d53972016-11-28 11:23:23 -0500431/* (LBRACKET expression? RBRACKET)* (EQ expression)? (COMMA IDENTIFER
ethannicholasb3058bd2016-07-01 08:22:01 -0700432 (LBRACKET expression? RBRACKET)* (EQ expression)?)* SEMICOLON */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500433std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods,
ethannicholas14fe8cc2016-09-07 13:37:16 -0700434 std::unique_ptr<ASTType> type,
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400435 String name) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700436 std::vector<ASTVarDeclaration> vars;
ethannicholasb3058bd2016-07-01 08:22:01 -0700437 std::vector<std::unique_ptr<ASTExpression>> currentVarSizes;
438 while (this->peek().fKind == Token::LBRACKET) {
439 this->nextToken();
440 if (this->peek().fKind == Token::RBRACKET) {
441 this->nextToken();
442 currentVarSizes.push_back(nullptr);
443 } else {
444 std::unique_ptr<ASTExpression> size(this->expression());
445 if (!size) {
446 return nullptr;
447 }
448 currentVarSizes.push_back(std::move(size));
449 if (!this->expect(Token::RBRACKET, "']'")) {
450 return nullptr;
451 }
452 }
453 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700454 std::unique_ptr<ASTExpression> value;
ethannicholasb3058bd2016-07-01 08:22:01 -0700455 if (this->peek().fKind == Token::EQ) {
456 this->nextToken();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700457 value = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700458 if (!value) {
459 return nullptr;
460 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700461 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700462 vars.emplace_back(std::move(name), std::move(currentVarSizes), std::move(value));
ethannicholasb3058bd2016-07-01 08:22:01 -0700463 while (this->peek().fKind == Token::COMMA) {
464 this->nextToken();
465 Token name;
466 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
467 return nullptr;
468 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700469 currentVarSizes.clear();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700470 value.reset();
ethannicholasb3058bd2016-07-01 08:22:01 -0700471 while (this->peek().fKind == Token::LBRACKET) {
472 this->nextToken();
473 if (this->peek().fKind == Token::RBRACKET) {
474 this->nextToken();
475 currentVarSizes.push_back(nullptr);
476 } else {
477 std::unique_ptr<ASTExpression> size(this->expression());
478 if (!size) {
479 return nullptr;
480 }
481 currentVarSizes.push_back(std::move(size));
482 if (!this->expect(Token::RBRACKET, "']'")) {
483 return nullptr;
484 }
485 }
486 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700487 if (this->peek().fKind == Token::EQ) {
488 this->nextToken();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700489 value = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700490 if (!value) {
491 return nullptr;
492 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700493 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700494 vars.emplace_back(std::move(name.fText), std::move(currentVarSizes), std::move(value));
ethannicholasb3058bd2016-07-01 08:22:01 -0700495 }
496 if (!this->expect(Token::SEMICOLON, "';'")) {
497 return nullptr;
498 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700499 return std::unique_ptr<ASTVarDeclarations>(new ASTVarDeclarations(std::move(mods),
500 std::move(type),
501 std::move(vars)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700502}
503
504/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
505std::unique_ptr<ASTParameter> Parser::parameter() {
Ethan Nicholasc6f5e102017-03-31 14:53:17 -0400506 Modifiers modifiers = this->modifiersWithDefaults(0);
ethannicholasb3058bd2016-07-01 08:22:01 -0700507 std::unique_ptr<ASTType> type = this->type();
508 if (!type) {
509 return nullptr;
510 }
511 Token name;
512 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
513 return nullptr;
514 }
515 std::vector<int> sizes;
516 while (this->peek().fKind == Token::LBRACKET) {
517 this->nextToken();
518 Token sizeToken;
519 if (!this->expect(Token::INT_LITERAL, "a positive integer", &sizeToken)) {
520 return nullptr;
521 }
522 sizes.push_back(SkSL::stoi(sizeToken.fText));
523 if (!this->expect(Token::RBRACKET, "']'")) {
524 return nullptr;
525 }
526 }
Ethan Nicholas11d53972016-11-28 11:23:23 -0500527 return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers,
528 std::move(type), name.fText,
ethannicholasb3058bd2016-07-01 08:22:01 -0700529 std::move(sizes)));
530}
531
532/** (EQ INT_LITERAL)? */
533int Parser::layoutInt() {
534 if (!this->expect(Token::EQ, "'='")) {
535 return -1;
536 }
537 Token resultToken;
538 if (this->expect(Token::INT_LITERAL, "a non-negative integer", &resultToken)) {
539 return SkSL::stoi(resultToken.fText);
540 }
541 return -1;
542}
543
ethannicholas8ac838d2016-11-22 08:39:36 -0800544/* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500545Layout Parser::layout() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700546 int location = -1;
Ethan Nicholas19671772016-11-28 16:30:17 -0500547 int offset = -1;
ethannicholasb3058bd2016-07-01 08:22:01 -0700548 int binding = -1;
549 int index = -1;
550 int set = -1;
551 int builtin = -1;
Greg Daniel64773e62016-11-22 09:44:03 -0500552 int inputAttachmentIndex = -1;
ethannicholasf789b382016-08-03 12:43:36 -0700553 bool originUpperLeft = false;
ethannicholas5961bc92016-10-12 06:39:56 -0700554 bool overrideCoverage = false;
555 bool blendSupportAllEquations = false;
Ethan Nicholas11d53972016-11-28 11:23:23 -0500556 Layout::Format format = Layout::Format::kUnspecified;
ethannicholas8ac838d2016-11-22 08:39:36 -0800557 bool pushConstant = false;
Ethan Nicholas52cad152017-02-16 16:37:32 -0500558 Layout::Primitive primitive = Layout::kUnspecified_Primitive;
559 int maxVertices = -1;
560 int invocations = -1;
ethannicholasb3058bd2016-07-01 08:22:01 -0700561 if (this->peek().fKind == Token::LAYOUT) {
562 this->nextToken();
563 if (!this->expect(Token::LPAREN, "'('")) {
Ethan Nicholas19671772016-11-28 16:30:17 -0500564 return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
Ethan Nicholas11d53972016-11-28 11:23:23 -0500565 originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
Ethan Nicholas52cad152017-02-16 16:37:32 -0500566 pushConstant, primitive, maxVertices, invocations);
ethannicholasb3058bd2016-07-01 08:22:01 -0700567 }
568 for (;;) {
569 Token t = this->nextToken();
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500570 YY_BUFFER_STATE buffer;
571 buffer = layout_scan_string(t.fText.c_str(), fLayoutScanner);
572 int token = layoutlex(fLayoutScanner);
573 layout_delete_buffer(buffer, fLayoutScanner);
574 if (token != Token::INVALID_TOKEN) {
575 switch (token) {
576 case Token::LOCATION:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500577 location = this->layoutInt();
578 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500579 case Token::OFFSET:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500580 offset = this->layoutInt();
581 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500582 case Token::BINDING:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500583 binding = this->layoutInt();
584 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500585 case Token::INDEX:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500586 index = this->layoutInt();
587 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500588 case Token::SET:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500589 set = this->layoutInt();
590 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500591 case Token::BUILTIN:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500592 builtin = this->layoutInt();
593 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500594 case Token::INPUT_ATTACHMENT_INDEX:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500595 inputAttachmentIndex = this->layoutInt();
596 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500597 case Token::ORIGIN_UPPER_LEFT:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500598 originUpperLeft = true;
599 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500600 case Token::OVERRIDE_COVERAGE:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500601 overrideCoverage = true;
602 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500603 case Token::BLEND_SUPPORT_ALL_EQUATIONS:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500604 blendSupportAllEquations = true;
605 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500606 case Token::PUSH_CONSTANT:
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500607 pushConstant = true;
608 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500609 case Token::POINTS:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500610 primitive = Layout::kPoints_Primitive;
611 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500612 case Token::LINES:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500613 primitive = Layout::kLines_Primitive;
614 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500615 case Token::LINE_STRIP:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500616 primitive = Layout::kLineStrip_Primitive;
617 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500618 case Token::LINES_ADJACENCY:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500619 primitive = Layout::kLinesAdjacency_Primitive;
620 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500621 case Token::TRIANGLES:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500622 primitive = Layout::kTriangles_Primitive;
623 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500624 case Token::TRIANGLE_STRIP:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500625 primitive = Layout::kTriangleStrip_Primitive;
626 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500627 case Token::TRIANGLES_ADJACENCY:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500628 primitive = Layout::kTrianglesAdjacency_Primitive;
629 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500630 case Token::MAX_VERTICES:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500631 maxVertices = this->layoutInt();
632 break;
Ethan Nicholasbfe15f62017-03-01 11:46:51 -0500633 case Token::INVOCATIONS:
Ethan Nicholas52cad152017-02-16 16:37:32 -0500634 invocations = this->layoutInt();
635 break;
Ethan Nicholas3614d9a2017-02-15 12:33:30 -0500636 }
Ethan Nicholas11d53972016-11-28 11:23:23 -0500637 } else if (Layout::ReadFormat(t.fText, &format)) {
Brian Salomon2a51de82016-11-16 12:06:01 -0500638 // AST::ReadFormat stored the result in 'format'.
ethannicholasb3058bd2016-07-01 08:22:01 -0700639 } else {
Greg Daniel64773e62016-11-22 09:44:03 -0500640 this->error(t.fPosition, ("'" + t.fText +
ethannicholasb3058bd2016-07-01 08:22:01 -0700641 "' is not a valid layout qualifier").c_str());
642 }
643 if (this->peek().fKind == Token::RPAREN) {
644 this->nextToken();
645 break;
646 }
647 if (!this->expect(Token::COMMA, "','")) {
648 break;
649 }
650 }
651 }
Ethan Nicholas19671772016-11-28 16:30:17 -0500652 return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
653 originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
Ethan Nicholas52cad152017-02-16 16:37:32 -0500654 pushConstant, primitive, maxVertices, invocations);
ethannicholasb3058bd2016-07-01 08:22:01 -0700655}
656
Brian Salomonf9f45122016-11-29 11:59:17 -0500657/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE |
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400658 READONLY | WRITEONLY | COHERENT | VOLATILE | RESTRICT | BUFFER)* */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500659Modifiers Parser::modifiers() {
660 Layout layout = this->layout();
ethannicholasb3058bd2016-07-01 08:22:01 -0700661 int flags = 0;
662 for (;;) {
663 // TODO: handle duplicate / incompatible flags
664 switch (peek().fKind) {
665 case Token::UNIFORM:
666 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500667 flags |= Modifiers::kUniform_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700668 break;
669 case Token::CONST:
670 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500671 flags |= Modifiers::kConst_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700672 break;
673 case Token::IN:
674 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500675 flags |= Modifiers::kIn_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700676 break;
677 case Token::OUT:
678 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500679 flags |= Modifiers::kOut_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700680 break;
681 case Token::INOUT:
682 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500683 flags |= Modifiers::kIn_Flag;
684 flags |= Modifiers::kOut_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700685 break;
686 case Token::LOWP:
687 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500688 flags |= Modifiers::kLowp_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700689 break;
690 case Token::MEDIUMP:
691 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500692 flags |= Modifiers::kMediump_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700693 break;
694 case Token::HIGHP:
695 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500696 flags |= Modifiers::kHighp_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700697 break;
ethannicholasf789b382016-08-03 12:43:36 -0700698 case Token::FLAT:
699 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500700 flags |= Modifiers::kFlat_Flag;
ethannicholasf789b382016-08-03 12:43:36 -0700701 break;
702 case Token::NOPERSPECTIVE:
703 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500704 flags |= Modifiers::kNoPerspective_Flag;
ethannicholasf789b382016-08-03 12:43:36 -0700705 break;
Brian Salomonf9f45122016-11-29 11:59:17 -0500706 case Token::READONLY:
707 this->nextToken();
708 flags |= Modifiers::kReadOnly_Flag;
709 break;
710 case Token::WRITEONLY:
711 this->nextToken();
712 flags |= Modifiers::kWriteOnly_Flag;
713 break;
714 case Token::COHERENT:
715 this->nextToken();
716 flags |= Modifiers::kCoherent_Flag;
717 break;
718 case Token::VOLATILE:
719 this->nextToken();
720 flags |= Modifiers::kVolatile_Flag;
721 break;
722 case Token::RESTRICT:
723 this->nextToken();
724 flags |= Modifiers::kRestrict_Flag;
725 break;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400726 case Token::BUFFER:
727 this->nextToken();
728 flags |= Modifiers::kBuffer_Flag;
729 break;
Ethan Nicholascb670962017-04-20 19:31:52 -0400730 case Token::HASSIDEEFFECTS:
731 this->nextToken();
732 flags |= Modifiers::kHasSideEffects_Flag;
733 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700734 default:
Ethan Nicholas11d53972016-11-28 11:23:23 -0500735 return Modifiers(layout, flags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700736 }
737 }
738}
739
Ethan Nicholas11d53972016-11-28 11:23:23 -0500740Modifiers Parser::modifiersWithDefaults(int defaultFlags) {
741 Modifiers result = this->modifiers();
ethannicholasb3058bd2016-07-01 08:22:01 -0700742 if (!result.fFlags) {
Ethan Nicholas11d53972016-11-28 11:23:23 -0500743 return Modifiers(result.fLayout, defaultFlags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700744 }
745 return result;
746}
747
748/* ifStatement | forStatement | doStatement | whileStatement | block | expression */
749std::unique_ptr<ASTStatement> Parser::statement() {
750 Token start = this->peek();
751 switch (start.fKind) {
752 case Token::IF:
753 return this->ifStatement();
754 case Token::FOR:
755 return this->forStatement();
756 case Token::DO:
757 return this->doStatement();
758 case Token::WHILE:
759 return this->whileStatement();
Ethan Nicholasaf197692017-02-27 13:26:45 -0500760 case Token::SWITCH:
761 return this->switchStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700762 case Token::RETURN:
763 return this->returnStatement();
764 case Token::BREAK:
765 return this->breakStatement();
766 case Token::CONTINUE:
767 return this->continueStatement();
768 case Token::DISCARD:
769 return this->discardStatement();
770 case Token::LBRACE:
771 return this->block();
772 case Token::SEMICOLON:
Ethan Nicholas11d53972016-11-28 11:23:23 -0500773 this->nextToken();
774 return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition,
ethannicholas0730be72016-09-01 07:59:02 -0700775 std::vector<std::unique_ptr<ASTStatement>>()));
ethannicholasb3058bd2016-07-01 08:22:01 -0700776 case Token::CONST: // fall through
777 case Token::HIGHP: // fall through
778 case Token::MEDIUMP: // fall through
779 case Token::LOWP: {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700780 auto decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700781 if (!decl) {
782 return nullptr;
783 }
784 return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(std::move(decl)));
785 }
786 case Token::IDENTIFIER:
787 if (this->isType(start.fText)) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700788 auto decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700789 if (!decl) {
790 return nullptr;
791 }
792 return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
793 std::move(decl)));
794 }
795 // fall through
796 default:
797 return this->expressionStatement();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500798 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700799}
800
Ethan Nicholas50afc172017-02-16 14:49:57 -0500801/* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* */
ethannicholasb3058bd2016-07-01 08:22:01 -0700802std::unique_ptr<ASTType> Parser::type() {
803 Token type;
804 if (!this->expect(Token::IDENTIFIER, "a type", &type)) {
805 return nullptr;
806 }
807 if (!this->isType(type.fText)) {
808 this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str());
809 return nullptr;
810 }
Ethan Nicholas50afc172017-02-16 14:49:57 -0500811 std::vector<int> sizes;
812 while (this->peek().fKind == Token::LBRACKET) {
813 this->expect(Token::LBRACKET, "'['");
814 if (this->peek().fKind != Token::RBRACKET) {
815 int64_t i;
816 if (this->intLiteral(&i)) {
817 sizes.push_back(i);
818 } else {
819 return nullptr;
820 }
821 } else {
822 sizes.push_back(-1);
823 }
824 this->expect(Token::RBRACKET, "']'");
825 }
Ethan Nicholas11d53972016-11-28 11:23:23 -0500826 return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText),
Ethan Nicholas50afc172017-02-16 14:49:57 -0500827 ASTType::kIdentifier_Kind, sizes));
ethannicholasb3058bd2016-07-01 08:22:01 -0700828}
829
Ethan Nicholas50afc172017-02-16 14:49:57 -0500830/* IDENTIFIER LBRACE varDeclaration* RBRACE (IDENTIFIER (LBRACKET expression? RBRACKET)*)? */
Ethan Nicholas11d53972016-11-28 11:23:23 -0500831std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700832 Token name;
833 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
834 return nullptr;
835 }
836 if (peek().fKind != Token::LBRACE) {
837 // we only get into interfaceBlock if we found a top-level identifier which was not a type.
Ethan Nicholas11d53972016-11-28 11:23:23 -0500838 // 99% of the time, the user was not actually intending to create an interface block, so
ethannicholasb3058bd2016-07-01 08:22:01 -0700839 // it's better to report it as an unknown type
840 this->error(name.fPosition, "no type named '" + name.fText + "'");
841 return nullptr;
842 }
843 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -0500844 std::vector<std::unique_ptr<ASTVarDeclarations>> decls;
ethannicholasb3058bd2016-07-01 08:22:01 -0700845 while (this->peek().fKind != Token::RBRACE) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700846 std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700847 if (!decl) {
848 return nullptr;
849 }
850 decls.push_back(std::move(decl));
851 }
852 this->nextToken();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400853 String instanceName;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500854 std::vector<std::unique_ptr<ASTExpression>> sizes;
ethannicholasb3058bd2016-07-01 08:22:01 -0700855 if (this->peek().fKind == Token::IDENTIFIER) {
Ethan Nicholas50afc172017-02-16 14:49:57 -0500856 instanceName = this->nextToken().fText;
857 while (this->peek().fKind == Token::LBRACKET) {
858 this->expect(Token::LBRACKET, "'['");
859 if (this->peek().fKind != Token::RBRACKET) {
860 std::unique_ptr<ASTExpression> size = this->expression();
861 if (!size) {
862 return nullptr;
863 }
864 sizes.push_back(std::move(size));
865 } else {
866 sizes.push_back(nullptr);
867 }
868 this->expect(Token::RBRACKET, "']'");
869 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700870 }
871 this->expect(Token::SEMICOLON, "';'");
Ethan Nicholas11d53972016-11-28 11:23:23 -0500872 return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods,
Ethan Nicholas50afc172017-02-16 14:49:57 -0500873 name.fText, std::move(decls),
874 std::move(instanceName),
875 std::move(sizes)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700876}
877
878/* IF LPAREN expression RPAREN statement (ELSE statement)? */
879std::unique_ptr<ASTIfStatement> Parser::ifStatement() {
880 Token start;
881 if (!this->expect(Token::IF, "'if'", &start)) {
882 return nullptr;
883 }
884 if (!this->expect(Token::LPAREN, "'('")) {
885 return nullptr;
886 }
887 std::unique_ptr<ASTExpression> test(this->expression());
888 if (!test) {
889 return nullptr;
890 }
891 if (!this->expect(Token::RPAREN, "')'")) {
892 return nullptr;
893 }
894 std::unique_ptr<ASTStatement> ifTrue(this->statement());
895 if (!ifTrue) {
896 return nullptr;
897 }
898 std::unique_ptr<ASTStatement> ifFalse;
899 if (this->peek().fKind == Token::ELSE) {
900 this->nextToken();
901 ifFalse = this->statement();
902 if (!ifFalse) {
903 return nullptr;
904 }
905 }
Ethan Nicholas11d53972016-11-28 11:23:23 -0500906 return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, std::move(test),
907 std::move(ifTrue),
ethannicholasb3058bd2016-07-01 08:22:01 -0700908 std::move(ifFalse)));
909}
910
911/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
912std::unique_ptr<ASTDoStatement> Parser::doStatement() {
913 Token start;
914 if (!this->expect(Token::DO, "'do'", &start)) {
915 return nullptr;
916 }
917 std::unique_ptr<ASTStatement> statement(this->statement());
918 if (!statement) {
919 return nullptr;
920 }
921 if (!this->expect(Token::WHILE, "'while'")) {
922 return nullptr;
923 }
924 if (!this->expect(Token::LPAREN, "'('")) {
925 return nullptr;
926 }
927 std::unique_ptr<ASTExpression> test(this->expression());
928 if (!test) {
929 return nullptr;
930 }
931 if (!this->expect(Token::RPAREN, "')'")) {
932 return nullptr;
933 }
934 if (!this->expect(Token::SEMICOLON, "';'")) {
935 return nullptr;
936 }
Ethan Nicholas11d53972016-11-28 11:23:23 -0500937 return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700938 std::move(statement),
939 std::move(test)));
940}
941
942/* WHILE LPAREN expression RPAREN STATEMENT */
943std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
944 Token start;
945 if (!this->expect(Token::WHILE, "'while'", &start)) {
946 return nullptr;
947 }
948 if (!this->expect(Token::LPAREN, "'('")) {
949 return nullptr;
950 }
951 std::unique_ptr<ASTExpression> test(this->expression());
952 if (!test) {
953 return nullptr;
954 }
955 if (!this->expect(Token::RPAREN, "')'")) {
956 return nullptr;
957 }
958 std::unique_ptr<ASTStatement> statement(this->statement());
959 if (!statement) {
960 return nullptr;
961 }
Ethan Nicholas11d53972016-11-28 11:23:23 -0500962 return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition,
963 std::move(test),
ethannicholasb3058bd2016-07-01 08:22:01 -0700964 std::move(statement)));
965}
966
Ethan Nicholasaf197692017-02-27 13:26:45 -0500967/* CASE expression COLON statement* */
968std::unique_ptr<ASTSwitchCase> Parser::switchCase() {
969 Token start;
970 if (!this->expect(Token::CASE, "'case'", &start)) {
971 return nullptr;
972 }
973 std::unique_ptr<ASTExpression> value = this->expression();
974 if (!value) {
975 return nullptr;
976 }
977 if (!this->expect(Token::COLON, "':'")) {
978 return nullptr;
979 }
980 std::vector<std::unique_ptr<ASTStatement>> statements;
981 while (this->peek().fKind != Token::RBRACE && this->peek().fKind != Token::CASE &&
982 this->peek().fKind != Token::DEFAULT) {
983 std::unique_ptr<ASTStatement> s = this->statement();
984 if (!s) {
985 return nullptr;
986 }
987 statements.push_back(std::move(s));
988 }
989 return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fPosition, std::move(value),
990 std::move(statements)));
991}
992
993/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
994std::unique_ptr<ASTStatement> Parser::switchStatement() {
995 Token start;
996 if (!this->expect(Token::SWITCH, "'switch'", &start)) {
997 return nullptr;
998 }
999 if (!this->expect(Token::LPAREN, "'('")) {
1000 return nullptr;
1001 }
1002 std::unique_ptr<ASTExpression> value(this->expression());
1003 if (!value) {
1004 return nullptr;
1005 }
1006 if (!this->expect(Token::RPAREN, "')'")) {
1007 return nullptr;
1008 }
1009 if (!this->expect(Token::LBRACE, "'{'")) {
1010 return nullptr;
1011 }
1012 std::vector<std::unique_ptr<ASTSwitchCase>> cases;
1013 while (this->peek().fKind == Token::CASE) {
1014 std::unique_ptr<ASTSwitchCase> c = this->switchCase();
1015 if (!c) {
1016 return nullptr;
1017 }
1018 cases.push_back(std::move(c));
1019 }
1020 // Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
1021 // parts of the compiler may rely upon this assumption.
1022 if (this->peek().fKind == Token::DEFAULT) {
1023 Token defaultStart;
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001024 ASSERT_RESULT(this->expect(Token::DEFAULT, "'default'", &defaultStart));
Ethan Nicholasaf197692017-02-27 13:26:45 -05001025 if (!this->expect(Token::COLON, "':'")) {
1026 return nullptr;
1027 }
1028 std::vector<std::unique_ptr<ASTStatement>> statements;
1029 while (this->peek().fKind != Token::RBRACE) {
1030 std::unique_ptr<ASTStatement> s = this->statement();
1031 if (!s) {
1032 return nullptr;
1033 }
1034 statements.push_back(std::move(s));
1035 }
1036 cases.emplace_back(new ASTSwitchCase(defaultStart.fPosition, nullptr,
1037 std::move(statements)));
1038 }
1039 if (!this->expect(Token::RBRACE, "'}'")) {
1040 return nullptr;
1041 }
1042 return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fPosition,
1043 std::move(value),
1044 std::move(cases)));
1045}
1046
Ethan Nicholas11d53972016-11-28 11:23:23 -05001047/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
ethannicholasb3058bd2016-07-01 08:22:01 -07001048 STATEMENT */
1049std::unique_ptr<ASTForStatement> Parser::forStatement() {
1050 Token start;
1051 if (!this->expect(Token::FOR, "'for'", &start)) {
1052 return nullptr;
1053 }
1054 if (!this->expect(Token::LPAREN, "'('")) {
1055 return nullptr;
1056 }
1057 std::unique_ptr<ASTStatement> initializer;
1058 Token nextToken = this->peek();
1059 switch (nextToken.fKind) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001060 case Token::SEMICOLON:
ethannicholas22f939e2016-10-13 13:25:34 -07001061 this->nextToken();
ethannicholasb3058bd2016-07-01 08:22:01 -07001062 break;
ethannicholasa54401d2016-10-14 08:37:32 -07001063 case Token::CONST: {
1064 std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
1065 if (!vd) {
1066 return nullptr;
1067 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001068 initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
ethannicholasa54401d2016-10-14 08:37:32 -07001069 std::move(vd)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001070 break;
ethannicholasa54401d2016-10-14 08:37:32 -07001071 }
1072 case Token::IDENTIFIER: {
ethannicholasb3058bd2016-07-01 08:22:01 -07001073 if (this->isType(nextToken.fText)) {
ethannicholasa54401d2016-10-14 08:37:32 -07001074 std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
1075 if (!vd) {
1076 return nullptr;
1077 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001078 initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
ethannicholasa54401d2016-10-14 08:37:32 -07001079 std::move(vd)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001080 break;
1081 }
ethannicholasa54401d2016-10-14 08:37:32 -07001082 } // fall through
ethannicholasb3058bd2016-07-01 08:22:01 -07001083 default:
1084 initializer = this->expressionStatement();
1085 }
1086 std::unique_ptr<ASTExpression> test;
1087 if (this->peek().fKind != Token::SEMICOLON) {
1088 test = this->expression();
1089 if (!test) {
1090 return nullptr;
1091 }
1092 }
1093 if (!this->expect(Token::SEMICOLON, "';'")) {
1094 return nullptr;
1095 }
1096 std::unique_ptr<ASTExpression> next;
ethannicholas22f939e2016-10-13 13:25:34 -07001097 if (this->peek().fKind != Token::RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001098 next = this->expression();
1099 if (!next) {
1100 return nullptr;
1101 }
1102 }
1103 if (!this->expect(Token::RPAREN, "')'")) {
1104 return nullptr;
1105 }
1106 std::unique_ptr<ASTStatement> statement(this->statement());
1107 if (!statement) {
1108 return nullptr;
1109 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001110 return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -07001111 std::move(initializer),
1112 std::move(test), std::move(next),
1113 std::move(statement)));
1114}
1115
1116/* RETURN expression? SEMICOLON */
1117std::unique_ptr<ASTReturnStatement> Parser::returnStatement() {
1118 Token start;
1119 if (!this->expect(Token::RETURN, "'return'", &start)) {
1120 return nullptr;
1121 }
1122 std::unique_ptr<ASTExpression> expression;
1123 if (this->peek().fKind != Token::SEMICOLON) {
1124 expression = this->expression();
1125 if (!expression) {
1126 return nullptr;
1127 }
1128 }
1129 if (!this->expect(Token::SEMICOLON, "';'")) {
1130 return nullptr;
1131 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001132 return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -07001133 std::move(expression)));
1134}
1135
1136/* BREAK SEMICOLON */
1137std::unique_ptr<ASTBreakStatement> Parser::breakStatement() {
1138 Token start;
1139 if (!this->expect(Token::BREAK, "'break'", &start)) {
1140 return nullptr;
1141 }
1142 if (!this->expect(Token::SEMICOLON, "';'")) {
1143 return nullptr;
1144 }
1145 return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fPosition));
1146}
1147
1148/* CONTINUE SEMICOLON */
1149std::unique_ptr<ASTContinueStatement> Parser::continueStatement() {
1150 Token start;
1151 if (!this->expect(Token::CONTINUE, "'continue'", &start)) {
1152 return nullptr;
1153 }
1154 if (!this->expect(Token::SEMICOLON, "';'")) {
1155 return nullptr;
1156 }
1157 return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fPosition));
1158}
1159
1160/* DISCARD SEMICOLON */
1161std::unique_ptr<ASTDiscardStatement> Parser::discardStatement() {
1162 Token start;
1163 if (!this->expect(Token::DISCARD, "'continue'", &start)) {
1164 return nullptr;
1165 }
1166 if (!this->expect(Token::SEMICOLON, "';'")) {
1167 return nullptr;
1168 }
1169 return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fPosition));
1170}
1171
1172/* LBRACE statement* RBRACE */
1173std::unique_ptr<ASTBlock> Parser::block() {
ethannicholascad64162016-10-27 10:54:02 -07001174 AutoDepth depth(this);
1175 if (!depth.checkValid()) {
1176 return nullptr;
1177 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001178 Token start;
1179 if (!this->expect(Token::LBRACE, "'{'", &start)) {
1180 return nullptr;
1181 }
1182 std::vector<std::unique_ptr<ASTStatement>> statements;
1183 for (;;) {
1184 switch (this->peek().fKind) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001185 case Token::RBRACE:
ethannicholasb3058bd2016-07-01 08:22:01 -07001186 this->nextToken();
Ethan Nicholas11d53972016-11-28 11:23:23 -05001187 return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -07001188 std::move(statements)));
Ethan Nicholas11d53972016-11-28 11:23:23 -05001189 case Token::END_OF_FILE:
ethannicholasb3058bd2016-07-01 08:22:01 -07001190 this->error(this->peek().fPosition, "expected '}', but found end of file");
1191 return nullptr;
1192 default: {
1193 std::unique_ptr<ASTStatement> statement = this->statement();
1194 if (!statement) {
1195 return nullptr;
1196 }
1197 statements.push_back(std::move(statement));
1198 }
1199 }
1200 }
1201}
1202
1203/* expression SEMICOLON */
1204std::unique_ptr<ASTExpressionStatement> Parser::expressionStatement() {
1205 std::unique_ptr<ASTExpression> expr = this->expression();
1206 if (expr) {
1207 if (this->expect(Token::SEMICOLON, "';'")) {
1208 ASTExpressionStatement* result = new ASTExpressionStatement(std::move(expr));
1209 return std::unique_ptr<ASTExpressionStatement>(result);
1210 }
1211 }
1212 return nullptr;
1213}
1214
1215/* assignmentExpression */
1216std::unique_ptr<ASTExpression> Parser::expression() {
ethannicholascad64162016-10-27 10:54:02 -07001217 AutoDepth depth(this);
1218 if (!depth.checkValid()) {
1219 return nullptr;
1220 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001221 return this->assignmentExpression();
1222}
1223
1224/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1225 BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1226 assignmentExpression)*
1227 */
1228std::unique_ptr<ASTExpression> Parser::assignmentExpression() {
1229 std::unique_ptr<ASTExpression> result = this->ternaryExpression();
1230 if (!result) {
1231 return nullptr;
1232 }
1233 for (;;) {
1234 switch (this->peek().fKind) {
1235 case Token::EQ: // fall through
1236 case Token::STAREQ: // fall through
1237 case Token::SLASHEQ: // fall through
1238 case Token::PERCENTEQ: // fall through
1239 case Token::PLUSEQ: // fall through
1240 case Token::MINUSEQ: // fall through
1241 case Token::SHLEQ: // fall through
1242 case Token::SHREQ: // fall through
1243 case Token::BITWISEANDEQ: // fall through
1244 case Token::BITWISEXOREQ: // fall through
1245 case Token::BITWISEOREQ: // fall through
1246 case Token::LOGICALANDEQ: // fall through
1247 case Token::LOGICALXOREQ: // fall through
1248 case Token::LOGICALOREQ: {
1249 Token t = this->nextToken();
1250 std::unique_ptr<ASTExpression> right = this->assignmentExpression();
1251 if (!right) {
1252 return nullptr;
1253 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001254 result = std::unique_ptr<ASTExpression>(new ASTBinaryExpression(std::move(result),
1255 t,
ethannicholasb3058bd2016-07-01 08:22:01 -07001256 std::move(right)));
1257 }
1258 default:
1259 return result;
1260 }
1261 }
1262}
1263
1264/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
1265std::unique_ptr<ASTExpression> Parser::ternaryExpression() {
1266 std::unique_ptr<ASTExpression> result = this->logicalOrExpression();
1267 if (!result) {
1268 return nullptr;
1269 }
1270 if (this->peek().fKind == Token::QUESTION) {
1271 Token question = this->nextToken();
1272 std::unique_ptr<ASTExpression> trueExpr = this->expression();
1273 if (!trueExpr) {
1274 return nullptr;
1275 }
1276 if (this->expect(Token::COLON, "':'")) {
1277 std::unique_ptr<ASTExpression> falseExpr = this->assignmentExpression();
Ethan Nicholas11d53972016-11-28 11:23:23 -05001278 return std::unique_ptr<ASTExpression>(new ASTTernaryExpression(std::move(result),
1279 std::move(trueExpr),
ethannicholasb3058bd2016-07-01 08:22:01 -07001280 std::move(falseExpr)));
1281 }
1282 return nullptr;
1283 }
1284 return result;
1285}
1286
1287/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
1288std::unique_ptr<ASTExpression> Parser::logicalOrExpression() {
1289 std::unique_ptr<ASTExpression> result = this->logicalXorExpression();
1290 if (!result) {
1291 return nullptr;
1292 }
1293 while (this->peek().fKind == Token::LOGICALOR) {
1294 Token t = this->nextToken();
1295 std::unique_ptr<ASTExpression> right = this->logicalXorExpression();
1296 if (!right) {
1297 return nullptr;
1298 }
1299 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1300 }
1301 return result;
1302}
1303
1304/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
1305std::unique_ptr<ASTExpression> Parser::logicalXorExpression() {
1306 std::unique_ptr<ASTExpression> result = this->logicalAndExpression();
1307 if (!result) {
1308 return nullptr;
1309 }
1310 while (this->peek().fKind == Token::LOGICALXOR) {
1311 Token t = this->nextToken();
1312 std::unique_ptr<ASTExpression> right = this->logicalAndExpression();
1313 if (!right) {
1314 return nullptr;
1315 }
1316 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1317 }
1318 return result;
1319}
1320
1321/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
1322std::unique_ptr<ASTExpression> Parser::logicalAndExpression() {
1323 std::unique_ptr<ASTExpression> result = this->bitwiseOrExpression();
1324 if (!result) {
1325 return nullptr;
1326 }
1327 while (this->peek().fKind == Token::LOGICALAND) {
1328 Token t = this->nextToken();
1329 std::unique_ptr<ASTExpression> right = this->bitwiseOrExpression();
1330 if (!right) {
1331 return nullptr;
1332 }
1333 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1334 }
1335 return result;
1336}
1337
1338/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
1339std::unique_ptr<ASTExpression> Parser::bitwiseOrExpression() {
1340 std::unique_ptr<ASTExpression> result = this->bitwiseXorExpression();
1341 if (!result) {
1342 return nullptr;
1343 }
1344 while (this->peek().fKind == Token::BITWISEOR) {
1345 Token t = this->nextToken();
1346 std::unique_ptr<ASTExpression> right = this->bitwiseXorExpression();
1347 if (!right) {
1348 return nullptr;
1349 }
1350 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1351 }
1352 return result;
1353}
1354
1355/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
1356std::unique_ptr<ASTExpression> Parser::bitwiseXorExpression() {
1357 std::unique_ptr<ASTExpression> result = this->bitwiseAndExpression();
1358 if (!result) {
1359 return nullptr;
1360 }
1361 while (this->peek().fKind == Token::BITWISEXOR) {
1362 Token t = this->nextToken();
1363 std::unique_ptr<ASTExpression> right = this->bitwiseAndExpression();
1364 if (!right) {
1365 return nullptr;
1366 }
1367 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1368 }
1369 return result;
1370}
1371
1372/* equalityExpression (BITWISEAND equalityExpression)* */
1373std::unique_ptr<ASTExpression> Parser::bitwiseAndExpression() {
1374 std::unique_ptr<ASTExpression> result = this->equalityExpression();
1375 if (!result) {
1376 return nullptr;
1377 }
1378 while (this->peek().fKind == Token::BITWISEAND) {
1379 Token t = this->nextToken();
1380 std::unique_ptr<ASTExpression> right = this->equalityExpression();
1381 if (!right) {
1382 return nullptr;
1383 }
1384 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1385 }
1386 return result;
1387}
1388
1389/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
1390std::unique_ptr<ASTExpression> Parser::equalityExpression() {
1391 std::unique_ptr<ASTExpression> result = this->relationalExpression();
1392 if (!result) {
1393 return nullptr;
1394 }
1395 for (;;) {
1396 switch (this->peek().fKind) {
1397 case Token::EQEQ: // fall through
1398 case Token::NEQ: {
1399 Token t = this->nextToken();
1400 std::unique_ptr<ASTExpression> right = this->relationalExpression();
1401 if (!right) {
1402 return nullptr;
1403 }
1404 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1405 break;
1406 }
1407 default:
1408 return result;
1409 }
1410 }
1411}
1412
1413/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
1414std::unique_ptr<ASTExpression> Parser::relationalExpression() {
1415 std::unique_ptr<ASTExpression> result = this->shiftExpression();
1416 if (!result) {
1417 return nullptr;
1418 }
1419 for (;;) {
1420 switch (this->peek().fKind) {
1421 case Token::LT: // fall through
1422 case Token::GT: // fall through
1423 case Token::LTEQ: // fall through
1424 case Token::GTEQ: {
1425 Token t = this->nextToken();
1426 std::unique_ptr<ASTExpression> right = this->shiftExpression();
1427 if (!right) {
1428 return nullptr;
1429 }
1430 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1431 break;
1432 }
1433 default:
1434 return result;
1435 }
1436 }
1437}
1438
1439/* additiveExpression ((SHL | SHR) additiveExpression)* */
1440std::unique_ptr<ASTExpression> Parser::shiftExpression() {
1441 std::unique_ptr<ASTExpression> result = this->additiveExpression();
1442 if (!result) {
1443 return nullptr;
1444 }
1445 for (;;) {
1446 switch (this->peek().fKind) {
1447 case Token::SHL: // fall through
1448 case Token::SHR: {
1449 Token t = this->nextToken();
1450 std::unique_ptr<ASTExpression> right = this->additiveExpression();
1451 if (!right) {
1452 return nullptr;
1453 }
1454 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1455 break;
1456 }
1457 default:
1458 return result;
1459 }
1460 }
1461}
1462
1463/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
1464std::unique_ptr<ASTExpression> Parser::additiveExpression() {
1465 std::unique_ptr<ASTExpression> result = this->multiplicativeExpression();
1466 if (!result) {
1467 return nullptr;
1468 }
1469 for (;;) {
1470 switch (this->peek().fKind) {
1471 case Token::PLUS: // fall through
1472 case Token::MINUS: {
1473 Token t = this->nextToken();
1474 std::unique_ptr<ASTExpression> right = this->multiplicativeExpression();
1475 if (!right) {
1476 return nullptr;
1477 }
1478 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1479 break;
1480 }
1481 default:
1482 return result;
1483 }
1484 }
1485}
1486
1487/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
1488std::unique_ptr<ASTExpression> Parser::multiplicativeExpression() {
1489 std::unique_ptr<ASTExpression> result = this->unaryExpression();
1490 if (!result) {
1491 return nullptr;
1492 }
1493 for (;;) {
1494 switch (this->peek().fKind) {
1495 case Token::STAR: // fall through
1496 case Token::SLASH: // fall through
1497 case Token::PERCENT: {
1498 Token t = this->nextToken();
1499 std::unique_ptr<ASTExpression> right = this->unaryExpression();
1500 if (!right) {
1501 return nullptr;
1502 }
1503 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1504 break;
1505 }
1506 default:
1507 return result;
1508 }
1509 }
1510}
1511
1512/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
1513std::unique_ptr<ASTExpression> Parser::unaryExpression() {
1514 switch (this->peek().fKind) {
ethannicholas5961bc92016-10-12 06:39:56 -07001515 case Token::PLUS: // fall through
1516 case Token::MINUS: // fall through
1517 case Token::LOGICALNOT: // fall through
1518 case Token::BITWISENOT: // fall through
1519 case Token::PLUSPLUS: // fall through
ethannicholasb3058bd2016-07-01 08:22:01 -07001520 case Token::MINUSMINUS: {
1521 Token t = this->nextToken();
1522 std::unique_ptr<ASTExpression> expr = this->unaryExpression();
1523 if (!expr) {
1524 return nullptr;
1525 }
1526 return std::unique_ptr<ASTExpression>(new ASTPrefixExpression(t, std::move(expr)));
1527 }
1528 default:
1529 return this->postfixExpression();
1530 }
1531}
1532
1533/* term suffix* */
1534std::unique_ptr<ASTExpression> Parser::postfixExpression() {
1535 std::unique_ptr<ASTExpression> result = this->term();
1536 if (!result) {
1537 return nullptr;
1538 }
1539 for (;;) {
1540 switch (this->peek().fKind) {
1541 case Token::LBRACKET: // fall through
1542 case Token::DOT: // fall through
1543 case Token::LPAREN: // fall through
1544 case Token::PLUSPLUS: // fall through
1545 case Token::MINUSMINUS: {
1546 std::unique_ptr<ASTSuffix> s = this->suffix();
1547 if (!s) {
1548 return nullptr;
1549 }
1550 result.reset(new ASTSuffixExpression(std::move(result), std::move(s)));
1551 break;
1552 }
1553 default:
1554 return result;
1555 }
1556 }
1557}
1558
Ethan Nicholas11d53972016-11-28 11:23:23 -05001559/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
ethannicholasb3058bd2016-07-01 08:22:01 -07001560 PLUSPLUS | MINUSMINUS */
1561std::unique_ptr<ASTSuffix> Parser::suffix() {
1562 Token next = this->nextToken();
1563 switch (next.fKind) {
1564 case Token::LBRACKET: {
ethannicholas5961bc92016-10-12 06:39:56 -07001565 if (this->peek().fKind == Token::RBRACKET) {
1566 this->nextToken();
1567 return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fPosition));
1568 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001569 std::unique_ptr<ASTExpression> e = this->expression();
1570 if (!e) {
1571 return nullptr;
1572 }
1573 this->expect(Token::RBRACKET, "']' to complete array access expression");
1574 return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e)));
1575 }
1576 case Token::DOT: {
1577 Position pos = this->peek().fPosition;
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001578 String text;
ethannicholasb3058bd2016-07-01 08:22:01 -07001579 if (this->identifier(&text)) {
1580 return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(pos, std::move(text)));
1581 }
1582 return nullptr;
1583 }
1584 case Token::LPAREN: {
1585 std::vector<std::unique_ptr<ASTExpression>> parameters;
1586 if (this->peek().fKind != Token::RPAREN) {
1587 for (;;) {
1588 std::unique_ptr<ASTExpression> expr = this->expression();
1589 if (!expr) {
1590 return nullptr;
1591 }
1592 parameters.push_back(std::move(expr));
1593 if (this->peek().fKind != Token::COMMA) {
1594 break;
1595 }
1596 this->nextToken();
1597 }
1598 }
1599 this->expect(Token::RPAREN, "')' to complete function parameters");
Ethan Nicholas11d53972016-11-28 11:23:23 -05001600 return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -07001601 std::move(parameters)));
1602 }
1603 case Token::PLUSPLUS:
Ethan Nicholas11d53972016-11-28 11:23:23 -05001604 return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -07001605 ASTSuffix::kPostIncrement_Kind));
1606 case Token::MINUSMINUS:
1607 return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
1608 ASTSuffix::kPostDecrement_Kind));
1609 default: {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001610 this->error(next.fPosition, "expected expression suffix, but found '" + next.fText +
ethannicholasb3058bd2016-07-01 08:22:01 -07001611 "'\n");
1612 return nullptr;
1613 }
1614 }
1615}
1616
1617/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */
1618std::unique_ptr<ASTExpression> Parser::term() {
1619 std::unique_ptr<ASTExpression> result;
1620 Token t = this->peek();
1621 switch (t.fKind) {
1622 case Token::IDENTIFIER: {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001623 String text;
ethannicholasb3058bd2016-07-01 08:22:01 -07001624 if (this->identifier(&text)) {
1625 result.reset(new ASTIdentifier(t.fPosition, std::move(text)));
1626 }
1627 break;
1628 }
1629 case Token::INT_LITERAL: {
1630 int64_t i;
1631 if (this->intLiteral(&i)) {
1632 result.reset(new ASTIntLiteral(t.fPosition, i));
1633 }
1634 break;
1635 }
1636 case Token::FLOAT_LITERAL: {
1637 double f;
1638 if (this->floatLiteral(&f)) {
1639 result.reset(new ASTFloatLiteral(t.fPosition, f));
1640 }
1641 break;
1642 }
1643 case Token::TRUE_LITERAL: // fall through
1644 case Token::FALSE_LITERAL: {
1645 bool b;
1646 if (this->boolLiteral(&b)) {
1647 result.reset(new ASTBoolLiteral(t.fPosition, b));
1648 }
1649 break;
1650 }
1651 case Token::LPAREN: {
1652 this->nextToken();
1653 result = this->expression();
1654 if (result) {
1655 this->expect(Token::RPAREN, "')' to complete expression");
1656 }
1657 break;
1658 }
1659 default:
1660 this->nextToken();
1661 this->error(t.fPosition, "expected expression, but found '" + t.fText + "'\n");
1662 result = nullptr;
1663 }
1664 return result;
1665}
1666
1667/* INT_LITERAL */
1668bool Parser::intLiteral(int64_t* dest) {
1669 Token t;
1670 if (this->expect(Token::INT_LITERAL, "integer literal", &t)) {
1671 *dest = SkSL::stol(t.fText);
1672 return true;
1673 }
1674 return false;
1675}
1676
1677/* FLOAT_LITERAL */
1678bool Parser::floatLiteral(double* dest) {
1679 Token t;
1680 if (this->expect(Token::FLOAT_LITERAL, "float literal", &t)) {
1681 *dest = SkSL::stod(t.fText);
1682 return true;
1683 }
1684 return false;
1685}
1686
1687/* TRUE_LITERAL | FALSE_LITERAL */
1688bool Parser::boolLiteral(bool* dest) {
1689 Token t = this->nextToken();
1690 switch (t.fKind) {
1691 case Token::TRUE_LITERAL:
1692 *dest = true;
1693 return true;
1694 case Token::FALSE_LITERAL:
1695 *dest = false;
1696 return true;
1697 default:
1698 this->error(t.fPosition, "expected 'true' or 'false', but found '" + t.fText + "'\n");
1699 return false;
1700 }
1701}
1702
1703/* IDENTIFIER */
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001704bool Parser::identifier(String* dest) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001705 Token t;
1706 if (this->expect(Token::IDENTIFIER, "identifier", &t)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001707 *dest = t.fText;
ethannicholasb3058bd2016-07-01 08:22:01 -07001708 return true;
1709 }
1710 return false;
1711}
1712
1713} // namespace