blob: 2be664dbd8fcc266c2b186d9ff9fd9f0af9d01a5 [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 */
7
8#include "stdio.h"
9#include "SkSLParser.h"
10#include "SkSLToken.h"
11
12#define register
13#ifdef __clang__
14#pragma clang diagnostic push
15#pragma clang diagnostic ignored "-Wunneeded-internal-declaration"
ethannicholas8e5a5882016-07-06 06:55:44 -070016#pragma clang diagnostic ignored "-Wnull-conversion"
ethannicholasf789b382016-08-03 12:43:36 -070017#pragma clang diagnostic ignored "-Wsign-compare"
18#endif
19#ifdef __GNUC__
20#pragma GCC diagnostic push
21#pragma GCC diagnostic ignored "-Wsign-compare"
22#endif
23#ifdef _MSC_VER
24#pragma warning(push)
25#pragma warning(disable:4018)
ethannicholasb3058bd2016-07-01 08:22:01 -070026#endif
27#include "lex.sksl.c"
28#ifdef __clang__
29#pragma clang diagnostic pop
30#endif
ethannicholasf789b382016-08-03 12:43:36 -070031#ifdef __GNUC__
32#pragma GCC diagnostic pop
33#endif
34#ifdef _MSC_VER
35#pragma warning(pop)
36#endif
ethannicholasb3058bd2016-07-01 08:22:01 -070037#undef register
38
39#include "ast/SkSLASTBinaryExpression.h"
40#include "ast/SkSLASTBlock.h"
41#include "ast/SkSLASTBoolLiteral.h"
42#include "ast/SkSLASTBreakStatement.h"
43#include "ast/SkSLASTCallSuffix.h"
44#include "ast/SkSLASTContinueStatement.h"
45#include "ast/SkSLASTDiscardStatement.h"
46#include "ast/SkSLASTDoStatement.h"
47#include "ast/SkSLASTExpression.h"
48#include "ast/SkSLASTExpressionStatement.h"
49#include "ast/SkSLASTExtension.h"
50#include "ast/SkSLASTFieldSuffix.h"
51#include "ast/SkSLASTFloatLiteral.h"
52#include "ast/SkSLASTForStatement.h"
53#include "ast/SkSLASTFunction.h"
54#include "ast/SkSLASTIdentifier.h"
55#include "ast/SkSLASTIfStatement.h"
56#include "ast/SkSLASTIndexSuffix.h"
57#include "ast/SkSLASTInterfaceBlock.h"
58#include "ast/SkSLASTIntLiteral.h"
ethannicholas5961bc92016-10-12 06:39:56 -070059#include "ast/SkSLASTModifiersDeclaration.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070060#include "ast/SkSLASTParameter.h"
ethannicholas5961bc92016-10-12 06:39:56 -070061#include "ast/SkSLASTPrecision.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070062#include "ast/SkSLASTPrefixExpression.h"
63#include "ast/SkSLASTReturnStatement.h"
64#include "ast/SkSLASTStatement.h"
65#include "ast/SkSLASTSuffixExpression.h"
66#include "ast/SkSLASTTernaryExpression.h"
67#include "ast/SkSLASTType.h"
68#include "ast/SkSLASTVarDeclaration.h"
69#include "ast/SkSLASTVarDeclarationStatement.h"
70#include "ast/SkSLASTWhileStatement.h"
71#include "ir/SkSLSymbolTable.h"
ethannicholasd598f792016-07-25 10:08:54 -070072#include "ir/SkSLType.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070073
74namespace SkSL {
75
ethannicholascad64162016-10-27 10:54:02 -070076#define MAX_PARSE_DEPTH 50
77
78class AutoDepth {
79public:
80 AutoDepth(Parser* p)
81 : fParser(p) {
82 fParser->fDepth++;
83 }
84
85 ~AutoDepth() {
86 fParser->fDepth--;
87 }
88
89 bool checkValid() {
90 if (fParser->fDepth > MAX_PARSE_DEPTH) {
91 fParser->error(fParser->peek().fPosition, "exceeded max parse depth");
92 return false;
93 }
94 return true;
95 }
96
97private:
98 Parser* fParser;
99};
100
ethannicholasb3058bd2016-07-01 08:22:01 -0700101Parser::Parser(std::string text, SymbolTable& types, ErrorReporter& errors)
102: fPushback(Position(-1, -1), Token::INVALID_TOKEN, "")
103, fTypes(types)
104, fErrors(errors) {
105 sksllex_init(&fScanner);
106 fBuffer = sksl_scan_string(text.c_str(), fScanner);
107 skslset_lineno(1, fScanner);
108
109 if (false) {
110 // avoid unused warning
111 yyunput(0, nullptr, fScanner);
112 }
113}
114
115Parser::~Parser() {
116 sksl_delete_buffer(fBuffer, fScanner);
ethannicholas69a7e7c2016-07-01 19:09:27 -0700117 sksllex_destroy(fScanner);
ethannicholasb3058bd2016-07-01 08:22:01 -0700118}
119
120/* (precision | directive | declaration)* END_OF_FILE */
121std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
122 std::vector<std::unique_ptr<ASTDeclaration>> result;
123 for (;;) {
124 switch (this->peek().fKind) {
125 case Token::END_OF_FILE:
126 return result;
ethannicholas5961bc92016-10-12 06:39:56 -0700127 case Token::PRECISION: {
128 std::unique_ptr<ASTDeclaration> precision = this->precision();
129 if (precision) {
130 result.push_back(std::move(precision));
131 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700132 break;
ethannicholas5961bc92016-10-12 06:39:56 -0700133 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700134 case Token::DIRECTIVE: {
135 std::unique_ptr<ASTDeclaration> decl = this->directive();
136 if (decl) {
137 result.push_back(std::move(decl));
138 }
139 break;
140 }
141 default: {
142 std::unique_ptr<ASTDeclaration> decl = this->declaration();
143 if (!decl) {
144 continue;
145 }
146 result.push_back(std::move(decl));
147 }
148 }
149 }
150}
151
152Token Parser::nextToken() {
153 if (fPushback.fKind != Token::INVALID_TOKEN) {
154 Token result = fPushback;
155 fPushback.fKind = Token::INVALID_TOKEN;
156 fPushback.fText = "";
157 return result;
158 }
159 int token = sksllex(fScanner);
ethannicholas471e8942016-10-28 09:02:46 -0700160 std::string text;
161 switch ((Token::Kind) token) {
162 case Token::IDENTIFIER: // fall through
163 case Token::INT_LITERAL: // fall through
164 case Token::FLOAT_LITERAL: // fall through
165 case Token::DIRECTIVE:
166 text = std::string(skslget_text(fScanner));
167 break;
168 default:
169 break;
170 }
171 return Token(Position(skslget_lineno(fScanner), -1), (Token::Kind) token, text);
ethannicholasb3058bd2016-07-01 08:22:01 -0700172}
173
174void Parser::pushback(Token t) {
175 ASSERT(fPushback.fKind == Token::INVALID_TOKEN);
176 fPushback = t;
177}
178
179Token Parser::peek() {
180 fPushback = this->nextToken();
181 return fPushback;
182}
183
184bool Parser::expect(Token::Kind kind, std::string expected, Token* result) {
185 Token next = this->nextToken();
186 if (next.fKind == kind) {
187 if (result) {
188 *result = next;
189 }
190 return true;
191 } else {
192 this->error(next.fPosition, "expected " + expected + ", but found '" + next.fText + "'");
193 return false;
194 }
195}
196
197void Parser::error(Position p, std::string msg) {
198 fErrors.error(p, msg);
199}
200
201bool Parser::isType(std::string name) {
202 return nullptr != fTypes[name];
203}
204
205/* PRECISION (LOWP | MEDIUMP | HIGHP) type SEMICOLON */
ethannicholas5961bc92016-10-12 06:39:56 -0700206std::unique_ptr<ASTDeclaration> Parser::precision() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700207 if (!this->expect(Token::PRECISION, "'precision'")) {
ethannicholas5961bc92016-10-12 06:39:56 -0700208 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700209 }
ethannicholas5961bc92016-10-12 06:39:56 -0700210 Modifiers::Flag result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700211 Token p = this->nextToken();
212 switch (p.fKind) {
ethannicholas5961bc92016-10-12 06:39:56 -0700213 case Token::LOWP:
214 result = Modifiers::kLowp_Flag;
215 break;
216 case Token::MEDIUMP:
217 result = Modifiers::kMediump_Flag;
218 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700219 case Token::HIGHP:
ethannicholas5961bc92016-10-12 06:39:56 -0700220 result = Modifiers::kHighp_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700221 break;
222 default:
223 this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" +
224 p.fText + "'");
ethannicholas5961bc92016-10-12 06:39:56 -0700225 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700226 }
ethannicholas5961bc92016-10-12 06:39:56 -0700227 // FIXME handle the type
ethannicholasb3058bd2016-07-01 08:22:01 -0700228 if (!this->type()) {
ethannicholas5961bc92016-10-12 06:39:56 -0700229 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700230 }
231 this->expect(Token::SEMICOLON, "';'");
ethannicholas5961bc92016-10-12 06:39:56 -0700232 return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result));
ethannicholasb3058bd2016-07-01 08:22:01 -0700233}
234
ethannicholas5961bc92016-10-12 06:39:56 -0700235/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
236 DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
ethannicholasb3058bd2016-07-01 08:22:01 -0700237std::unique_ptr<ASTDeclaration> Parser::directive() {
238 Token start;
239 if (!this->expect(Token::DIRECTIVE, "a directive", &start)) {
240 return nullptr;
241 }
242 if (start.fText == "#version") {
243 this->expect(Token::INT_LITERAL, "a version number");
ethannicholas5961bc92016-10-12 06:39:56 -0700244 Token next = this->peek();
245 if (next.fText == "es" || next.fText == "compatibility") {
246 this->nextToken();
247 }
248 // version is ignored for now; it will eventually become an error when we stop pretending
249 // to be GLSL
ethannicholasb3058bd2016-07-01 08:22:01 -0700250 return nullptr;
251 } else if (start.fText == "#extension") {
252 Token name;
253 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
254 return nullptr;
255 }
256 if (!this->expect(Token::COLON, "':'")) {
257 return nullptr;
258 }
259 // FIXME: need to start paying attention to this token
260 if (!this->expect(Token::IDENTIFIER, "an identifier")) {
261 return nullptr;
262 }
263 return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition,
264 std::move(name.fText)));
265 } else {
266 this->error(start.fPosition, "unsupported directive '" + start.fText + "'");
267 return nullptr;
268 }
269}
270
271/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
272 (COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
273std::unique_ptr<ASTDeclaration> Parser::declaration() {
274 ASTModifiers modifiers = this->modifiers();
275 Token lookahead = this->peek();
276 if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) {
277 // we have an identifier that's not a type, could be the start of an interface block
278 return this->interfaceBlock(modifiers);
279 }
280 if (lookahead.fKind == Token::STRUCT) {
281 return this->structVarDeclaration(modifiers);
282 }
ethannicholas5961bc92016-10-12 06:39:56 -0700283 if (lookahead.fKind == Token::SEMICOLON) {
284 this->nextToken();
285 return std::unique_ptr<ASTDeclaration>(new ASTModifiersDeclaration(modifiers));
286 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700287 std::unique_ptr<ASTType> type(this->type());
288 if (!type) {
289 return nullptr;
290 }
291 if (type->fKind == ASTType::kStruct_Kind && peek().fKind == Token::SEMICOLON) {
292 this->nextToken();
293 return nullptr;
294 }
295 Token name;
296 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
297 return nullptr;
298 }
299 if (!modifiers.fFlags && this->peek().fKind == Token::LPAREN) {
300 this->nextToken();
301 std::vector<std::unique_ptr<ASTParameter>> parameters;
302 while (this->peek().fKind != Token::RPAREN) {
303 if (parameters.size() > 0) {
304 if (!this->expect(Token::COMMA, "','")) {
305 return nullptr;
306 }
307 }
308 std::unique_ptr<ASTParameter> parameter = this->parameter();
309 if (!parameter) {
310 return nullptr;
311 }
312 parameters.push_back(std::move(parameter));
313 }
314 this->nextToken();
315 std::unique_ptr<ASTBlock> body;
316 if (this->peek().fKind == Token::SEMICOLON) {
317 this->nextToken();
318 } else {
319 body = this->block();
320 if (!body) {
321 return nullptr;
322 }
323 }
324 return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition, std::move(type),
325 std::move(name.fText),
326 std::move(parameters),
327 std::move(body)));
328 } else {
329 return this->varDeclarationEnd(modifiers, std::move(type), name.fText);
330 }
331}
332
333/* modifiers type IDENTIFIER varDeclarationEnd */
ethannicholas14fe8cc2016-09-07 13:37:16 -0700334std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700335 ASTModifiers modifiers = this->modifiers();
336 std::unique_ptr<ASTType> type(this->type());
337 if (!type) {
338 return nullptr;
339 }
340 Token name;
341 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
342 return nullptr;
343 }
344 return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText));
345}
346
347/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
348std::unique_ptr<ASTType> Parser::structDeclaration() {
349 if (!this->expect(Token::STRUCT, "'struct'")) {
350 return nullptr;
351 }
352 Token name;
353 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
354 return nullptr;
355 }
356 if (!this->expect(Token::LBRACE, "'{'")) {
357 return nullptr;
358 }
359 std::vector<Type::Field> fields;
360 while (this->peek().fKind != Token::RBRACE) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700361 std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700362 if (!decl) {
363 return nullptr;
364 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700365 for (const auto& var : decl->fVars) {
ethannicholasd598f792016-07-25 10:08:54 -0700366 auto type = (const Type*) fTypes[decl->fType->fName];
ethannicholas14fe8cc2016-09-07 13:37:16 -0700367 for (int i = (int) var.fSizes.size() - 1; i >= 0; i--) {
ethannicholasdd4645b2016-10-14 12:14:46 -0700368 if (!var.fSizes[i] || var.fSizes[i]->fKind != ASTExpression::kInt_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700369 this->error(decl->fPosition, "array size in struct field must be a constant");
ethannicholasdd4645b2016-10-14 12:14:46 -0700370 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700371 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700372 uint64_t columns = ((ASTIntLiteral&) *var.fSizes[i]).fValue;
ethannicholasb3058bd2016-07-01 08:22:01 -0700373 std::string name = type->name() + "[" + to_string(columns) + "]";
ethannicholasd598f792016-07-25 10:08:54 -0700374 type = new Type(name, Type::kArray_Kind, *type, (int) columns);
375 fTypes.takeOwnership((Type*) type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700376 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700377 fields.push_back(Type::Field(decl->fModifiers, var.fName, type));
378 if (var.fValue) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700379 this->error(decl->fPosition, "initializers are not permitted on struct fields");
380 }
381 }
382 }
383 if (!this->expect(Token::RBRACE, "'}'")) {
384 return nullptr;
385 }
ethannicholasd598f792016-07-25 10:08:54 -0700386 fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fText, fields)));
387 return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText,
ethannicholasb3058bd2016-07-01 08:22:01 -0700388 ASTType::kStruct_Kind));
389}
390
391/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
ethannicholas14fe8cc2016-09-07 13:37:16 -0700392std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(ASTModifiers modifiers) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700393 std::unique_ptr<ASTType> type = this->structDeclaration();
394 if (!type) {
395 return nullptr;
396 }
397 if (peek().fKind == Token::IDENTIFIER) {
398 Token name = this->nextToken();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700399 std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers,
400 std::move(type),
401 std::move(name.fText));
ethannicholasb3058bd2016-07-01 08:22:01 -0700402 if (result) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700403 for (const auto& var : result->fVars) {
404 if (var.fValue) {
405 this->error(var.fValue->fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700406 "struct variables cannot be initialized");
407 }
408 }
409 }
410 return result;
411 }
412 this->expect(Token::SEMICOLON, "';'");
413 return nullptr;
414}
415
416/* (LBRACKET expression? RBRACKET)* (EQ expression)? (COMMA IDENTIFER
417 (LBRACKET expression? RBRACKET)* (EQ expression)?)* SEMICOLON */
ethannicholas14fe8cc2016-09-07 13:37:16 -0700418std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(ASTModifiers mods,
419 std::unique_ptr<ASTType> type,
420 std::string name) {
421 std::vector<ASTVarDeclaration> vars;
ethannicholasb3058bd2016-07-01 08:22:01 -0700422 std::vector<std::unique_ptr<ASTExpression>> currentVarSizes;
423 while (this->peek().fKind == Token::LBRACKET) {
424 this->nextToken();
425 if (this->peek().fKind == Token::RBRACKET) {
426 this->nextToken();
427 currentVarSizes.push_back(nullptr);
428 } else {
429 std::unique_ptr<ASTExpression> size(this->expression());
430 if (!size) {
431 return nullptr;
432 }
433 currentVarSizes.push_back(std::move(size));
434 if (!this->expect(Token::RBRACKET, "']'")) {
435 return nullptr;
436 }
437 }
438 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700439 std::unique_ptr<ASTExpression> value;
ethannicholasb3058bd2016-07-01 08:22:01 -0700440 if (this->peek().fKind == Token::EQ) {
441 this->nextToken();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700442 value = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700443 if (!value) {
444 return nullptr;
445 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700446 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700447 vars.emplace_back(std::move(name), std::move(currentVarSizes), std::move(value));
ethannicholasb3058bd2016-07-01 08:22:01 -0700448 while (this->peek().fKind == Token::COMMA) {
449 this->nextToken();
450 Token name;
451 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
452 return nullptr;
453 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700454 currentVarSizes.clear();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700455 value.reset();
ethannicholasb3058bd2016-07-01 08:22:01 -0700456 while (this->peek().fKind == Token::LBRACKET) {
457 this->nextToken();
458 if (this->peek().fKind == Token::RBRACKET) {
459 this->nextToken();
460 currentVarSizes.push_back(nullptr);
461 } else {
462 std::unique_ptr<ASTExpression> size(this->expression());
463 if (!size) {
464 return nullptr;
465 }
466 currentVarSizes.push_back(std::move(size));
467 if (!this->expect(Token::RBRACKET, "']'")) {
468 return nullptr;
469 }
470 }
471 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700472 if (this->peek().fKind == Token::EQ) {
473 this->nextToken();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700474 value = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700475 if (!value) {
476 return nullptr;
477 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700478 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700479 vars.emplace_back(std::move(name.fText), std::move(currentVarSizes), std::move(value));
ethannicholasb3058bd2016-07-01 08:22:01 -0700480 }
481 if (!this->expect(Token::SEMICOLON, "';'")) {
482 return nullptr;
483 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700484 return std::unique_ptr<ASTVarDeclarations>(new ASTVarDeclarations(std::move(mods),
485 std::move(type),
486 std::move(vars)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700487}
488
489/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
490std::unique_ptr<ASTParameter> Parser::parameter() {
491 ASTModifiers modifiers = this->modifiersWithDefaults(ASTModifiers::kIn_Flag);
492 std::unique_ptr<ASTType> type = this->type();
493 if (!type) {
494 return nullptr;
495 }
496 Token name;
497 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
498 return nullptr;
499 }
500 std::vector<int> sizes;
501 while (this->peek().fKind == Token::LBRACKET) {
502 this->nextToken();
503 Token sizeToken;
504 if (!this->expect(Token::INT_LITERAL, "a positive integer", &sizeToken)) {
505 return nullptr;
506 }
507 sizes.push_back(SkSL::stoi(sizeToken.fText));
508 if (!this->expect(Token::RBRACKET, "']'")) {
509 return nullptr;
510 }
511 }
512 return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers,
513 std::move(type), name.fText,
514 std::move(sizes)));
515}
516
517/** (EQ INT_LITERAL)? */
518int Parser::layoutInt() {
519 if (!this->expect(Token::EQ, "'='")) {
520 return -1;
521 }
522 Token resultToken;
523 if (this->expect(Token::INT_LITERAL, "a non-negative integer", &resultToken)) {
524 return SkSL::stoi(resultToken.fText);
525 }
526 return -1;
527}
528
egdaniel988283c2016-11-16 07:29:51 -0800529/* LAYOUT LPAREN IDENTIFIER EQ INT_LITERAL (COMMA IDENTIFIER EQ INT_LITERAL)*
530 RPAREN */
ethannicholasb3058bd2016-07-01 08:22:01 -0700531ASTLayout Parser::layout() {
532 int location = -1;
533 int binding = -1;
534 int index = -1;
535 int set = -1;
536 int builtin = -1;
ethannicholasf789b382016-08-03 12:43:36 -0700537 bool originUpperLeft = false;
ethannicholas5961bc92016-10-12 06:39:56 -0700538 bool overrideCoverage = false;
539 bool blendSupportAllEquations = false;
Brian Salomon2a51de82016-11-16 12:06:01 -0500540 ASTLayout::Format format = ASTLayout::Format::kUnspecified;
ethannicholasb3058bd2016-07-01 08:22:01 -0700541 if (this->peek().fKind == Token::LAYOUT) {
542 this->nextToken();
543 if (!this->expect(Token::LPAREN, "'('")) {
ethannicholas5961bc92016-10-12 06:39:56 -0700544 return ASTLayout(location, binding, index, set, builtin, originUpperLeft,
Brian Salomon2a51de82016-11-16 12:06:01 -0500545 overrideCoverage, blendSupportAllEquations, format);
ethannicholasb3058bd2016-07-01 08:22:01 -0700546 }
547 for (;;) {
548 Token t = this->nextToken();
549 if (t.fText == "location") {
550 location = this->layoutInt();
551 } else if (t.fText == "binding") {
552 binding = this->layoutInt();
553 } else if (t.fText == "index") {
554 index = this->layoutInt();
555 } else if (t.fText == "set") {
556 set = this->layoutInt();
557 } else if (t.fText == "builtin") {
558 builtin = this->layoutInt();
ethannicholasf789b382016-08-03 12:43:36 -0700559 } else if (t.fText == "origin_upper_left") {
560 originUpperLeft = true;
ethannicholas5961bc92016-10-12 06:39:56 -0700561 } else if (t.fText == "override_coverage") {
562 overrideCoverage = true;
563 } else if (t.fText == "blend_support_all_equations") {
564 blendSupportAllEquations = true;
Brian Salomon2a51de82016-11-16 12:06:01 -0500565 } else if (ASTLayout::ReadFormat(t.fText, &format)) {
566 // AST::ReadFormat stored the result in 'format'.
ethannicholasb3058bd2016-07-01 08:22:01 -0700567 } else {
568 this->error(t.fPosition, ("'" + t.fText +
569 "' is not a valid layout qualifier").c_str());
570 }
571 if (this->peek().fKind == Token::RPAREN) {
572 this->nextToken();
573 break;
574 }
575 if (!this->expect(Token::COMMA, "','")) {
576 break;
577 }
578 }
579 }
ethannicholas5961bc92016-10-12 06:39:56 -0700580 return ASTLayout(location, binding, index, set, builtin, originUpperLeft, overrideCoverage,
Brian Salomon2a51de82016-11-16 12:06:01 -0500581 blendSupportAllEquations, format);
ethannicholasb3058bd2016-07-01 08:22:01 -0700582}
583
ethannicholasf789b382016-08-03 12:43:36 -0700584/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE)* */
ethannicholasb3058bd2016-07-01 08:22:01 -0700585ASTModifiers Parser::modifiers() {
586 ASTLayout layout = this->layout();
587 int flags = 0;
588 for (;;) {
589 // TODO: handle duplicate / incompatible flags
590 switch (peek().fKind) {
591 case Token::UNIFORM:
592 this->nextToken();
593 flags |= ASTModifiers::kUniform_Flag;
594 break;
595 case Token::CONST:
596 this->nextToken();
597 flags |= ASTModifiers::kConst_Flag;
598 break;
599 case Token::IN:
600 this->nextToken();
601 flags |= ASTModifiers::kIn_Flag;
602 break;
603 case Token::OUT:
604 this->nextToken();
605 flags |= ASTModifiers::kOut_Flag;
606 break;
607 case Token::INOUT:
608 this->nextToken();
609 flags |= ASTModifiers::kIn_Flag;
610 flags |= ASTModifiers::kOut_Flag;
611 break;
612 case Token::LOWP:
613 this->nextToken();
614 flags |= ASTModifiers::kLowp_Flag;
615 break;
616 case Token::MEDIUMP:
617 this->nextToken();
618 flags |= ASTModifiers::kMediump_Flag;
619 break;
620 case Token::HIGHP:
621 this->nextToken();
622 flags |= ASTModifiers::kHighp_Flag;
623 break;
ethannicholasf789b382016-08-03 12:43:36 -0700624 case Token::FLAT:
625 this->nextToken();
626 flags |= ASTModifiers::kFlat_Flag;
627 break;
628 case Token::NOPERSPECTIVE:
629 this->nextToken();
630 flags |= ASTModifiers::kNoPerspective_Flag;
631 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700632 default:
633 return ASTModifiers(layout, flags);
634 }
635 }
636}
637
638ASTModifiers Parser::modifiersWithDefaults(int defaultFlags) {
639 ASTModifiers result = this->modifiers();
640 if (!result.fFlags) {
641 return ASTModifiers(result.fLayout, defaultFlags);
642 }
643 return result;
644}
645
646/* ifStatement | forStatement | doStatement | whileStatement | block | expression */
647std::unique_ptr<ASTStatement> Parser::statement() {
648 Token start = this->peek();
649 switch (start.fKind) {
650 case Token::IF:
651 return this->ifStatement();
652 case Token::FOR:
653 return this->forStatement();
654 case Token::DO:
655 return this->doStatement();
656 case Token::WHILE:
657 return this->whileStatement();
658 case Token::RETURN:
659 return this->returnStatement();
660 case Token::BREAK:
661 return this->breakStatement();
662 case Token::CONTINUE:
663 return this->continueStatement();
664 case Token::DISCARD:
665 return this->discardStatement();
666 case Token::LBRACE:
667 return this->block();
668 case Token::SEMICOLON:
669 this->nextToken();
ethannicholas0730be72016-09-01 07:59:02 -0700670 return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition,
671 std::vector<std::unique_ptr<ASTStatement>>()));
ethannicholasb3058bd2016-07-01 08:22:01 -0700672 case Token::CONST: // fall through
673 case Token::HIGHP: // fall through
674 case Token::MEDIUMP: // fall through
675 case Token::LOWP: {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700676 auto decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700677 if (!decl) {
678 return nullptr;
679 }
680 return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(std::move(decl)));
681 }
682 case Token::IDENTIFIER:
683 if (this->isType(start.fText)) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700684 auto decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700685 if (!decl) {
686 return nullptr;
687 }
688 return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
689 std::move(decl)));
690 }
691 // fall through
692 default:
693 return this->expressionStatement();
694 }
695}
696
697/* IDENTIFIER(type) */
698std::unique_ptr<ASTType> Parser::type() {
699 Token type;
700 if (!this->expect(Token::IDENTIFIER, "a type", &type)) {
701 return nullptr;
702 }
703 if (!this->isType(type.fText)) {
704 this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str());
705 return nullptr;
706 }
707 return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText),
708 ASTType::kIdentifier_Kind));
709}
710
711/* IDENTIFIER LBRACE varDeclaration* RBRACE */
712std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(ASTModifiers mods) {
713 Token name;
714 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
715 return nullptr;
716 }
717 if (peek().fKind != Token::LBRACE) {
718 // we only get into interfaceBlock if we found a top-level identifier which was not a type.
719 // 99% of the time, the user was not actually intending to create an interface block, so
720 // it's better to report it as an unknown type
721 this->error(name.fPosition, "no type named '" + name.fText + "'");
722 return nullptr;
723 }
724 this->nextToken();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700725 std::vector<std::unique_ptr<ASTVarDeclarations>> decls;
ethannicholasb3058bd2016-07-01 08:22:01 -0700726 while (this->peek().fKind != Token::RBRACE) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700727 std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700728 if (!decl) {
729 return nullptr;
730 }
731 decls.push_back(std::move(decl));
732 }
733 this->nextToken();
734 std::string valueName;
735 if (this->peek().fKind == Token::IDENTIFIER) {
736 valueName = this->nextToken().fText;
737 }
738 this->expect(Token::SEMICOLON, "';'");
739 return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods,
740 name.fText, std::move(valueName),
741 std::move(decls)));
742}
743
744/* IF LPAREN expression RPAREN statement (ELSE statement)? */
745std::unique_ptr<ASTIfStatement> Parser::ifStatement() {
746 Token start;
747 if (!this->expect(Token::IF, "'if'", &start)) {
748 return nullptr;
749 }
750 if (!this->expect(Token::LPAREN, "'('")) {
751 return nullptr;
752 }
753 std::unique_ptr<ASTExpression> test(this->expression());
754 if (!test) {
755 return nullptr;
756 }
757 if (!this->expect(Token::RPAREN, "')'")) {
758 return nullptr;
759 }
760 std::unique_ptr<ASTStatement> ifTrue(this->statement());
761 if (!ifTrue) {
762 return nullptr;
763 }
764 std::unique_ptr<ASTStatement> ifFalse;
765 if (this->peek().fKind == Token::ELSE) {
766 this->nextToken();
767 ifFalse = this->statement();
768 if (!ifFalse) {
769 return nullptr;
770 }
771 }
772 return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, std::move(test),
773 std::move(ifTrue),
774 std::move(ifFalse)));
775}
776
777/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
778std::unique_ptr<ASTDoStatement> Parser::doStatement() {
779 Token start;
780 if (!this->expect(Token::DO, "'do'", &start)) {
781 return nullptr;
782 }
783 std::unique_ptr<ASTStatement> statement(this->statement());
784 if (!statement) {
785 return nullptr;
786 }
787 if (!this->expect(Token::WHILE, "'while'")) {
788 return nullptr;
789 }
790 if (!this->expect(Token::LPAREN, "'('")) {
791 return nullptr;
792 }
793 std::unique_ptr<ASTExpression> test(this->expression());
794 if (!test) {
795 return nullptr;
796 }
797 if (!this->expect(Token::RPAREN, "')'")) {
798 return nullptr;
799 }
800 if (!this->expect(Token::SEMICOLON, "';'")) {
801 return nullptr;
802 }
803 return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition,
804 std::move(statement),
805 std::move(test)));
806}
807
808/* WHILE LPAREN expression RPAREN STATEMENT */
809std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
810 Token start;
811 if (!this->expect(Token::WHILE, "'while'", &start)) {
812 return nullptr;
813 }
814 if (!this->expect(Token::LPAREN, "'('")) {
815 return nullptr;
816 }
817 std::unique_ptr<ASTExpression> test(this->expression());
818 if (!test) {
819 return nullptr;
820 }
821 if (!this->expect(Token::RPAREN, "')'")) {
822 return nullptr;
823 }
824 std::unique_ptr<ASTStatement> statement(this->statement());
825 if (!statement) {
826 return nullptr;
827 }
828 return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition,
829 std::move(test),
830 std::move(statement)));
831}
832
833/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
834 STATEMENT */
835std::unique_ptr<ASTForStatement> Parser::forStatement() {
836 Token start;
837 if (!this->expect(Token::FOR, "'for'", &start)) {
838 return nullptr;
839 }
840 if (!this->expect(Token::LPAREN, "'('")) {
841 return nullptr;
842 }
843 std::unique_ptr<ASTStatement> initializer;
844 Token nextToken = this->peek();
845 switch (nextToken.fKind) {
846 case Token::SEMICOLON:
ethannicholas22f939e2016-10-13 13:25:34 -0700847 this->nextToken();
ethannicholasb3058bd2016-07-01 08:22:01 -0700848 break;
ethannicholasa54401d2016-10-14 08:37:32 -0700849 case Token::CONST: {
850 std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
851 if (!vd) {
852 return nullptr;
853 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700854 initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
ethannicholasa54401d2016-10-14 08:37:32 -0700855 std::move(vd)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700856 break;
ethannicholasa54401d2016-10-14 08:37:32 -0700857 }
858 case Token::IDENTIFIER: {
ethannicholasb3058bd2016-07-01 08:22:01 -0700859 if (this->isType(nextToken.fText)) {
ethannicholasa54401d2016-10-14 08:37:32 -0700860 std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
861 if (!vd) {
862 return nullptr;
863 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700864 initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
ethannicholasa54401d2016-10-14 08:37:32 -0700865 std::move(vd)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700866 break;
867 }
ethannicholasa54401d2016-10-14 08:37:32 -0700868 } // fall through
ethannicholasb3058bd2016-07-01 08:22:01 -0700869 default:
870 initializer = this->expressionStatement();
871 }
872 std::unique_ptr<ASTExpression> test;
873 if (this->peek().fKind != Token::SEMICOLON) {
874 test = this->expression();
875 if (!test) {
876 return nullptr;
877 }
878 }
879 if (!this->expect(Token::SEMICOLON, "';'")) {
880 return nullptr;
881 }
882 std::unique_ptr<ASTExpression> next;
ethannicholas22f939e2016-10-13 13:25:34 -0700883 if (this->peek().fKind != Token::RPAREN) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700884 next = this->expression();
885 if (!next) {
886 return nullptr;
887 }
888 }
889 if (!this->expect(Token::RPAREN, "')'")) {
890 return nullptr;
891 }
892 std::unique_ptr<ASTStatement> statement(this->statement());
893 if (!statement) {
894 return nullptr;
895 }
896 return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition,
897 std::move(initializer),
898 std::move(test), std::move(next),
899 std::move(statement)));
900}
901
902/* RETURN expression? SEMICOLON */
903std::unique_ptr<ASTReturnStatement> Parser::returnStatement() {
904 Token start;
905 if (!this->expect(Token::RETURN, "'return'", &start)) {
906 return nullptr;
907 }
908 std::unique_ptr<ASTExpression> expression;
909 if (this->peek().fKind != Token::SEMICOLON) {
910 expression = this->expression();
911 if (!expression) {
912 return nullptr;
913 }
914 }
915 if (!this->expect(Token::SEMICOLON, "';'")) {
916 return nullptr;
917 }
918 return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition,
919 std::move(expression)));
920}
921
922/* BREAK SEMICOLON */
923std::unique_ptr<ASTBreakStatement> Parser::breakStatement() {
924 Token start;
925 if (!this->expect(Token::BREAK, "'break'", &start)) {
926 return nullptr;
927 }
928 if (!this->expect(Token::SEMICOLON, "';'")) {
929 return nullptr;
930 }
931 return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fPosition));
932}
933
934/* CONTINUE SEMICOLON */
935std::unique_ptr<ASTContinueStatement> Parser::continueStatement() {
936 Token start;
937 if (!this->expect(Token::CONTINUE, "'continue'", &start)) {
938 return nullptr;
939 }
940 if (!this->expect(Token::SEMICOLON, "';'")) {
941 return nullptr;
942 }
943 return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fPosition));
944}
945
946/* DISCARD SEMICOLON */
947std::unique_ptr<ASTDiscardStatement> Parser::discardStatement() {
948 Token start;
949 if (!this->expect(Token::DISCARD, "'continue'", &start)) {
950 return nullptr;
951 }
952 if (!this->expect(Token::SEMICOLON, "';'")) {
953 return nullptr;
954 }
955 return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fPosition));
956}
957
958/* LBRACE statement* RBRACE */
959std::unique_ptr<ASTBlock> Parser::block() {
ethannicholascad64162016-10-27 10:54:02 -0700960 AutoDepth depth(this);
961 if (!depth.checkValid()) {
962 return nullptr;
963 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700964 Token start;
965 if (!this->expect(Token::LBRACE, "'{'", &start)) {
966 return nullptr;
967 }
968 std::vector<std::unique_ptr<ASTStatement>> statements;
969 for (;;) {
970 switch (this->peek().fKind) {
971 case Token::RBRACE:
972 this->nextToken();
973 return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition,
974 std::move(statements)));
975 case Token::END_OF_FILE:
976 this->error(this->peek().fPosition, "expected '}', but found end of file");
977 return nullptr;
978 default: {
979 std::unique_ptr<ASTStatement> statement = this->statement();
980 if (!statement) {
981 return nullptr;
982 }
983 statements.push_back(std::move(statement));
984 }
985 }
986 }
987}
988
989/* expression SEMICOLON */
990std::unique_ptr<ASTExpressionStatement> Parser::expressionStatement() {
991 std::unique_ptr<ASTExpression> expr = this->expression();
992 if (expr) {
993 if (this->expect(Token::SEMICOLON, "';'")) {
994 ASTExpressionStatement* result = new ASTExpressionStatement(std::move(expr));
995 return std::unique_ptr<ASTExpressionStatement>(result);
996 }
997 }
998 return nullptr;
999}
1000
1001/* assignmentExpression */
1002std::unique_ptr<ASTExpression> Parser::expression() {
ethannicholascad64162016-10-27 10:54:02 -07001003 AutoDepth depth(this);
1004 if (!depth.checkValid()) {
1005 return nullptr;
1006 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001007 return this->assignmentExpression();
1008}
1009
1010/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1011 BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1012 assignmentExpression)*
1013 */
1014std::unique_ptr<ASTExpression> Parser::assignmentExpression() {
1015 std::unique_ptr<ASTExpression> result = this->ternaryExpression();
1016 if (!result) {
1017 return nullptr;
1018 }
1019 for (;;) {
1020 switch (this->peek().fKind) {
1021 case Token::EQ: // fall through
1022 case Token::STAREQ: // fall through
1023 case Token::SLASHEQ: // fall through
1024 case Token::PERCENTEQ: // fall through
1025 case Token::PLUSEQ: // fall through
1026 case Token::MINUSEQ: // fall through
1027 case Token::SHLEQ: // fall through
1028 case Token::SHREQ: // fall through
1029 case Token::BITWISEANDEQ: // fall through
1030 case Token::BITWISEXOREQ: // fall through
1031 case Token::BITWISEOREQ: // fall through
1032 case Token::LOGICALANDEQ: // fall through
1033 case Token::LOGICALXOREQ: // fall through
1034 case Token::LOGICALOREQ: {
1035 Token t = this->nextToken();
1036 std::unique_ptr<ASTExpression> right = this->assignmentExpression();
1037 if (!right) {
1038 return nullptr;
1039 }
1040 result = std::unique_ptr<ASTExpression>(new ASTBinaryExpression(std::move(result),
1041 t,
1042 std::move(right)));
1043 }
1044 default:
1045 return result;
1046 }
1047 }
1048}
1049
1050/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
1051std::unique_ptr<ASTExpression> Parser::ternaryExpression() {
1052 std::unique_ptr<ASTExpression> result = this->logicalOrExpression();
1053 if (!result) {
1054 return nullptr;
1055 }
1056 if (this->peek().fKind == Token::QUESTION) {
1057 Token question = this->nextToken();
1058 std::unique_ptr<ASTExpression> trueExpr = this->expression();
1059 if (!trueExpr) {
1060 return nullptr;
1061 }
1062 if (this->expect(Token::COLON, "':'")) {
1063 std::unique_ptr<ASTExpression> falseExpr = this->assignmentExpression();
1064 return std::unique_ptr<ASTExpression>(new ASTTernaryExpression(std::move(result),
1065 std::move(trueExpr),
1066 std::move(falseExpr)));
1067 }
1068 return nullptr;
1069 }
1070 return result;
1071}
1072
1073/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
1074std::unique_ptr<ASTExpression> Parser::logicalOrExpression() {
1075 std::unique_ptr<ASTExpression> result = this->logicalXorExpression();
1076 if (!result) {
1077 return nullptr;
1078 }
1079 while (this->peek().fKind == Token::LOGICALOR) {
1080 Token t = this->nextToken();
1081 std::unique_ptr<ASTExpression> right = this->logicalXorExpression();
1082 if (!right) {
1083 return nullptr;
1084 }
1085 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1086 }
1087 return result;
1088}
1089
1090/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
1091std::unique_ptr<ASTExpression> Parser::logicalXorExpression() {
1092 std::unique_ptr<ASTExpression> result = this->logicalAndExpression();
1093 if (!result) {
1094 return nullptr;
1095 }
1096 while (this->peek().fKind == Token::LOGICALXOR) {
1097 Token t = this->nextToken();
1098 std::unique_ptr<ASTExpression> right = this->logicalAndExpression();
1099 if (!right) {
1100 return nullptr;
1101 }
1102 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1103 }
1104 return result;
1105}
1106
1107/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
1108std::unique_ptr<ASTExpression> Parser::logicalAndExpression() {
1109 std::unique_ptr<ASTExpression> result = this->bitwiseOrExpression();
1110 if (!result) {
1111 return nullptr;
1112 }
1113 while (this->peek().fKind == Token::LOGICALAND) {
1114 Token t = this->nextToken();
1115 std::unique_ptr<ASTExpression> right = this->bitwiseOrExpression();
1116 if (!right) {
1117 return nullptr;
1118 }
1119 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1120 }
1121 return result;
1122}
1123
1124/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
1125std::unique_ptr<ASTExpression> Parser::bitwiseOrExpression() {
1126 std::unique_ptr<ASTExpression> result = this->bitwiseXorExpression();
1127 if (!result) {
1128 return nullptr;
1129 }
1130 while (this->peek().fKind == Token::BITWISEOR) {
1131 Token t = this->nextToken();
1132 std::unique_ptr<ASTExpression> right = this->bitwiseXorExpression();
1133 if (!right) {
1134 return nullptr;
1135 }
1136 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1137 }
1138 return result;
1139}
1140
1141/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
1142std::unique_ptr<ASTExpression> Parser::bitwiseXorExpression() {
1143 std::unique_ptr<ASTExpression> result = this->bitwiseAndExpression();
1144 if (!result) {
1145 return nullptr;
1146 }
1147 while (this->peek().fKind == Token::BITWISEXOR) {
1148 Token t = this->nextToken();
1149 std::unique_ptr<ASTExpression> right = this->bitwiseAndExpression();
1150 if (!right) {
1151 return nullptr;
1152 }
1153 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1154 }
1155 return result;
1156}
1157
1158/* equalityExpression (BITWISEAND equalityExpression)* */
1159std::unique_ptr<ASTExpression> Parser::bitwiseAndExpression() {
1160 std::unique_ptr<ASTExpression> result = this->equalityExpression();
1161 if (!result) {
1162 return nullptr;
1163 }
1164 while (this->peek().fKind == Token::BITWISEAND) {
1165 Token t = this->nextToken();
1166 std::unique_ptr<ASTExpression> right = this->equalityExpression();
1167 if (!right) {
1168 return nullptr;
1169 }
1170 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1171 }
1172 return result;
1173}
1174
1175/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
1176std::unique_ptr<ASTExpression> Parser::equalityExpression() {
1177 std::unique_ptr<ASTExpression> result = this->relationalExpression();
1178 if (!result) {
1179 return nullptr;
1180 }
1181 for (;;) {
1182 switch (this->peek().fKind) {
1183 case Token::EQEQ: // fall through
1184 case Token::NEQ: {
1185 Token t = this->nextToken();
1186 std::unique_ptr<ASTExpression> right = this->relationalExpression();
1187 if (!right) {
1188 return nullptr;
1189 }
1190 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1191 break;
1192 }
1193 default:
1194 return result;
1195 }
1196 }
1197}
1198
1199/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
1200std::unique_ptr<ASTExpression> Parser::relationalExpression() {
1201 std::unique_ptr<ASTExpression> result = this->shiftExpression();
1202 if (!result) {
1203 return nullptr;
1204 }
1205 for (;;) {
1206 switch (this->peek().fKind) {
1207 case Token::LT: // fall through
1208 case Token::GT: // fall through
1209 case Token::LTEQ: // fall through
1210 case Token::GTEQ: {
1211 Token t = this->nextToken();
1212 std::unique_ptr<ASTExpression> right = this->shiftExpression();
1213 if (!right) {
1214 return nullptr;
1215 }
1216 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1217 break;
1218 }
1219 default:
1220 return result;
1221 }
1222 }
1223}
1224
1225/* additiveExpression ((SHL | SHR) additiveExpression)* */
1226std::unique_ptr<ASTExpression> Parser::shiftExpression() {
1227 std::unique_ptr<ASTExpression> result = this->additiveExpression();
1228 if (!result) {
1229 return nullptr;
1230 }
1231 for (;;) {
1232 switch (this->peek().fKind) {
1233 case Token::SHL: // fall through
1234 case Token::SHR: {
1235 Token t = this->nextToken();
1236 std::unique_ptr<ASTExpression> right = this->additiveExpression();
1237 if (!right) {
1238 return nullptr;
1239 }
1240 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1241 break;
1242 }
1243 default:
1244 return result;
1245 }
1246 }
1247}
1248
1249/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
1250std::unique_ptr<ASTExpression> Parser::additiveExpression() {
1251 std::unique_ptr<ASTExpression> result = this->multiplicativeExpression();
1252 if (!result) {
1253 return nullptr;
1254 }
1255 for (;;) {
1256 switch (this->peek().fKind) {
1257 case Token::PLUS: // fall through
1258 case Token::MINUS: {
1259 Token t = this->nextToken();
1260 std::unique_ptr<ASTExpression> right = this->multiplicativeExpression();
1261 if (!right) {
1262 return nullptr;
1263 }
1264 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1265 break;
1266 }
1267 default:
1268 return result;
1269 }
1270 }
1271}
1272
1273/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
1274std::unique_ptr<ASTExpression> Parser::multiplicativeExpression() {
1275 std::unique_ptr<ASTExpression> result = this->unaryExpression();
1276 if (!result) {
1277 return nullptr;
1278 }
1279 for (;;) {
1280 switch (this->peek().fKind) {
1281 case Token::STAR: // fall through
1282 case Token::SLASH: // fall through
1283 case Token::PERCENT: {
1284 Token t = this->nextToken();
1285 std::unique_ptr<ASTExpression> right = this->unaryExpression();
1286 if (!right) {
1287 return nullptr;
1288 }
1289 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1290 break;
1291 }
1292 default:
1293 return result;
1294 }
1295 }
1296}
1297
1298/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
1299std::unique_ptr<ASTExpression> Parser::unaryExpression() {
1300 switch (this->peek().fKind) {
ethannicholas5961bc92016-10-12 06:39:56 -07001301 case Token::PLUS: // fall through
1302 case Token::MINUS: // fall through
1303 case Token::LOGICALNOT: // fall through
1304 case Token::BITWISENOT: // fall through
1305 case Token::PLUSPLUS: // fall through
ethannicholasb3058bd2016-07-01 08:22:01 -07001306 case Token::MINUSMINUS: {
1307 Token t = this->nextToken();
1308 std::unique_ptr<ASTExpression> expr = this->unaryExpression();
1309 if (!expr) {
1310 return nullptr;
1311 }
1312 return std::unique_ptr<ASTExpression>(new ASTPrefixExpression(t, std::move(expr)));
1313 }
1314 default:
1315 return this->postfixExpression();
1316 }
1317}
1318
1319/* term suffix* */
1320std::unique_ptr<ASTExpression> Parser::postfixExpression() {
1321 std::unique_ptr<ASTExpression> result = this->term();
1322 if (!result) {
1323 return nullptr;
1324 }
1325 for (;;) {
1326 switch (this->peek().fKind) {
1327 case Token::LBRACKET: // fall through
1328 case Token::DOT: // fall through
1329 case Token::LPAREN: // fall through
1330 case Token::PLUSPLUS: // fall through
1331 case Token::MINUSMINUS: {
1332 std::unique_ptr<ASTSuffix> s = this->suffix();
1333 if (!s) {
1334 return nullptr;
1335 }
1336 result.reset(new ASTSuffixExpression(std::move(result), std::move(s)));
1337 break;
1338 }
1339 default:
1340 return result;
1341 }
1342 }
1343}
1344
ethannicholas5961bc92016-10-12 06:39:56 -07001345/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
ethannicholasb3058bd2016-07-01 08:22:01 -07001346 PLUSPLUS | MINUSMINUS */
1347std::unique_ptr<ASTSuffix> Parser::suffix() {
1348 Token next = this->nextToken();
1349 switch (next.fKind) {
1350 case Token::LBRACKET: {
ethannicholas5961bc92016-10-12 06:39:56 -07001351 if (this->peek().fKind == Token::RBRACKET) {
1352 this->nextToken();
1353 return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fPosition));
1354 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001355 std::unique_ptr<ASTExpression> e = this->expression();
1356 if (!e) {
1357 return nullptr;
1358 }
1359 this->expect(Token::RBRACKET, "']' to complete array access expression");
1360 return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e)));
1361 }
1362 case Token::DOT: {
1363 Position pos = this->peek().fPosition;
1364 std::string text;
1365 if (this->identifier(&text)) {
1366 return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(pos, std::move(text)));
1367 }
1368 return nullptr;
1369 }
1370 case Token::LPAREN: {
1371 std::vector<std::unique_ptr<ASTExpression>> parameters;
1372 if (this->peek().fKind != Token::RPAREN) {
1373 for (;;) {
1374 std::unique_ptr<ASTExpression> expr = this->expression();
1375 if (!expr) {
1376 return nullptr;
1377 }
1378 parameters.push_back(std::move(expr));
1379 if (this->peek().fKind != Token::COMMA) {
1380 break;
1381 }
1382 this->nextToken();
1383 }
1384 }
1385 this->expect(Token::RPAREN, "')' to complete function parameters");
1386 return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition,
1387 std::move(parameters)));
1388 }
1389 case Token::PLUSPLUS:
1390 return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
1391 ASTSuffix::kPostIncrement_Kind));
1392 case Token::MINUSMINUS:
1393 return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
1394 ASTSuffix::kPostDecrement_Kind));
1395 default: {
1396 this->error(next.fPosition, "expected expression suffix, but found '" + next.fText +
1397 "'\n");
1398 return nullptr;
1399 }
1400 }
1401}
1402
1403/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */
1404std::unique_ptr<ASTExpression> Parser::term() {
1405 std::unique_ptr<ASTExpression> result;
1406 Token t = this->peek();
1407 switch (t.fKind) {
1408 case Token::IDENTIFIER: {
1409 std::string text;
1410 if (this->identifier(&text)) {
1411 result.reset(new ASTIdentifier(t.fPosition, std::move(text)));
1412 }
1413 break;
1414 }
1415 case Token::INT_LITERAL: {
1416 int64_t i;
1417 if (this->intLiteral(&i)) {
1418 result.reset(new ASTIntLiteral(t.fPosition, i));
1419 }
1420 break;
1421 }
1422 case Token::FLOAT_LITERAL: {
1423 double f;
1424 if (this->floatLiteral(&f)) {
1425 result.reset(new ASTFloatLiteral(t.fPosition, f));
1426 }
1427 break;
1428 }
1429 case Token::TRUE_LITERAL: // fall through
1430 case Token::FALSE_LITERAL: {
1431 bool b;
1432 if (this->boolLiteral(&b)) {
1433 result.reset(new ASTBoolLiteral(t.fPosition, b));
1434 }
1435 break;
1436 }
1437 case Token::LPAREN: {
1438 this->nextToken();
1439 result = this->expression();
1440 if (result) {
1441 this->expect(Token::RPAREN, "')' to complete expression");
1442 }
1443 break;
1444 }
1445 default:
1446 this->nextToken();
1447 this->error(t.fPosition, "expected expression, but found '" + t.fText + "'\n");
1448 result = nullptr;
1449 }
1450 return result;
1451}
1452
1453/* INT_LITERAL */
1454bool Parser::intLiteral(int64_t* dest) {
1455 Token t;
1456 if (this->expect(Token::INT_LITERAL, "integer literal", &t)) {
1457 *dest = SkSL::stol(t.fText);
1458 return true;
1459 }
1460 return false;
1461}
1462
1463/* FLOAT_LITERAL */
1464bool Parser::floatLiteral(double* dest) {
1465 Token t;
1466 if (this->expect(Token::FLOAT_LITERAL, "float literal", &t)) {
1467 *dest = SkSL::stod(t.fText);
1468 return true;
1469 }
1470 return false;
1471}
1472
1473/* TRUE_LITERAL | FALSE_LITERAL */
1474bool Parser::boolLiteral(bool* dest) {
1475 Token t = this->nextToken();
1476 switch (t.fKind) {
1477 case Token::TRUE_LITERAL:
1478 *dest = true;
1479 return true;
1480 case Token::FALSE_LITERAL:
1481 *dest = false;
1482 return true;
1483 default:
1484 this->error(t.fPosition, "expected 'true' or 'false', but found '" + t.fText + "'\n");
1485 return false;
1486 }
1487}
1488
1489/* IDENTIFIER */
1490bool Parser::identifier(std::string* dest) {
1491 Token t;
1492 if (this->expect(Token::IDENTIFIER, "identifier", &t)) {
1493 *dest = t.fText;
1494 return true;
1495 }
1496 return false;
1497}
1498
1499} // namespace