blob: b240e4501e98a1f4847cd8c00ca784d854ee9a31 [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"
59#include "ast/SkSLASTParameter.h"
60#include "ast/SkSLASTPrefixExpression.h"
61#include "ast/SkSLASTReturnStatement.h"
62#include "ast/SkSLASTStatement.h"
63#include "ast/SkSLASTSuffixExpression.h"
64#include "ast/SkSLASTTernaryExpression.h"
65#include "ast/SkSLASTType.h"
66#include "ast/SkSLASTVarDeclaration.h"
67#include "ast/SkSLASTVarDeclarationStatement.h"
68#include "ast/SkSLASTWhileStatement.h"
69#include "ir/SkSLSymbolTable.h"
ethannicholasd598f792016-07-25 10:08:54 -070070#include "ir/SkSLType.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070071
72namespace SkSL {
73
74Parser::Parser(std::string text, SymbolTable& types, ErrorReporter& errors)
75: fPushback(Position(-1, -1), Token::INVALID_TOKEN, "")
76, fTypes(types)
77, fErrors(errors) {
78 sksllex_init(&fScanner);
79 fBuffer = sksl_scan_string(text.c_str(), fScanner);
80 skslset_lineno(1, fScanner);
81
82 if (false) {
83 // avoid unused warning
84 yyunput(0, nullptr, fScanner);
85 }
86}
87
88Parser::~Parser() {
89 sksl_delete_buffer(fBuffer, fScanner);
ethannicholas69a7e7c2016-07-01 19:09:27 -070090 sksllex_destroy(fScanner);
ethannicholasb3058bd2016-07-01 08:22:01 -070091}
92
93/* (precision | directive | declaration)* END_OF_FILE */
94std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
95 std::vector<std::unique_ptr<ASTDeclaration>> result;
96 for (;;) {
97 switch (this->peek().fKind) {
98 case Token::END_OF_FILE:
99 return result;
100 case Token::PRECISION:
101 this->precision();
102 break;
103 case Token::DIRECTIVE: {
104 std::unique_ptr<ASTDeclaration> decl = this->directive();
105 if (decl) {
106 result.push_back(std::move(decl));
107 }
108 break;
109 }
110 default: {
111 std::unique_ptr<ASTDeclaration> decl = this->declaration();
112 if (!decl) {
113 continue;
114 }
115 result.push_back(std::move(decl));
116 }
117 }
118 }
119}
120
121Token Parser::nextToken() {
122 if (fPushback.fKind != Token::INVALID_TOKEN) {
123 Token result = fPushback;
124 fPushback.fKind = Token::INVALID_TOKEN;
125 fPushback.fText = "";
126 return result;
127 }
128 int token = sksllex(fScanner);
129 return Token(Position(skslget_lineno(fScanner), -1), (Token::Kind) token,
130 token == Token::END_OF_FILE ? "<end of file>" :
131 std::string(skslget_text(fScanner)));
132}
133
134void Parser::pushback(Token t) {
135 ASSERT(fPushback.fKind == Token::INVALID_TOKEN);
136 fPushback = t;
137}
138
139Token Parser::peek() {
140 fPushback = this->nextToken();
141 return fPushback;
142}
143
144bool Parser::expect(Token::Kind kind, std::string expected, Token* result) {
145 Token next = this->nextToken();
146 if (next.fKind == kind) {
147 if (result) {
148 *result = next;
149 }
150 return true;
151 } else {
152 this->error(next.fPosition, "expected " + expected + ", but found '" + next.fText + "'");
153 return false;
154 }
155}
156
157void Parser::error(Position p, std::string msg) {
158 fErrors.error(p, msg);
159}
160
161bool Parser::isType(std::string name) {
162 return nullptr != fTypes[name];
163}
164
165/* PRECISION (LOWP | MEDIUMP | HIGHP) type SEMICOLON */
166void Parser::precision() {
167 if (!this->expect(Token::PRECISION, "'precision'")) {
168 return;
169 }
170 Token p = this->nextToken();
171 switch (p.fKind) {
172 case Token::LOWP: // fall through
173 case Token::MEDIUMP: // fall through
174 case Token::HIGHP:
175 // ignored for now
176 break;
177 default:
178 this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" +
179 p.fText + "'");
180 return;
181 }
182 if (!this->type()) {
183 return;
184 }
185 this->expect(Token::SEMICOLON, "';'");
186}
187
188/* DIRECTIVE(#version) INT_LITERAL | DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
189std::unique_ptr<ASTDeclaration> Parser::directive() {
190 Token start;
191 if (!this->expect(Token::DIRECTIVE, "a directive", &start)) {
192 return nullptr;
193 }
194 if (start.fText == "#version") {
195 this->expect(Token::INT_LITERAL, "a version number");
196 // ignored for now
197 return nullptr;
198 } else if (start.fText == "#extension") {
199 Token name;
200 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
201 return nullptr;
202 }
203 if (!this->expect(Token::COLON, "':'")) {
204 return nullptr;
205 }
206 // FIXME: need to start paying attention to this token
207 if (!this->expect(Token::IDENTIFIER, "an identifier")) {
208 return nullptr;
209 }
210 return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition,
211 std::move(name.fText)));
212 } else {
213 this->error(start.fPosition, "unsupported directive '" + start.fText + "'");
214 return nullptr;
215 }
216}
217
218/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
219 (COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
220std::unique_ptr<ASTDeclaration> Parser::declaration() {
221 ASTModifiers modifiers = this->modifiers();
222 Token lookahead = this->peek();
223 if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) {
224 // we have an identifier that's not a type, could be the start of an interface block
225 return this->interfaceBlock(modifiers);
226 }
227 if (lookahead.fKind == Token::STRUCT) {
228 return this->structVarDeclaration(modifiers);
229 }
230 std::unique_ptr<ASTType> type(this->type());
231 if (!type) {
232 return nullptr;
233 }
234 if (type->fKind == ASTType::kStruct_Kind && peek().fKind == Token::SEMICOLON) {
235 this->nextToken();
236 return nullptr;
237 }
238 Token name;
239 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
240 return nullptr;
241 }
242 if (!modifiers.fFlags && this->peek().fKind == Token::LPAREN) {
243 this->nextToken();
244 std::vector<std::unique_ptr<ASTParameter>> parameters;
245 while (this->peek().fKind != Token::RPAREN) {
246 if (parameters.size() > 0) {
247 if (!this->expect(Token::COMMA, "','")) {
248 return nullptr;
249 }
250 }
251 std::unique_ptr<ASTParameter> parameter = this->parameter();
252 if (!parameter) {
253 return nullptr;
254 }
255 parameters.push_back(std::move(parameter));
256 }
257 this->nextToken();
258 std::unique_ptr<ASTBlock> body;
259 if (this->peek().fKind == Token::SEMICOLON) {
260 this->nextToken();
261 } else {
262 body = this->block();
263 if (!body) {
264 return nullptr;
265 }
266 }
267 return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition, std::move(type),
268 std::move(name.fText),
269 std::move(parameters),
270 std::move(body)));
271 } else {
272 return this->varDeclarationEnd(modifiers, std::move(type), name.fText);
273 }
274}
275
276/* modifiers type IDENTIFIER varDeclarationEnd */
ethannicholas14fe8cc2016-09-07 13:37:16 -0700277std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() {
ethannicholasb3058bd2016-07-01 08:22:01 -0700278 ASTModifiers modifiers = this->modifiers();
279 std::unique_ptr<ASTType> type(this->type());
280 if (!type) {
281 return nullptr;
282 }
283 Token name;
284 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
285 return nullptr;
286 }
287 return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText));
288}
289
290/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
291std::unique_ptr<ASTType> Parser::structDeclaration() {
292 if (!this->expect(Token::STRUCT, "'struct'")) {
293 return nullptr;
294 }
295 Token name;
296 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
297 return nullptr;
298 }
299 if (!this->expect(Token::LBRACE, "'{'")) {
300 return nullptr;
301 }
302 std::vector<Type::Field> fields;
303 while (this->peek().fKind != Token::RBRACE) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700304 std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700305 if (!decl) {
306 return nullptr;
307 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700308 for (const auto& var : decl->fVars) {
ethannicholasd598f792016-07-25 10:08:54 -0700309 auto type = (const Type*) fTypes[decl->fType->fName];
ethannicholas14fe8cc2016-09-07 13:37:16 -0700310 for (int i = (int) var.fSizes.size() - 1; i >= 0; i--) {
311 if (var.fSizes[i]->fKind != ASTExpression::kInt_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700312 this->error(decl->fPosition, "array size in struct field must be a constant");
313 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700314 uint64_t columns = ((ASTIntLiteral&) *var.fSizes[i]).fValue;
ethannicholasb3058bd2016-07-01 08:22:01 -0700315 std::string name = type->name() + "[" + to_string(columns) + "]";
ethannicholasd598f792016-07-25 10:08:54 -0700316 type = new Type(name, Type::kArray_Kind, *type, (int) columns);
317 fTypes.takeOwnership((Type*) type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700318 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700319 fields.push_back(Type::Field(decl->fModifiers, var.fName, type));
320 if (var.fValue) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700321 this->error(decl->fPosition, "initializers are not permitted on struct fields");
322 }
323 }
324 }
325 if (!this->expect(Token::RBRACE, "'}'")) {
326 return nullptr;
327 }
ethannicholasd598f792016-07-25 10:08:54 -0700328 fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fText, fields)));
329 return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText,
ethannicholasb3058bd2016-07-01 08:22:01 -0700330 ASTType::kStruct_Kind));
331}
332
333/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
ethannicholas14fe8cc2016-09-07 13:37:16 -0700334std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(ASTModifiers modifiers) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700335 std::unique_ptr<ASTType> type = this->structDeclaration();
336 if (!type) {
337 return nullptr;
338 }
339 if (peek().fKind == Token::IDENTIFIER) {
340 Token name = this->nextToken();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700341 std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers,
342 std::move(type),
343 std::move(name.fText));
ethannicholasb3058bd2016-07-01 08:22:01 -0700344 if (result) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700345 for (const auto& var : result->fVars) {
346 if (var.fValue) {
347 this->error(var.fValue->fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700348 "struct variables cannot be initialized");
349 }
350 }
351 }
352 return result;
353 }
354 this->expect(Token::SEMICOLON, "';'");
355 return nullptr;
356}
357
358/* (LBRACKET expression? RBRACKET)* (EQ expression)? (COMMA IDENTIFER
359 (LBRACKET expression? RBRACKET)* (EQ expression)?)* SEMICOLON */
ethannicholas14fe8cc2016-09-07 13:37:16 -0700360std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(ASTModifiers mods,
361 std::unique_ptr<ASTType> type,
362 std::string name) {
363 std::vector<ASTVarDeclaration> vars;
ethannicholasb3058bd2016-07-01 08:22:01 -0700364 std::vector<std::unique_ptr<ASTExpression>> currentVarSizes;
365 while (this->peek().fKind == Token::LBRACKET) {
366 this->nextToken();
367 if (this->peek().fKind == Token::RBRACKET) {
368 this->nextToken();
369 currentVarSizes.push_back(nullptr);
370 } else {
371 std::unique_ptr<ASTExpression> size(this->expression());
372 if (!size) {
373 return nullptr;
374 }
375 currentVarSizes.push_back(std::move(size));
376 if (!this->expect(Token::RBRACKET, "']'")) {
377 return nullptr;
378 }
379 }
380 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700381 std::unique_ptr<ASTExpression> value;
ethannicholasb3058bd2016-07-01 08:22:01 -0700382 if (this->peek().fKind == Token::EQ) {
383 this->nextToken();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700384 value = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700385 if (!value) {
386 return nullptr;
387 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700388 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700389 vars.emplace_back(std::move(name), std::move(currentVarSizes), std::move(value));
ethannicholasb3058bd2016-07-01 08:22:01 -0700390 while (this->peek().fKind == Token::COMMA) {
391 this->nextToken();
392 Token name;
393 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
394 return nullptr;
395 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700396 currentVarSizes.clear();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700397 value.reset();
ethannicholasb3058bd2016-07-01 08:22:01 -0700398 while (this->peek().fKind == Token::LBRACKET) {
399 this->nextToken();
400 if (this->peek().fKind == Token::RBRACKET) {
401 this->nextToken();
402 currentVarSizes.push_back(nullptr);
403 } else {
404 std::unique_ptr<ASTExpression> size(this->expression());
405 if (!size) {
406 return nullptr;
407 }
408 currentVarSizes.push_back(std::move(size));
409 if (!this->expect(Token::RBRACKET, "']'")) {
410 return nullptr;
411 }
412 }
413 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700414 if (this->peek().fKind == Token::EQ) {
415 this->nextToken();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700416 value = this->expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700417 if (!value) {
418 return nullptr;
419 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700420 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700421 vars.emplace_back(std::move(name.fText), std::move(currentVarSizes), std::move(value));
ethannicholasb3058bd2016-07-01 08:22:01 -0700422 }
423 if (!this->expect(Token::SEMICOLON, "';'")) {
424 return nullptr;
425 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700426 return std::unique_ptr<ASTVarDeclarations>(new ASTVarDeclarations(std::move(mods),
427 std::move(type),
428 std::move(vars)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700429}
430
431/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
432std::unique_ptr<ASTParameter> Parser::parameter() {
433 ASTModifiers modifiers = this->modifiersWithDefaults(ASTModifiers::kIn_Flag);
434 std::unique_ptr<ASTType> type = this->type();
435 if (!type) {
436 return nullptr;
437 }
438 Token name;
439 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
440 return nullptr;
441 }
442 std::vector<int> sizes;
443 while (this->peek().fKind == Token::LBRACKET) {
444 this->nextToken();
445 Token sizeToken;
446 if (!this->expect(Token::INT_LITERAL, "a positive integer", &sizeToken)) {
447 return nullptr;
448 }
449 sizes.push_back(SkSL::stoi(sizeToken.fText));
450 if (!this->expect(Token::RBRACKET, "']'")) {
451 return nullptr;
452 }
453 }
454 return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers,
455 std::move(type), name.fText,
456 std::move(sizes)));
457}
458
459/** (EQ INT_LITERAL)? */
460int Parser::layoutInt() {
461 if (!this->expect(Token::EQ, "'='")) {
462 return -1;
463 }
464 Token resultToken;
465 if (this->expect(Token::INT_LITERAL, "a non-negative integer", &resultToken)) {
466 return SkSL::stoi(resultToken.fText);
467 }
468 return -1;
469}
470
471/* LAYOUT LPAREN IDENTIFIER EQ INT_LITERAL (COMMA IDENTIFIER EQ INT_LITERAL)*
472 RPAREN */
473ASTLayout Parser::layout() {
474 int location = -1;
475 int binding = -1;
476 int index = -1;
477 int set = -1;
478 int builtin = -1;
ethannicholasf789b382016-08-03 12:43:36 -0700479 bool originUpperLeft = false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700480 if (this->peek().fKind == Token::LAYOUT) {
481 this->nextToken();
482 if (!this->expect(Token::LPAREN, "'('")) {
ethannicholasf789b382016-08-03 12:43:36 -0700483 return ASTLayout(location, binding, index, set, builtin, originUpperLeft);
ethannicholasb3058bd2016-07-01 08:22:01 -0700484 }
485 for (;;) {
486 Token t = this->nextToken();
487 if (t.fText == "location") {
488 location = this->layoutInt();
489 } else if (t.fText == "binding") {
490 binding = this->layoutInt();
491 } else if (t.fText == "index") {
492 index = this->layoutInt();
493 } else if (t.fText == "set") {
494 set = this->layoutInt();
495 } else if (t.fText == "builtin") {
496 builtin = this->layoutInt();
ethannicholasf789b382016-08-03 12:43:36 -0700497 } else if (t.fText == "origin_upper_left") {
498 originUpperLeft = true;
ethannicholasb3058bd2016-07-01 08:22:01 -0700499 } else {
500 this->error(t.fPosition, ("'" + t.fText +
501 "' is not a valid layout qualifier").c_str());
502 }
503 if (this->peek().fKind == Token::RPAREN) {
504 this->nextToken();
505 break;
506 }
507 if (!this->expect(Token::COMMA, "','")) {
508 break;
509 }
510 }
511 }
ethannicholasf789b382016-08-03 12:43:36 -0700512 return ASTLayout(location, binding, index, set, builtin, originUpperLeft);
ethannicholasb3058bd2016-07-01 08:22:01 -0700513}
514
ethannicholasf789b382016-08-03 12:43:36 -0700515/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE)* */
ethannicholasb3058bd2016-07-01 08:22:01 -0700516ASTModifiers Parser::modifiers() {
517 ASTLayout layout = this->layout();
518 int flags = 0;
519 for (;;) {
520 // TODO: handle duplicate / incompatible flags
521 switch (peek().fKind) {
522 case Token::UNIFORM:
523 this->nextToken();
524 flags |= ASTModifiers::kUniform_Flag;
525 break;
526 case Token::CONST:
527 this->nextToken();
528 flags |= ASTModifiers::kConst_Flag;
529 break;
530 case Token::IN:
531 this->nextToken();
532 flags |= ASTModifiers::kIn_Flag;
533 break;
534 case Token::OUT:
535 this->nextToken();
536 flags |= ASTModifiers::kOut_Flag;
537 break;
538 case Token::INOUT:
539 this->nextToken();
540 flags |= ASTModifiers::kIn_Flag;
541 flags |= ASTModifiers::kOut_Flag;
542 break;
543 case Token::LOWP:
544 this->nextToken();
545 flags |= ASTModifiers::kLowp_Flag;
546 break;
547 case Token::MEDIUMP:
548 this->nextToken();
549 flags |= ASTModifiers::kMediump_Flag;
550 break;
551 case Token::HIGHP:
552 this->nextToken();
553 flags |= ASTModifiers::kHighp_Flag;
554 break;
ethannicholasf789b382016-08-03 12:43:36 -0700555 case Token::FLAT:
556 this->nextToken();
557 flags |= ASTModifiers::kFlat_Flag;
558 break;
559 case Token::NOPERSPECTIVE:
560 this->nextToken();
561 flags |= ASTModifiers::kNoPerspective_Flag;
562 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700563 default:
564 return ASTModifiers(layout, flags);
565 }
566 }
567}
568
569ASTModifiers Parser::modifiersWithDefaults(int defaultFlags) {
570 ASTModifiers result = this->modifiers();
571 if (!result.fFlags) {
572 return ASTModifiers(result.fLayout, defaultFlags);
573 }
574 return result;
575}
576
577/* ifStatement | forStatement | doStatement | whileStatement | block | expression */
578std::unique_ptr<ASTStatement> Parser::statement() {
579 Token start = this->peek();
580 switch (start.fKind) {
581 case Token::IF:
582 return this->ifStatement();
583 case Token::FOR:
584 return this->forStatement();
585 case Token::DO:
586 return this->doStatement();
587 case Token::WHILE:
588 return this->whileStatement();
589 case Token::RETURN:
590 return this->returnStatement();
591 case Token::BREAK:
592 return this->breakStatement();
593 case Token::CONTINUE:
594 return this->continueStatement();
595 case Token::DISCARD:
596 return this->discardStatement();
597 case Token::LBRACE:
598 return this->block();
599 case Token::SEMICOLON:
600 this->nextToken();
ethannicholas0730be72016-09-01 07:59:02 -0700601 return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition,
602 std::vector<std::unique_ptr<ASTStatement>>()));
ethannicholasb3058bd2016-07-01 08:22:01 -0700603 case Token::CONST: // fall through
604 case Token::HIGHP: // fall through
605 case Token::MEDIUMP: // fall through
606 case Token::LOWP: {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700607 auto decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700608 if (!decl) {
609 return nullptr;
610 }
611 return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(std::move(decl)));
612 }
613 case Token::IDENTIFIER:
614 if (this->isType(start.fText)) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700615 auto decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700616 if (!decl) {
617 return nullptr;
618 }
619 return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
620 std::move(decl)));
621 }
622 // fall through
623 default:
624 return this->expressionStatement();
625 }
626}
627
628/* IDENTIFIER(type) */
629std::unique_ptr<ASTType> Parser::type() {
630 Token type;
631 if (!this->expect(Token::IDENTIFIER, "a type", &type)) {
632 return nullptr;
633 }
634 if (!this->isType(type.fText)) {
635 this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str());
636 return nullptr;
637 }
638 return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText),
639 ASTType::kIdentifier_Kind));
640}
641
642/* IDENTIFIER LBRACE varDeclaration* RBRACE */
643std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(ASTModifiers mods) {
644 Token name;
645 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
646 return nullptr;
647 }
648 if (peek().fKind != Token::LBRACE) {
649 // we only get into interfaceBlock if we found a top-level identifier which was not a type.
650 // 99% of the time, the user was not actually intending to create an interface block, so
651 // it's better to report it as an unknown type
652 this->error(name.fPosition, "no type named '" + name.fText + "'");
653 return nullptr;
654 }
655 this->nextToken();
ethannicholas14fe8cc2016-09-07 13:37:16 -0700656 std::vector<std::unique_ptr<ASTVarDeclarations>> decls;
ethannicholasb3058bd2016-07-01 08:22:01 -0700657 while (this->peek().fKind != Token::RBRACE) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700658 std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700659 if (!decl) {
660 return nullptr;
661 }
662 decls.push_back(std::move(decl));
663 }
664 this->nextToken();
665 std::string valueName;
666 if (this->peek().fKind == Token::IDENTIFIER) {
667 valueName = this->nextToken().fText;
668 }
669 this->expect(Token::SEMICOLON, "';'");
670 return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods,
671 name.fText, std::move(valueName),
672 std::move(decls)));
673}
674
675/* IF LPAREN expression RPAREN statement (ELSE statement)? */
676std::unique_ptr<ASTIfStatement> Parser::ifStatement() {
677 Token start;
678 if (!this->expect(Token::IF, "'if'", &start)) {
679 return nullptr;
680 }
681 if (!this->expect(Token::LPAREN, "'('")) {
682 return nullptr;
683 }
684 std::unique_ptr<ASTExpression> test(this->expression());
685 if (!test) {
686 return nullptr;
687 }
688 if (!this->expect(Token::RPAREN, "')'")) {
689 return nullptr;
690 }
691 std::unique_ptr<ASTStatement> ifTrue(this->statement());
692 if (!ifTrue) {
693 return nullptr;
694 }
695 std::unique_ptr<ASTStatement> ifFalse;
696 if (this->peek().fKind == Token::ELSE) {
697 this->nextToken();
698 ifFalse = this->statement();
699 if (!ifFalse) {
700 return nullptr;
701 }
702 }
703 return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, std::move(test),
704 std::move(ifTrue),
705 std::move(ifFalse)));
706}
707
708/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
709std::unique_ptr<ASTDoStatement> Parser::doStatement() {
710 Token start;
711 if (!this->expect(Token::DO, "'do'", &start)) {
712 return nullptr;
713 }
714 std::unique_ptr<ASTStatement> statement(this->statement());
715 if (!statement) {
716 return nullptr;
717 }
718 if (!this->expect(Token::WHILE, "'while'")) {
719 return nullptr;
720 }
721 if (!this->expect(Token::LPAREN, "'('")) {
722 return nullptr;
723 }
724 std::unique_ptr<ASTExpression> test(this->expression());
725 if (!test) {
726 return nullptr;
727 }
728 if (!this->expect(Token::RPAREN, "')'")) {
729 return nullptr;
730 }
731 if (!this->expect(Token::SEMICOLON, "';'")) {
732 return nullptr;
733 }
734 return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition,
735 std::move(statement),
736 std::move(test)));
737}
738
739/* WHILE LPAREN expression RPAREN STATEMENT */
740std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
741 Token start;
742 if (!this->expect(Token::WHILE, "'while'", &start)) {
743 return nullptr;
744 }
745 if (!this->expect(Token::LPAREN, "'('")) {
746 return nullptr;
747 }
748 std::unique_ptr<ASTExpression> test(this->expression());
749 if (!test) {
750 return nullptr;
751 }
752 if (!this->expect(Token::RPAREN, "')'")) {
753 return nullptr;
754 }
755 std::unique_ptr<ASTStatement> statement(this->statement());
756 if (!statement) {
757 return nullptr;
758 }
759 return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition,
760 std::move(test),
761 std::move(statement)));
762}
763
764/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
765 STATEMENT */
766std::unique_ptr<ASTForStatement> Parser::forStatement() {
767 Token start;
768 if (!this->expect(Token::FOR, "'for'", &start)) {
769 return nullptr;
770 }
771 if (!this->expect(Token::LPAREN, "'('")) {
772 return nullptr;
773 }
774 std::unique_ptr<ASTStatement> initializer;
775 Token nextToken = this->peek();
776 switch (nextToken.fKind) {
777 case Token::SEMICOLON:
778 break;
779 case Token::CONST:
780 initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
ethannicholas14fe8cc2016-09-07 13:37:16 -0700781 this->varDeclarations()));
ethannicholasb3058bd2016-07-01 08:22:01 -0700782 break;
783 case Token::IDENTIFIER:
784 if (this->isType(nextToken.fText)) {
785 initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
ethannicholas14fe8cc2016-09-07 13:37:16 -0700786 this->varDeclarations()));
ethannicholasb3058bd2016-07-01 08:22:01 -0700787 break;
788 }
789 // fall through
790 default:
791 initializer = this->expressionStatement();
792 }
793 std::unique_ptr<ASTExpression> test;
794 if (this->peek().fKind != Token::SEMICOLON) {
795 test = this->expression();
796 if (!test) {
797 return nullptr;
798 }
799 }
800 if (!this->expect(Token::SEMICOLON, "';'")) {
801 return nullptr;
802 }
803 std::unique_ptr<ASTExpression> next;
804 if (this->peek().fKind != Token::SEMICOLON) {
805 next = this->expression();
806 if (!next) {
807 return nullptr;
808 }
809 }
810 if (!this->expect(Token::RPAREN, "')'")) {
811 return nullptr;
812 }
813 std::unique_ptr<ASTStatement> statement(this->statement());
814 if (!statement) {
815 return nullptr;
816 }
817 return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition,
818 std::move(initializer),
819 std::move(test), std::move(next),
820 std::move(statement)));
821}
822
823/* RETURN expression? SEMICOLON */
824std::unique_ptr<ASTReturnStatement> Parser::returnStatement() {
825 Token start;
826 if (!this->expect(Token::RETURN, "'return'", &start)) {
827 return nullptr;
828 }
829 std::unique_ptr<ASTExpression> expression;
830 if (this->peek().fKind != Token::SEMICOLON) {
831 expression = this->expression();
832 if (!expression) {
833 return nullptr;
834 }
835 }
836 if (!this->expect(Token::SEMICOLON, "';'")) {
837 return nullptr;
838 }
839 return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition,
840 std::move(expression)));
841}
842
843/* BREAK SEMICOLON */
844std::unique_ptr<ASTBreakStatement> Parser::breakStatement() {
845 Token start;
846 if (!this->expect(Token::BREAK, "'break'", &start)) {
847 return nullptr;
848 }
849 if (!this->expect(Token::SEMICOLON, "';'")) {
850 return nullptr;
851 }
852 return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fPosition));
853}
854
855/* CONTINUE SEMICOLON */
856std::unique_ptr<ASTContinueStatement> Parser::continueStatement() {
857 Token start;
858 if (!this->expect(Token::CONTINUE, "'continue'", &start)) {
859 return nullptr;
860 }
861 if (!this->expect(Token::SEMICOLON, "';'")) {
862 return nullptr;
863 }
864 return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fPosition));
865}
866
867/* DISCARD SEMICOLON */
868std::unique_ptr<ASTDiscardStatement> Parser::discardStatement() {
869 Token start;
870 if (!this->expect(Token::DISCARD, "'continue'", &start)) {
871 return nullptr;
872 }
873 if (!this->expect(Token::SEMICOLON, "';'")) {
874 return nullptr;
875 }
876 return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fPosition));
877}
878
879/* LBRACE statement* RBRACE */
880std::unique_ptr<ASTBlock> Parser::block() {
881 Token start;
882 if (!this->expect(Token::LBRACE, "'{'", &start)) {
883 return nullptr;
884 }
885 std::vector<std::unique_ptr<ASTStatement>> statements;
886 for (;;) {
887 switch (this->peek().fKind) {
888 case Token::RBRACE:
889 this->nextToken();
890 return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition,
891 std::move(statements)));
892 case Token::END_OF_FILE:
893 this->error(this->peek().fPosition, "expected '}', but found end of file");
894 return nullptr;
895 default: {
896 std::unique_ptr<ASTStatement> statement = this->statement();
897 if (!statement) {
898 return nullptr;
899 }
900 statements.push_back(std::move(statement));
901 }
902 }
903 }
904}
905
906/* expression SEMICOLON */
907std::unique_ptr<ASTExpressionStatement> Parser::expressionStatement() {
908 std::unique_ptr<ASTExpression> expr = this->expression();
909 if (expr) {
910 if (this->expect(Token::SEMICOLON, "';'")) {
911 ASTExpressionStatement* result = new ASTExpressionStatement(std::move(expr));
912 return std::unique_ptr<ASTExpressionStatement>(result);
913 }
914 }
915 return nullptr;
916}
917
918/* assignmentExpression */
919std::unique_ptr<ASTExpression> Parser::expression() {
920 return this->assignmentExpression();
921}
922
923/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
924 BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
925 assignmentExpression)*
926 */
927std::unique_ptr<ASTExpression> Parser::assignmentExpression() {
928 std::unique_ptr<ASTExpression> result = this->ternaryExpression();
929 if (!result) {
930 return nullptr;
931 }
932 for (;;) {
933 switch (this->peek().fKind) {
934 case Token::EQ: // fall through
935 case Token::STAREQ: // fall through
936 case Token::SLASHEQ: // fall through
937 case Token::PERCENTEQ: // fall through
938 case Token::PLUSEQ: // fall through
939 case Token::MINUSEQ: // fall through
940 case Token::SHLEQ: // fall through
941 case Token::SHREQ: // fall through
942 case Token::BITWISEANDEQ: // fall through
943 case Token::BITWISEXOREQ: // fall through
944 case Token::BITWISEOREQ: // fall through
945 case Token::LOGICALANDEQ: // fall through
946 case Token::LOGICALXOREQ: // fall through
947 case Token::LOGICALOREQ: {
948 Token t = this->nextToken();
949 std::unique_ptr<ASTExpression> right = this->assignmentExpression();
950 if (!right) {
951 return nullptr;
952 }
953 result = std::unique_ptr<ASTExpression>(new ASTBinaryExpression(std::move(result),
954 t,
955 std::move(right)));
956 }
957 default:
958 return result;
959 }
960 }
961}
962
963/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
964std::unique_ptr<ASTExpression> Parser::ternaryExpression() {
965 std::unique_ptr<ASTExpression> result = this->logicalOrExpression();
966 if (!result) {
967 return nullptr;
968 }
969 if (this->peek().fKind == Token::QUESTION) {
970 Token question = this->nextToken();
971 std::unique_ptr<ASTExpression> trueExpr = this->expression();
972 if (!trueExpr) {
973 return nullptr;
974 }
975 if (this->expect(Token::COLON, "':'")) {
976 std::unique_ptr<ASTExpression> falseExpr = this->assignmentExpression();
977 return std::unique_ptr<ASTExpression>(new ASTTernaryExpression(std::move(result),
978 std::move(trueExpr),
979 std::move(falseExpr)));
980 }
981 return nullptr;
982 }
983 return result;
984}
985
986/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
987std::unique_ptr<ASTExpression> Parser::logicalOrExpression() {
988 std::unique_ptr<ASTExpression> result = this->logicalXorExpression();
989 if (!result) {
990 return nullptr;
991 }
992 while (this->peek().fKind == Token::LOGICALOR) {
993 Token t = this->nextToken();
994 std::unique_ptr<ASTExpression> right = this->logicalXorExpression();
995 if (!right) {
996 return nullptr;
997 }
998 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
999 }
1000 return result;
1001}
1002
1003/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
1004std::unique_ptr<ASTExpression> Parser::logicalXorExpression() {
1005 std::unique_ptr<ASTExpression> result = this->logicalAndExpression();
1006 if (!result) {
1007 return nullptr;
1008 }
1009 while (this->peek().fKind == Token::LOGICALXOR) {
1010 Token t = this->nextToken();
1011 std::unique_ptr<ASTExpression> right = this->logicalAndExpression();
1012 if (!right) {
1013 return nullptr;
1014 }
1015 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1016 }
1017 return result;
1018}
1019
1020/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
1021std::unique_ptr<ASTExpression> Parser::logicalAndExpression() {
1022 std::unique_ptr<ASTExpression> result = this->bitwiseOrExpression();
1023 if (!result) {
1024 return nullptr;
1025 }
1026 while (this->peek().fKind == Token::LOGICALAND) {
1027 Token t = this->nextToken();
1028 std::unique_ptr<ASTExpression> right = this->bitwiseOrExpression();
1029 if (!right) {
1030 return nullptr;
1031 }
1032 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1033 }
1034 return result;
1035}
1036
1037/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
1038std::unique_ptr<ASTExpression> Parser::bitwiseOrExpression() {
1039 std::unique_ptr<ASTExpression> result = this->bitwiseXorExpression();
1040 if (!result) {
1041 return nullptr;
1042 }
1043 while (this->peek().fKind == Token::BITWISEOR) {
1044 Token t = this->nextToken();
1045 std::unique_ptr<ASTExpression> right = this->bitwiseXorExpression();
1046 if (!right) {
1047 return nullptr;
1048 }
1049 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1050 }
1051 return result;
1052}
1053
1054/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
1055std::unique_ptr<ASTExpression> Parser::bitwiseXorExpression() {
1056 std::unique_ptr<ASTExpression> result = this->bitwiseAndExpression();
1057 if (!result) {
1058 return nullptr;
1059 }
1060 while (this->peek().fKind == Token::BITWISEXOR) {
1061 Token t = this->nextToken();
1062 std::unique_ptr<ASTExpression> right = this->bitwiseAndExpression();
1063 if (!right) {
1064 return nullptr;
1065 }
1066 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1067 }
1068 return result;
1069}
1070
1071/* equalityExpression (BITWISEAND equalityExpression)* */
1072std::unique_ptr<ASTExpression> Parser::bitwiseAndExpression() {
1073 std::unique_ptr<ASTExpression> result = this->equalityExpression();
1074 if (!result) {
1075 return nullptr;
1076 }
1077 while (this->peek().fKind == Token::BITWISEAND) {
1078 Token t = this->nextToken();
1079 std::unique_ptr<ASTExpression> right = this->equalityExpression();
1080 if (!right) {
1081 return nullptr;
1082 }
1083 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1084 }
1085 return result;
1086}
1087
1088/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
1089std::unique_ptr<ASTExpression> Parser::equalityExpression() {
1090 std::unique_ptr<ASTExpression> result = this->relationalExpression();
1091 if (!result) {
1092 return nullptr;
1093 }
1094 for (;;) {
1095 switch (this->peek().fKind) {
1096 case Token::EQEQ: // fall through
1097 case Token::NEQ: {
1098 Token t = this->nextToken();
1099 std::unique_ptr<ASTExpression> right = this->relationalExpression();
1100 if (!right) {
1101 return nullptr;
1102 }
1103 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1104 break;
1105 }
1106 default:
1107 return result;
1108 }
1109 }
1110}
1111
1112/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
1113std::unique_ptr<ASTExpression> Parser::relationalExpression() {
1114 std::unique_ptr<ASTExpression> result = this->shiftExpression();
1115 if (!result) {
1116 return nullptr;
1117 }
1118 for (;;) {
1119 switch (this->peek().fKind) {
1120 case Token::LT: // fall through
1121 case Token::GT: // fall through
1122 case Token::LTEQ: // fall through
1123 case Token::GTEQ: {
1124 Token t = this->nextToken();
1125 std::unique_ptr<ASTExpression> right = this->shiftExpression();
1126 if (!right) {
1127 return nullptr;
1128 }
1129 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1130 break;
1131 }
1132 default:
1133 return result;
1134 }
1135 }
1136}
1137
1138/* additiveExpression ((SHL | SHR) additiveExpression)* */
1139std::unique_ptr<ASTExpression> Parser::shiftExpression() {
1140 std::unique_ptr<ASTExpression> result = this->additiveExpression();
1141 if (!result) {
1142 return nullptr;
1143 }
1144 for (;;) {
1145 switch (this->peek().fKind) {
1146 case Token::SHL: // fall through
1147 case Token::SHR: {
1148 Token t = this->nextToken();
1149 std::unique_ptr<ASTExpression> right = this->additiveExpression();
1150 if (!right) {
1151 return nullptr;
1152 }
1153 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1154 break;
1155 }
1156 default:
1157 return result;
1158 }
1159 }
1160}
1161
1162/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
1163std::unique_ptr<ASTExpression> Parser::additiveExpression() {
1164 std::unique_ptr<ASTExpression> result = this->multiplicativeExpression();
1165 if (!result) {
1166 return nullptr;
1167 }
1168 for (;;) {
1169 switch (this->peek().fKind) {
1170 case Token::PLUS: // fall through
1171 case Token::MINUS: {
1172 Token t = this->nextToken();
1173 std::unique_ptr<ASTExpression> right = this->multiplicativeExpression();
1174 if (!right) {
1175 return nullptr;
1176 }
1177 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1178 break;
1179 }
1180 default:
1181 return result;
1182 }
1183 }
1184}
1185
1186/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
1187std::unique_ptr<ASTExpression> Parser::multiplicativeExpression() {
1188 std::unique_ptr<ASTExpression> result = this->unaryExpression();
1189 if (!result) {
1190 return nullptr;
1191 }
1192 for (;;) {
1193 switch (this->peek().fKind) {
1194 case Token::STAR: // fall through
1195 case Token::SLASH: // fall through
1196 case Token::PERCENT: {
1197 Token t = this->nextToken();
1198 std::unique_ptr<ASTExpression> right = this->unaryExpression();
1199 if (!right) {
1200 return nullptr;
1201 }
1202 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1203 break;
1204 }
1205 default:
1206 return result;
1207 }
1208 }
1209}
1210
1211/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
1212std::unique_ptr<ASTExpression> Parser::unaryExpression() {
1213 switch (this->peek().fKind) {
1214 case Token::PLUS: // fall through
1215 case Token::MINUS: // fall through
1216 case Token::NOT: // fall through
1217 case Token::PLUSPLUS: // fall through
1218 case Token::MINUSMINUS: {
1219 Token t = this->nextToken();
1220 std::unique_ptr<ASTExpression> expr = this->unaryExpression();
1221 if (!expr) {
1222 return nullptr;
1223 }
1224 return std::unique_ptr<ASTExpression>(new ASTPrefixExpression(t, std::move(expr)));
1225 }
1226 default:
1227 return this->postfixExpression();
1228 }
1229}
1230
1231/* term suffix* */
1232std::unique_ptr<ASTExpression> Parser::postfixExpression() {
1233 std::unique_ptr<ASTExpression> result = this->term();
1234 if (!result) {
1235 return nullptr;
1236 }
1237 for (;;) {
1238 switch (this->peek().fKind) {
1239 case Token::LBRACKET: // fall through
1240 case Token::DOT: // fall through
1241 case Token::LPAREN: // fall through
1242 case Token::PLUSPLUS: // fall through
1243 case Token::MINUSMINUS: {
1244 std::unique_ptr<ASTSuffix> s = this->suffix();
1245 if (!s) {
1246 return nullptr;
1247 }
1248 result.reset(new ASTSuffixExpression(std::move(result), std::move(s)));
1249 break;
1250 }
1251 default:
1252 return result;
1253 }
1254 }
1255}
1256
1257/* LBRACKET expression RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
1258 PLUSPLUS | MINUSMINUS */
1259std::unique_ptr<ASTSuffix> Parser::suffix() {
1260 Token next = this->nextToken();
1261 switch (next.fKind) {
1262 case Token::LBRACKET: {
1263 std::unique_ptr<ASTExpression> e = this->expression();
1264 if (!e) {
1265 return nullptr;
1266 }
1267 this->expect(Token::RBRACKET, "']' to complete array access expression");
1268 return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e)));
1269 }
1270 case Token::DOT: {
1271 Position pos = this->peek().fPosition;
1272 std::string text;
1273 if (this->identifier(&text)) {
1274 return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(pos, std::move(text)));
1275 }
1276 return nullptr;
1277 }
1278 case Token::LPAREN: {
1279 std::vector<std::unique_ptr<ASTExpression>> parameters;
1280 if (this->peek().fKind != Token::RPAREN) {
1281 for (;;) {
1282 std::unique_ptr<ASTExpression> expr = this->expression();
1283 if (!expr) {
1284 return nullptr;
1285 }
1286 parameters.push_back(std::move(expr));
1287 if (this->peek().fKind != Token::COMMA) {
1288 break;
1289 }
1290 this->nextToken();
1291 }
1292 }
1293 this->expect(Token::RPAREN, "')' to complete function parameters");
1294 return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition,
1295 std::move(parameters)));
1296 }
1297 case Token::PLUSPLUS:
1298 return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
1299 ASTSuffix::kPostIncrement_Kind));
1300 case Token::MINUSMINUS:
1301 return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
1302 ASTSuffix::kPostDecrement_Kind));
1303 default: {
1304 this->error(next.fPosition, "expected expression suffix, but found '" + next.fText +
1305 "'\n");
1306 return nullptr;
1307 }
1308 }
1309}
1310
1311/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */
1312std::unique_ptr<ASTExpression> Parser::term() {
1313 std::unique_ptr<ASTExpression> result;
1314 Token t = this->peek();
1315 switch (t.fKind) {
1316 case Token::IDENTIFIER: {
1317 std::string text;
1318 if (this->identifier(&text)) {
1319 result.reset(new ASTIdentifier(t.fPosition, std::move(text)));
1320 }
1321 break;
1322 }
1323 case Token::INT_LITERAL: {
1324 int64_t i;
1325 if (this->intLiteral(&i)) {
1326 result.reset(new ASTIntLiteral(t.fPosition, i));
1327 }
1328 break;
1329 }
1330 case Token::FLOAT_LITERAL: {
1331 double f;
1332 if (this->floatLiteral(&f)) {
1333 result.reset(new ASTFloatLiteral(t.fPosition, f));
1334 }
1335 break;
1336 }
1337 case Token::TRUE_LITERAL: // fall through
1338 case Token::FALSE_LITERAL: {
1339 bool b;
1340 if (this->boolLiteral(&b)) {
1341 result.reset(new ASTBoolLiteral(t.fPosition, b));
1342 }
1343 break;
1344 }
1345 case Token::LPAREN: {
1346 this->nextToken();
1347 result = this->expression();
1348 if (result) {
1349 this->expect(Token::RPAREN, "')' to complete expression");
1350 }
1351 break;
1352 }
1353 default:
1354 this->nextToken();
1355 this->error(t.fPosition, "expected expression, but found '" + t.fText + "'\n");
1356 result = nullptr;
1357 }
1358 return result;
1359}
1360
1361/* INT_LITERAL */
1362bool Parser::intLiteral(int64_t* dest) {
1363 Token t;
1364 if (this->expect(Token::INT_LITERAL, "integer literal", &t)) {
1365 *dest = SkSL::stol(t.fText);
1366 return true;
1367 }
1368 return false;
1369}
1370
1371/* FLOAT_LITERAL */
1372bool Parser::floatLiteral(double* dest) {
1373 Token t;
1374 if (this->expect(Token::FLOAT_LITERAL, "float literal", &t)) {
1375 *dest = SkSL::stod(t.fText);
1376 return true;
1377 }
1378 return false;
1379}
1380
1381/* TRUE_LITERAL | FALSE_LITERAL */
1382bool Parser::boolLiteral(bool* dest) {
1383 Token t = this->nextToken();
1384 switch (t.fKind) {
1385 case Token::TRUE_LITERAL:
1386 *dest = true;
1387 return true;
1388 case Token::FALSE_LITERAL:
1389 *dest = false;
1390 return true;
1391 default:
1392 this->error(t.fPosition, "expected 'true' or 'false', but found '" + t.fText + "'\n");
1393 return false;
1394 }
1395}
1396
1397/* IDENTIFIER */
1398bool Parser::identifier(std::string* dest) {
1399 Token t;
1400 if (this->expect(Token::IDENTIFIER, "identifier", &t)) {
1401 *dest = t.fText;
1402 return true;
1403 }
1404 return false;
1405}
1406
1407} // namespace