Line data Source code
1 : /*
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 : #include "disable_flex_warnings.h"
14 : #include "lex.sksl.c"
15 : static_assert(YY_FLEX_MAJOR_VERSION * 100 + YY_FLEX_MINOR_VERSION * 10 +
16 : YY_FLEX_SUBMINOR_VERSION >= 261,
17 : "we require Flex 2.6.1 or better for security reasons");
18 : #undef register
19 : #ifdef __clang__
20 : #pragma clang diagnostic pop
21 : #endif
22 : #ifdef __GNUC__
23 : #pragma GCC diagnostic pop
24 : #endif
25 : #ifdef _MSC_VER
26 : #pragma warning(pop)
27 : #endif
28 :
29 : #include "lex.layout.h"
30 : #include "ast/SkSLASTBinaryExpression.h"
31 : #include "ast/SkSLASTBlock.h"
32 : #include "ast/SkSLASTBoolLiteral.h"
33 : #include "ast/SkSLASTBreakStatement.h"
34 : #include "ast/SkSLASTCallSuffix.h"
35 : #include "ast/SkSLASTContinueStatement.h"
36 : #include "ast/SkSLASTDiscardStatement.h"
37 : #include "ast/SkSLASTDoStatement.h"
38 : #include "ast/SkSLASTExpression.h"
39 : #include "ast/SkSLASTExpressionStatement.h"
40 : #include "ast/SkSLASTExtension.h"
41 : #include "ast/SkSLASTFieldSuffix.h"
42 : #include "ast/SkSLASTFloatLiteral.h"
43 : #include "ast/SkSLASTForStatement.h"
44 : #include "ast/SkSLASTFunction.h"
45 : #include "ast/SkSLASTIdentifier.h"
46 : #include "ast/SkSLASTIfStatement.h"
47 : #include "ast/SkSLASTIndexSuffix.h"
48 : #include "ast/SkSLASTInterfaceBlock.h"
49 : #include "ast/SkSLASTIntLiteral.h"
50 : #include "ast/SkSLASTModifiersDeclaration.h"
51 : #include "ast/SkSLASTParameter.h"
52 : #include "ast/SkSLASTPrecision.h"
53 : #include "ast/SkSLASTPrefixExpression.h"
54 : #include "ast/SkSLASTReturnStatement.h"
55 : #include "ast/SkSLASTStatement.h"
56 : #include "ast/SkSLASTSuffixExpression.h"
57 : #include "ast/SkSLASTSwitchCase.h"
58 : #include "ast/SkSLASTSwitchStatement.h"
59 : #include "ast/SkSLASTTernaryExpression.h"
60 : #include "ast/SkSLASTType.h"
61 : #include "ast/SkSLASTVarDeclaration.h"
62 : #include "ast/SkSLASTVarDeclarationStatement.h"
63 : #include "ast/SkSLASTWhileStatement.h"
64 : #include "ir/SkSLSymbolTable.h"
65 : #include "ir/SkSLModifiers.h"
66 : #include "ir/SkSLType.h"
67 :
68 : namespace SkSL {
69 :
70 : #define MAX_PARSE_DEPTH 50
71 :
72 : class AutoDepth {
73 : public:
74 0 : AutoDepth(Parser* p)
75 0 : : fParser(p) {
76 0 : fParser->fDepth++;
77 0 : }
78 :
79 0 : ~AutoDepth() {
80 0 : fParser->fDepth--;
81 0 : }
82 :
83 0 : bool checkValid() {
84 0 : if (fParser->fDepth > MAX_PARSE_DEPTH) {
85 0 : fParser->error(fParser->peek().fPosition, String("exceeded max parse depth"));
86 0 : return false;
87 : }
88 0 : return true;
89 : }
90 :
91 : private:
92 : Parser* fParser;
93 : };
94 :
95 0 : Parser::Parser(String text, SymbolTable& types, ErrorReporter& errors)
96 0 : : fPushback(Position(-1, -1), Token::INVALID_TOKEN, String())
97 : , fTypes(types)
98 0 : , fErrors(errors) {
99 0 : sksllex_init(&fScanner);
100 0 : layoutlex_init(&fLayoutScanner);
101 0 : fBuffer = sksl_scan_string(text.c_str(), fScanner);
102 0 : skslset_lineno(1, fScanner);
103 :
104 : if (false) {
105 : // avoid unused warning
106 : yyunput(0, nullptr, fScanner);
107 : }
108 0 : }
109 :
110 0 : Parser::~Parser() {
111 0 : sksl_delete_buffer(fBuffer, fScanner);
112 0 : sksllex_destroy(fScanner);
113 0 : layoutlex_destroy(fLayoutScanner);
114 0 : }
115 :
116 : /* (precision | directive | declaration)* END_OF_FILE */
117 0 : std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
118 0 : std::vector<std::unique_ptr<ASTDeclaration>> result;
119 : for (;;) {
120 0 : switch (this->peek().fKind) {
121 : case Token::END_OF_FILE:
122 0 : return result;
123 : case Token::PRECISION: {
124 0 : std::unique_ptr<ASTDeclaration> precision = this->precision();
125 0 : if (precision) {
126 0 : result.push_back(std::move(precision));
127 : }
128 0 : break;
129 : }
130 : case Token::DIRECTIVE: {
131 0 : std::unique_ptr<ASTDeclaration> decl = this->directive();
132 0 : if (decl) {
133 0 : result.push_back(std::move(decl));
134 : }
135 0 : break;
136 : }
137 : default: {
138 0 : std::unique_ptr<ASTDeclaration> decl = this->declaration();
139 0 : if (!decl) {
140 0 : continue;
141 : }
142 0 : result.push_back(std::move(decl));
143 : }
144 : }
145 0 : }
146 : }
147 :
148 0 : Token Parser::nextToken() {
149 0 : if (fPushback.fKind != Token::INVALID_TOKEN) {
150 0 : Token result = fPushback;
151 0 : fPushback.fKind = Token::INVALID_TOKEN;
152 0 : fPushback.fText = "";
153 0 : return result;
154 : }
155 0 : int token = sksllex(fScanner);
156 0 : String text;
157 0 : switch ((Token::Kind) token) {
158 : case Token::IDENTIFIER: // fall through
159 : case Token::INT_LITERAL: // fall through
160 : case Token::FLOAT_LITERAL: // fall through
161 : case Token::DIRECTIVE:
162 0 : text = String(skslget_text(fScanner));
163 0 : break;
164 : default:
165 : #ifdef SK_DEBUG
166 0 : text = String(skslget_text(fScanner));
167 : #endif
168 0 : break;
169 : }
170 0 : return Token(Position(skslget_lineno(fScanner), -1), (Token::Kind) token, text);
171 : }
172 :
173 0 : void Parser::pushback(Token t) {
174 0 : ASSERT(fPushback.fKind == Token::INVALID_TOKEN);
175 0 : fPushback = t;
176 0 : }
177 :
178 0 : Token Parser::peek() {
179 0 : fPushback = this->nextToken();
180 0 : return fPushback;
181 : }
182 :
183 :
184 0 : bool Parser::expect(Token::Kind kind, const char* expected, Token* result) {
185 0 : return this->expect(kind, String(expected), result);
186 : }
187 :
188 0 : bool Parser::expect(Token::Kind kind, String expected, Token* result) {
189 0 : Token next = this->nextToken();
190 0 : if (next.fKind == kind) {
191 0 : if (result) {
192 0 : *result = next;
193 : }
194 0 : return true;
195 : } else {
196 0 : if (next.fText.size()) {
197 0 : this->error(next.fPosition, "expected " + expected + ", but found '" + next.fText +
198 0 : "'");
199 : } else {
200 0 : this->error(next.fPosition, "parse error, recompile in debug mode for details");
201 : }
202 0 : return false;
203 : }
204 : }
205 :
206 0 : void Parser::error(Position p, const char* msg) {
207 0 : this->error(p, String(msg));
208 0 : }
209 :
210 0 : void Parser::error(Position p, String msg) {
211 0 : fErrors.error(p, msg);
212 0 : }
213 :
214 0 : bool Parser::isType(String name) {
215 0 : return nullptr != fTypes[name];
216 : }
217 :
218 : /* PRECISION (LOWP | MEDIUMP | HIGHP) type SEMICOLON */
219 0 : std::unique_ptr<ASTDeclaration> Parser::precision() {
220 0 : if (!this->expect(Token::PRECISION, "'precision'")) {
221 0 : return nullptr;
222 : }
223 : Modifiers::Flag result;
224 0 : Token p = this->nextToken();
225 0 : switch (p.fKind) {
226 : case Token::LOWP:
227 0 : result = Modifiers::kLowp_Flag;
228 0 : break;
229 : case Token::MEDIUMP:
230 0 : result = Modifiers::kMediump_Flag;
231 0 : break;
232 : case Token::HIGHP:
233 0 : result = Modifiers::kHighp_Flag;
234 0 : break;
235 : default:
236 0 : this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" +
237 0 : p.fText + "'");
238 0 : return nullptr;
239 : }
240 : // FIXME handle the type
241 0 : if (!this->type()) {
242 0 : return nullptr;
243 : }
244 0 : this->expect(Token::SEMICOLON, "';'");
245 0 : return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result));
246 : }
247 :
248 : /* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
249 : DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
250 0 : std::unique_ptr<ASTDeclaration> Parser::directive() {
251 0 : Token start;
252 0 : if (!this->expect(Token::DIRECTIVE, "a directive", &start)) {
253 0 : return nullptr;
254 : }
255 0 : if (start.fText == "#version") {
256 0 : this->expect(Token::INT_LITERAL, "a version number");
257 0 : Token next = this->peek();
258 0 : if (next.fText == "es" || next.fText == "compatibility") {
259 0 : this->nextToken();
260 : }
261 : // version is ignored for now; it will eventually become an error when we stop pretending
262 : // to be GLSL
263 0 : return nullptr;
264 0 : } else if (start.fText == "#extension") {
265 0 : Token name;
266 0 : if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
267 0 : return nullptr;
268 : }
269 0 : if (!this->expect(Token::COLON, "':'")) {
270 0 : return nullptr;
271 : }
272 : // FIXME: need to start paying attention to this token
273 0 : if (!this->expect(Token::IDENTIFIER, "an identifier")) {
274 0 : return nullptr;
275 : }
276 0 : return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition,
277 0 : std::move(name.fText)));
278 : } else {
279 0 : this->error(start.fPosition, "unsupported directive '" + start.fText + "'");
280 0 : return nullptr;
281 : }
282 : }
283 :
284 : /* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
285 : (COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
286 0 : std::unique_ptr<ASTDeclaration> Parser::declaration() {
287 0 : Modifiers modifiers = this->modifiers();
288 0 : Token lookahead = this->peek();
289 0 : if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) {
290 : // we have an identifier that's not a type, could be the start of an interface block
291 0 : return this->interfaceBlock(modifiers);
292 : }
293 0 : if (lookahead.fKind == Token::STRUCT) {
294 0 : return this->structVarDeclaration(modifiers);
295 : }
296 0 : if (lookahead.fKind == Token::SEMICOLON) {
297 0 : this->nextToken();
298 0 : return std::unique_ptr<ASTDeclaration>(new ASTModifiersDeclaration(modifiers));
299 : }
300 0 : std::unique_ptr<ASTType> type(this->type());
301 0 : if (!type) {
302 0 : return nullptr;
303 : }
304 0 : if (type->fKind == ASTType::kStruct_Kind && peek().fKind == Token::SEMICOLON) {
305 0 : this->nextToken();
306 0 : return nullptr;
307 : }
308 0 : Token name;
309 0 : if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
310 0 : return nullptr;
311 : }
312 0 : if (!modifiers.fFlags && this->peek().fKind == Token::LPAREN) {
313 0 : this->nextToken();
314 0 : std::vector<std::unique_ptr<ASTParameter>> parameters;
315 0 : while (this->peek().fKind != Token::RPAREN) {
316 0 : if (parameters.size() > 0) {
317 0 : if (!this->expect(Token::COMMA, "','")) {
318 0 : return nullptr;
319 : }
320 : }
321 0 : std::unique_ptr<ASTParameter> parameter = this->parameter();
322 0 : if (!parameter) {
323 0 : return nullptr;
324 : }
325 0 : parameters.push_back(std::move(parameter));
326 : }
327 0 : this->nextToken();
328 0 : std::unique_ptr<ASTBlock> body;
329 0 : if (this->peek().fKind == Token::SEMICOLON) {
330 0 : this->nextToken();
331 : } else {
332 0 : body = this->block();
333 0 : if (!body) {
334 0 : return nullptr;
335 : }
336 : }
337 0 : return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition, std::move(type),
338 0 : std::move(name.fText),
339 0 : std::move(parameters),
340 0 : std::move(body)));
341 : } else {
342 0 : return this->varDeclarationEnd(modifiers, std::move(type), name.fText);
343 : }
344 : }
345 :
346 : /* modifiers type IDENTIFIER varDeclarationEnd */
347 0 : std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() {
348 0 : Modifiers modifiers = this->modifiers();
349 0 : std::unique_ptr<ASTType> type(this->type());
350 0 : if (!type) {
351 0 : return nullptr;
352 : }
353 0 : Token name;
354 0 : if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
355 0 : return nullptr;
356 : }
357 0 : return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText));
358 : }
359 :
360 : /* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
361 0 : std::unique_ptr<ASTType> Parser::structDeclaration() {
362 0 : if (!this->expect(Token::STRUCT, "'struct'")) {
363 0 : return nullptr;
364 : }
365 0 : Token name;
366 0 : if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
367 0 : return nullptr;
368 : }
369 0 : if (!this->expect(Token::LBRACE, "'{'")) {
370 0 : return nullptr;
371 : }
372 0 : std::vector<Type::Field> fields;
373 0 : while (this->peek().fKind != Token::RBRACE) {
374 0 : std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
375 0 : if (!decl) {
376 0 : return nullptr;
377 : }
378 0 : for (const auto& var : decl->fVars) {
379 0 : auto type = (const Type*) fTypes[decl->fType->fName];
380 0 : for (int i = (int) var.fSizes.size() - 1; i >= 0; i--) {
381 0 : if (!var.fSizes[i] || var.fSizes[i]->fKind != ASTExpression::kInt_Kind) {
382 0 : this->error(decl->fPosition, "array size in struct field must be a constant");
383 0 : return nullptr;
384 : }
385 0 : uint64_t columns = ((ASTIntLiteral&) *var.fSizes[i]).fValue;
386 0 : String name = type->name() + "[" + to_string(columns) + "]";
387 0 : type = new Type(name, Type::kArray_Kind, *type, (int) columns);
388 0 : fTypes.takeOwnership((Type*) type);
389 : }
390 0 : fields.push_back(Type::Field(decl->fModifiers, var.fName, type));
391 0 : if (var.fValue) {
392 0 : this->error(decl->fPosition, "initializers are not permitted on struct fields");
393 : }
394 : }
395 : }
396 0 : if (!this->expect(Token::RBRACE, "'}'")) {
397 0 : return nullptr;
398 : }
399 0 : fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fPosition, name.fText, fields)));
400 0 : return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText,
401 0 : ASTType::kStruct_Kind, std::vector<int>()));
402 : }
403 :
404 : /* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
405 0 : std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(Modifiers modifiers) {
406 0 : std::unique_ptr<ASTType> type = this->structDeclaration();
407 0 : if (!type) {
408 0 : return nullptr;
409 : }
410 0 : if (peek().fKind == Token::IDENTIFIER) {
411 0 : Token name = this->nextToken();
412 : std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers,
413 0 : std::move(type),
414 0 : std::move(name.fText));
415 0 : if (result) {
416 0 : for (const auto& var : result->fVars) {
417 0 : if (var.fValue) {
418 0 : this->error(var.fValue->fPosition,
419 0 : "struct variables cannot be initialized");
420 : }
421 : }
422 : }
423 0 : return result;
424 : }
425 0 : this->expect(Token::SEMICOLON, "';'");
426 0 : return nullptr;
427 : }
428 :
429 : /* (LBRACKET expression? RBRACKET)* (EQ expression)? (COMMA IDENTIFER
430 : (LBRACKET expression? RBRACKET)* (EQ expression)?)* SEMICOLON */
431 0 : std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods,
432 : std::unique_ptr<ASTType> type,
433 : String name) {
434 0 : std::vector<ASTVarDeclaration> vars;
435 0 : std::vector<std::unique_ptr<ASTExpression>> currentVarSizes;
436 0 : while (this->peek().fKind == Token::LBRACKET) {
437 0 : this->nextToken();
438 0 : if (this->peek().fKind == Token::RBRACKET) {
439 0 : this->nextToken();
440 0 : currentVarSizes.push_back(nullptr);
441 : } else {
442 0 : std::unique_ptr<ASTExpression> size(this->expression());
443 0 : if (!size) {
444 0 : return nullptr;
445 : }
446 0 : currentVarSizes.push_back(std::move(size));
447 0 : if (!this->expect(Token::RBRACKET, "']'")) {
448 0 : return nullptr;
449 : }
450 : }
451 : }
452 0 : std::unique_ptr<ASTExpression> value;
453 0 : if (this->peek().fKind == Token::EQ) {
454 0 : this->nextToken();
455 0 : value = this->expression();
456 0 : if (!value) {
457 0 : return nullptr;
458 : }
459 : }
460 0 : vars.emplace_back(std::move(name), std::move(currentVarSizes), std::move(value));
461 0 : while (this->peek().fKind == Token::COMMA) {
462 0 : this->nextToken();
463 0 : Token name;
464 0 : if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
465 0 : return nullptr;
466 : }
467 0 : currentVarSizes.clear();
468 0 : value.reset();
469 0 : while (this->peek().fKind == Token::LBRACKET) {
470 0 : this->nextToken();
471 0 : if (this->peek().fKind == Token::RBRACKET) {
472 0 : this->nextToken();
473 0 : currentVarSizes.push_back(nullptr);
474 : } else {
475 0 : std::unique_ptr<ASTExpression> size(this->expression());
476 0 : if (!size) {
477 0 : return nullptr;
478 : }
479 0 : currentVarSizes.push_back(std::move(size));
480 0 : if (!this->expect(Token::RBRACKET, "']'")) {
481 0 : return nullptr;
482 : }
483 : }
484 : }
485 0 : if (this->peek().fKind == Token::EQ) {
486 0 : this->nextToken();
487 0 : value = this->expression();
488 0 : if (!value) {
489 0 : return nullptr;
490 : }
491 : }
492 0 : vars.emplace_back(std::move(name.fText), std::move(currentVarSizes), std::move(value));
493 : }
494 0 : if (!this->expect(Token::SEMICOLON, "';'")) {
495 0 : return nullptr;
496 : }
497 0 : return std::unique_ptr<ASTVarDeclarations>(new ASTVarDeclarations(std::move(mods),
498 0 : std::move(type),
499 0 : std::move(vars)));
500 : }
501 :
502 : /* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
503 0 : std::unique_ptr<ASTParameter> Parser::parameter() {
504 0 : Modifiers modifiers = this->modifiersWithDefaults(0);
505 0 : std::unique_ptr<ASTType> type = this->type();
506 0 : if (!type) {
507 0 : return nullptr;
508 : }
509 0 : Token name;
510 0 : if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
511 0 : return nullptr;
512 : }
513 0 : std::vector<int> sizes;
514 0 : while (this->peek().fKind == Token::LBRACKET) {
515 0 : this->nextToken();
516 0 : Token sizeToken;
517 0 : if (!this->expect(Token::INT_LITERAL, "a positive integer", &sizeToken)) {
518 0 : return nullptr;
519 : }
520 0 : sizes.push_back(SkSL::stoi(sizeToken.fText));
521 0 : if (!this->expect(Token::RBRACKET, "']'")) {
522 0 : return nullptr;
523 : }
524 : }
525 0 : return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers,
526 0 : std::move(type), name.fText,
527 0 : std::move(sizes)));
528 : }
529 :
530 : /** (EQ INT_LITERAL)? */
531 0 : int Parser::layoutInt() {
532 0 : if (!this->expect(Token::EQ, "'='")) {
533 0 : return -1;
534 : }
535 0 : Token resultToken;
536 0 : if (this->expect(Token::INT_LITERAL, "a non-negative integer", &resultToken)) {
537 0 : return SkSL::stoi(resultToken.fText);
538 : }
539 0 : return -1;
540 : }
541 :
542 : /* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
543 0 : Layout Parser::layout() {
544 0 : int location = -1;
545 0 : int offset = -1;
546 0 : int binding = -1;
547 0 : int index = -1;
548 0 : int set = -1;
549 0 : int builtin = -1;
550 0 : int inputAttachmentIndex = -1;
551 0 : bool originUpperLeft = false;
552 0 : bool overrideCoverage = false;
553 0 : bool blendSupportAllEquations = false;
554 0 : Layout::Format format = Layout::Format::kUnspecified;
555 0 : bool pushConstant = false;
556 0 : Layout::Primitive primitive = Layout::kUnspecified_Primitive;
557 0 : int maxVertices = -1;
558 0 : int invocations = -1;
559 0 : if (this->peek().fKind == Token::LAYOUT) {
560 0 : this->nextToken();
561 0 : if (!this->expect(Token::LPAREN, "'('")) {
562 : return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
563 : originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
564 0 : pushConstant, primitive, maxVertices, invocations);
565 : }
566 : for (;;) {
567 0 : Token t = this->nextToken();
568 : YY_BUFFER_STATE buffer;
569 0 : buffer = layout_scan_string(t.fText.c_str(), fLayoutScanner);
570 0 : int token = layoutlex(fLayoutScanner);
571 0 : layout_delete_buffer(buffer, fLayoutScanner);
572 0 : if (token != Token::INVALID_TOKEN) {
573 0 : switch (token) {
574 : case Token::LOCATION:
575 0 : location = this->layoutInt();
576 0 : break;
577 : case Token::OFFSET:
578 0 : offset = this->layoutInt();
579 0 : break;
580 : case Token::BINDING:
581 0 : binding = this->layoutInt();
582 0 : break;
583 : case Token::INDEX:
584 0 : index = this->layoutInt();
585 0 : break;
586 : case Token::SET:
587 0 : set = this->layoutInt();
588 0 : break;
589 : case Token::BUILTIN:
590 0 : builtin = this->layoutInt();
591 0 : break;
592 : case Token::INPUT_ATTACHMENT_INDEX:
593 0 : inputAttachmentIndex = this->layoutInt();
594 0 : break;
595 : case Token::ORIGIN_UPPER_LEFT:
596 0 : originUpperLeft = true;
597 0 : break;
598 : case Token::OVERRIDE_COVERAGE:
599 0 : overrideCoverage = true;
600 0 : break;
601 : case Token::BLEND_SUPPORT_ALL_EQUATIONS:
602 0 : blendSupportAllEquations = true;
603 0 : break;
604 : case Token::PUSH_CONSTANT:
605 0 : pushConstant = true;
606 0 : break;
607 : case Token::POINTS:
608 0 : primitive = Layout::kPoints_Primitive;
609 0 : break;
610 : case Token::LINES:
611 0 : primitive = Layout::kLines_Primitive;
612 0 : break;
613 : case Token::LINE_STRIP:
614 0 : primitive = Layout::kLineStrip_Primitive;
615 0 : break;
616 : case Token::LINES_ADJACENCY:
617 0 : primitive = Layout::kLinesAdjacency_Primitive;
618 0 : break;
619 : case Token::TRIANGLES:
620 0 : primitive = Layout::kTriangles_Primitive;
621 0 : break;
622 : case Token::TRIANGLE_STRIP:
623 0 : primitive = Layout::kTriangleStrip_Primitive;
624 0 : break;
625 : case Token::TRIANGLES_ADJACENCY:
626 0 : primitive = Layout::kTrianglesAdjacency_Primitive;
627 0 : break;
628 : case Token::MAX_VERTICES:
629 0 : maxVertices = this->layoutInt();
630 0 : break;
631 : case Token::INVOCATIONS:
632 0 : invocations = this->layoutInt();
633 0 : break;
634 : }
635 0 : } else if (Layout::ReadFormat(t.fText, &format)) {
636 : // AST::ReadFormat stored the result in 'format'.
637 : } else {
638 0 : this->error(t.fPosition, ("'" + t.fText +
639 0 : "' is not a valid layout qualifier").c_str());
640 : }
641 0 : if (this->peek().fKind == Token::RPAREN) {
642 0 : this->nextToken();
643 0 : break;
644 : }
645 0 : if (!this->expect(Token::COMMA, "','")) {
646 0 : break;
647 : }
648 0 : }
649 : }
650 : return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
651 : originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
652 0 : pushConstant, primitive, maxVertices, invocations);
653 : }
654 :
655 : /* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE |
656 : READONLY | WRITEONLY | COHERENT | VOLATILE | RESTRICT)* */
657 0 : Modifiers Parser::modifiers() {
658 0 : Layout layout = this->layout();
659 0 : int flags = 0;
660 : for (;;) {
661 : // TODO: handle duplicate / incompatible flags
662 0 : switch (peek().fKind) {
663 : case Token::UNIFORM:
664 0 : this->nextToken();
665 0 : flags |= Modifiers::kUniform_Flag;
666 0 : break;
667 : case Token::CONST:
668 0 : this->nextToken();
669 0 : flags |= Modifiers::kConst_Flag;
670 0 : break;
671 : case Token::IN:
672 0 : this->nextToken();
673 0 : flags |= Modifiers::kIn_Flag;
674 0 : break;
675 : case Token::OUT:
676 0 : this->nextToken();
677 0 : flags |= Modifiers::kOut_Flag;
678 0 : break;
679 : case Token::INOUT:
680 0 : this->nextToken();
681 0 : flags |= Modifiers::kIn_Flag;
682 0 : flags |= Modifiers::kOut_Flag;
683 0 : break;
684 : case Token::LOWP:
685 0 : this->nextToken();
686 0 : flags |= Modifiers::kLowp_Flag;
687 0 : break;
688 : case Token::MEDIUMP:
689 0 : this->nextToken();
690 0 : flags |= Modifiers::kMediump_Flag;
691 0 : break;
692 : case Token::HIGHP:
693 0 : this->nextToken();
694 0 : flags |= Modifiers::kHighp_Flag;
695 0 : break;
696 : case Token::FLAT:
697 0 : this->nextToken();
698 0 : flags |= Modifiers::kFlat_Flag;
699 0 : break;
700 : case Token::NOPERSPECTIVE:
701 0 : this->nextToken();
702 0 : flags |= Modifiers::kNoPerspective_Flag;
703 0 : break;
704 : case Token::READONLY:
705 0 : this->nextToken();
706 0 : flags |= Modifiers::kReadOnly_Flag;
707 0 : break;
708 : case Token::WRITEONLY:
709 0 : this->nextToken();
710 0 : flags |= Modifiers::kWriteOnly_Flag;
711 0 : break;
712 : case Token::COHERENT:
713 0 : this->nextToken();
714 0 : flags |= Modifiers::kCoherent_Flag;
715 0 : break;
716 : case Token::VOLATILE:
717 0 : this->nextToken();
718 0 : flags |= Modifiers::kVolatile_Flag;
719 0 : break;
720 : case Token::RESTRICT:
721 0 : this->nextToken();
722 0 : flags |= Modifiers::kRestrict_Flag;
723 0 : break;
724 : default:
725 0 : return Modifiers(layout, flags);
726 : }
727 : }
728 : }
729 :
730 0 : Modifiers Parser::modifiersWithDefaults(int defaultFlags) {
731 0 : Modifiers result = this->modifiers();
732 0 : if (!result.fFlags) {
733 0 : return Modifiers(result.fLayout, defaultFlags);
734 : }
735 0 : return result;
736 : }
737 :
738 : /* ifStatement | forStatement | doStatement | whileStatement | block | expression */
739 0 : std::unique_ptr<ASTStatement> Parser::statement() {
740 0 : Token start = this->peek();
741 0 : switch (start.fKind) {
742 : case Token::IF:
743 0 : return this->ifStatement();
744 : case Token::FOR:
745 0 : return this->forStatement();
746 : case Token::DO:
747 0 : return this->doStatement();
748 : case Token::WHILE:
749 0 : return this->whileStatement();
750 : case Token::SWITCH:
751 0 : return this->switchStatement();
752 : case Token::RETURN:
753 0 : return this->returnStatement();
754 : case Token::BREAK:
755 0 : return this->breakStatement();
756 : case Token::CONTINUE:
757 0 : return this->continueStatement();
758 : case Token::DISCARD:
759 0 : return this->discardStatement();
760 : case Token::LBRACE:
761 0 : return this->block();
762 : case Token::SEMICOLON:
763 0 : this->nextToken();
764 0 : return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition,
765 0 : std::vector<std::unique_ptr<ASTStatement>>()));
766 : case Token::CONST: // fall through
767 : case Token::HIGHP: // fall through
768 : case Token::MEDIUMP: // fall through
769 : case Token::LOWP: {
770 0 : auto decl = this->varDeclarations();
771 0 : if (!decl) {
772 0 : return nullptr;
773 : }
774 0 : return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(std::move(decl)));
775 : }
776 : case Token::IDENTIFIER:
777 0 : if (this->isType(start.fText)) {
778 0 : auto decl = this->varDeclarations();
779 0 : if (!decl) {
780 0 : return nullptr;
781 : }
782 : return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
783 0 : std::move(decl)));
784 : }
785 : // fall through
786 : default:
787 0 : return this->expressionStatement();
788 : }
789 : }
790 :
791 : /* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* */
792 0 : std::unique_ptr<ASTType> Parser::type() {
793 0 : Token type;
794 0 : if (!this->expect(Token::IDENTIFIER, "a type", &type)) {
795 0 : return nullptr;
796 : }
797 0 : if (!this->isType(type.fText)) {
798 0 : this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str());
799 0 : return nullptr;
800 : }
801 0 : std::vector<int> sizes;
802 0 : while (this->peek().fKind == Token::LBRACKET) {
803 0 : this->expect(Token::LBRACKET, "'['");
804 0 : if (this->peek().fKind != Token::RBRACKET) {
805 : int64_t i;
806 0 : if (this->intLiteral(&i)) {
807 0 : sizes.push_back(i);
808 : } else {
809 0 : return nullptr;
810 : }
811 : } else {
812 0 : sizes.push_back(-1);
813 : }
814 0 : this->expect(Token::RBRACKET, "']'");
815 : }
816 0 : return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText),
817 0 : ASTType::kIdentifier_Kind, sizes));
818 : }
819 :
820 : /* IDENTIFIER LBRACE varDeclaration* RBRACE (IDENTIFIER (LBRACKET expression? RBRACKET)*)? */
821 0 : std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) {
822 0 : Token name;
823 0 : if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
824 0 : return nullptr;
825 : }
826 0 : if (peek().fKind != Token::LBRACE) {
827 : // we only get into interfaceBlock if we found a top-level identifier which was not a type.
828 : // 99% of the time, the user was not actually intending to create an interface block, so
829 : // it's better to report it as an unknown type
830 0 : this->error(name.fPosition, "no type named '" + name.fText + "'");
831 0 : return nullptr;
832 : }
833 0 : this->nextToken();
834 0 : std::vector<std::unique_ptr<ASTVarDeclarations>> decls;
835 0 : while (this->peek().fKind != Token::RBRACE) {
836 0 : std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
837 0 : if (!decl) {
838 0 : return nullptr;
839 : }
840 0 : decls.push_back(std::move(decl));
841 : }
842 0 : this->nextToken();
843 0 : String instanceName;
844 0 : std::vector<std::unique_ptr<ASTExpression>> sizes;
845 0 : if (this->peek().fKind == Token::IDENTIFIER) {
846 0 : instanceName = this->nextToken().fText;
847 0 : while (this->peek().fKind == Token::LBRACKET) {
848 0 : this->expect(Token::LBRACKET, "'['");
849 0 : if (this->peek().fKind != Token::RBRACKET) {
850 0 : std::unique_ptr<ASTExpression> size = this->expression();
851 0 : if (!size) {
852 0 : return nullptr;
853 : }
854 0 : sizes.push_back(std::move(size));
855 : } else {
856 0 : sizes.push_back(nullptr);
857 : }
858 0 : this->expect(Token::RBRACKET, "']'");
859 : }
860 : }
861 0 : this->expect(Token::SEMICOLON, "';'");
862 0 : return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods,
863 0 : name.fText, std::move(decls),
864 0 : std::move(instanceName),
865 0 : std::move(sizes)));
866 : }
867 :
868 : /* IF LPAREN expression RPAREN statement (ELSE statement)? */
869 0 : std::unique_ptr<ASTIfStatement> Parser::ifStatement() {
870 0 : Token start;
871 0 : if (!this->expect(Token::IF, "'if'", &start)) {
872 0 : return nullptr;
873 : }
874 0 : if (!this->expect(Token::LPAREN, "'('")) {
875 0 : return nullptr;
876 : }
877 0 : std::unique_ptr<ASTExpression> test(this->expression());
878 0 : if (!test) {
879 0 : return nullptr;
880 : }
881 0 : if (!this->expect(Token::RPAREN, "')'")) {
882 0 : return nullptr;
883 : }
884 0 : std::unique_ptr<ASTStatement> ifTrue(this->statement());
885 0 : if (!ifTrue) {
886 0 : return nullptr;
887 : }
888 0 : std::unique_ptr<ASTStatement> ifFalse;
889 0 : if (this->peek().fKind == Token::ELSE) {
890 0 : this->nextToken();
891 0 : ifFalse = this->statement();
892 0 : if (!ifFalse) {
893 0 : return nullptr;
894 : }
895 : }
896 0 : return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, std::move(test),
897 0 : std::move(ifTrue),
898 0 : std::move(ifFalse)));
899 : }
900 :
901 : /* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
902 0 : std::unique_ptr<ASTDoStatement> Parser::doStatement() {
903 0 : Token start;
904 0 : if (!this->expect(Token::DO, "'do'", &start)) {
905 0 : return nullptr;
906 : }
907 0 : std::unique_ptr<ASTStatement> statement(this->statement());
908 0 : if (!statement) {
909 0 : return nullptr;
910 : }
911 0 : if (!this->expect(Token::WHILE, "'while'")) {
912 0 : return nullptr;
913 : }
914 0 : if (!this->expect(Token::LPAREN, "'('")) {
915 0 : return nullptr;
916 : }
917 0 : std::unique_ptr<ASTExpression> test(this->expression());
918 0 : if (!test) {
919 0 : return nullptr;
920 : }
921 0 : if (!this->expect(Token::RPAREN, "')'")) {
922 0 : return nullptr;
923 : }
924 0 : if (!this->expect(Token::SEMICOLON, "';'")) {
925 0 : return nullptr;
926 : }
927 0 : return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition,
928 0 : std::move(statement),
929 0 : std::move(test)));
930 : }
931 :
932 : /* WHILE LPAREN expression RPAREN STATEMENT */
933 0 : std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
934 0 : Token start;
935 0 : if (!this->expect(Token::WHILE, "'while'", &start)) {
936 0 : return nullptr;
937 : }
938 0 : if (!this->expect(Token::LPAREN, "'('")) {
939 0 : return nullptr;
940 : }
941 0 : std::unique_ptr<ASTExpression> test(this->expression());
942 0 : if (!test) {
943 0 : return nullptr;
944 : }
945 0 : if (!this->expect(Token::RPAREN, "')'")) {
946 0 : return nullptr;
947 : }
948 0 : std::unique_ptr<ASTStatement> statement(this->statement());
949 0 : if (!statement) {
950 0 : return nullptr;
951 : }
952 0 : return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition,
953 0 : std::move(test),
954 0 : std::move(statement)));
955 : }
956 :
957 : /* CASE expression COLON statement* */
958 0 : std::unique_ptr<ASTSwitchCase> Parser::switchCase() {
959 0 : Token start;
960 0 : if (!this->expect(Token::CASE, "'case'", &start)) {
961 0 : return nullptr;
962 : }
963 0 : std::unique_ptr<ASTExpression> value = this->expression();
964 0 : if (!value) {
965 0 : return nullptr;
966 : }
967 0 : if (!this->expect(Token::COLON, "':'")) {
968 0 : return nullptr;
969 : }
970 0 : std::vector<std::unique_ptr<ASTStatement>> statements;
971 0 : while (this->peek().fKind != Token::RBRACE && this->peek().fKind != Token::CASE &&
972 0 : this->peek().fKind != Token::DEFAULT) {
973 0 : std::unique_ptr<ASTStatement> s = this->statement();
974 0 : if (!s) {
975 0 : return nullptr;
976 : }
977 0 : statements.push_back(std::move(s));
978 : }
979 0 : return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fPosition, std::move(value),
980 0 : std::move(statements)));
981 : }
982 :
983 : /* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
984 0 : std::unique_ptr<ASTStatement> Parser::switchStatement() {
985 0 : Token start;
986 0 : if (!this->expect(Token::SWITCH, "'switch'", &start)) {
987 0 : return nullptr;
988 : }
989 0 : if (!this->expect(Token::LPAREN, "'('")) {
990 0 : return nullptr;
991 : }
992 0 : std::unique_ptr<ASTExpression> value(this->expression());
993 0 : if (!value) {
994 0 : return nullptr;
995 : }
996 0 : if (!this->expect(Token::RPAREN, "')'")) {
997 0 : return nullptr;
998 : }
999 0 : if (!this->expect(Token::LBRACE, "'{'")) {
1000 0 : return nullptr;
1001 : }
1002 0 : std::vector<std::unique_ptr<ASTSwitchCase>> cases;
1003 0 : while (this->peek().fKind == Token::CASE) {
1004 0 : std::unique_ptr<ASTSwitchCase> c = this->switchCase();
1005 0 : if (!c) {
1006 0 : return nullptr;
1007 : }
1008 0 : cases.push_back(std::move(c));
1009 : }
1010 : // Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
1011 : // parts of the compiler may rely upon this assumption.
1012 0 : if (this->peek().fKind == Token::DEFAULT) {
1013 0 : Token defaultStart;
1014 0 : ASSERT_RESULT(this->expect(Token::DEFAULT, "'default'", &defaultStart));
1015 0 : if (!this->expect(Token::COLON, "':'")) {
1016 0 : return nullptr;
1017 : }
1018 0 : std::vector<std::unique_ptr<ASTStatement>> statements;
1019 0 : while (this->peek().fKind != Token::RBRACE) {
1020 0 : std::unique_ptr<ASTStatement> s = this->statement();
1021 0 : if (!s) {
1022 0 : return nullptr;
1023 : }
1024 0 : statements.push_back(std::move(s));
1025 : }
1026 0 : cases.emplace_back(new ASTSwitchCase(defaultStart.fPosition, nullptr,
1027 0 : std::move(statements)));
1028 : }
1029 0 : if (!this->expect(Token::RBRACE, "'}'")) {
1030 0 : return nullptr;
1031 : }
1032 0 : return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fPosition,
1033 0 : std::move(value),
1034 0 : std::move(cases)));
1035 : }
1036 :
1037 : /* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
1038 : STATEMENT */
1039 0 : std::unique_ptr<ASTForStatement> Parser::forStatement() {
1040 0 : Token start;
1041 0 : if (!this->expect(Token::FOR, "'for'", &start)) {
1042 0 : return nullptr;
1043 : }
1044 0 : if (!this->expect(Token::LPAREN, "'('")) {
1045 0 : return nullptr;
1046 : }
1047 0 : std::unique_ptr<ASTStatement> initializer;
1048 0 : Token nextToken = this->peek();
1049 0 : switch (nextToken.fKind) {
1050 : case Token::SEMICOLON:
1051 0 : this->nextToken();
1052 0 : break;
1053 : case Token::CONST: {
1054 0 : std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
1055 0 : if (!vd) {
1056 0 : return nullptr;
1057 : }
1058 0 : initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
1059 0 : std::move(vd)));
1060 0 : break;
1061 : }
1062 : case Token::IDENTIFIER: {
1063 0 : if (this->isType(nextToken.fText)) {
1064 0 : std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
1065 0 : if (!vd) {
1066 0 : return nullptr;
1067 : }
1068 0 : initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
1069 0 : std::move(vd)));
1070 0 : break;
1071 : }
1072 : } // fall through
1073 : default:
1074 0 : initializer = this->expressionStatement();
1075 : }
1076 0 : std::unique_ptr<ASTExpression> test;
1077 0 : if (this->peek().fKind != Token::SEMICOLON) {
1078 0 : test = this->expression();
1079 0 : if (!test) {
1080 0 : return nullptr;
1081 : }
1082 : }
1083 0 : if (!this->expect(Token::SEMICOLON, "';'")) {
1084 0 : return nullptr;
1085 : }
1086 0 : std::unique_ptr<ASTExpression> next;
1087 0 : if (this->peek().fKind != Token::RPAREN) {
1088 0 : next = this->expression();
1089 0 : if (!next) {
1090 0 : return nullptr;
1091 : }
1092 : }
1093 0 : if (!this->expect(Token::RPAREN, "')'")) {
1094 0 : return nullptr;
1095 : }
1096 0 : std::unique_ptr<ASTStatement> statement(this->statement());
1097 0 : if (!statement) {
1098 0 : return nullptr;
1099 : }
1100 0 : return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition,
1101 0 : std::move(initializer),
1102 0 : std::move(test), std::move(next),
1103 0 : std::move(statement)));
1104 : }
1105 :
1106 : /* RETURN expression? SEMICOLON */
1107 0 : std::unique_ptr<ASTReturnStatement> Parser::returnStatement() {
1108 0 : Token start;
1109 0 : if (!this->expect(Token::RETURN, "'return'", &start)) {
1110 0 : return nullptr;
1111 : }
1112 0 : std::unique_ptr<ASTExpression> expression;
1113 0 : if (this->peek().fKind != Token::SEMICOLON) {
1114 0 : expression = this->expression();
1115 0 : if (!expression) {
1116 0 : return nullptr;
1117 : }
1118 : }
1119 0 : if (!this->expect(Token::SEMICOLON, "';'")) {
1120 0 : return nullptr;
1121 : }
1122 0 : return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition,
1123 0 : std::move(expression)));
1124 : }
1125 :
1126 : /* BREAK SEMICOLON */
1127 0 : std::unique_ptr<ASTBreakStatement> Parser::breakStatement() {
1128 0 : Token start;
1129 0 : if (!this->expect(Token::BREAK, "'break'", &start)) {
1130 0 : return nullptr;
1131 : }
1132 0 : if (!this->expect(Token::SEMICOLON, "';'")) {
1133 0 : return nullptr;
1134 : }
1135 0 : return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fPosition));
1136 : }
1137 :
1138 : /* CONTINUE SEMICOLON */
1139 0 : std::unique_ptr<ASTContinueStatement> Parser::continueStatement() {
1140 0 : Token start;
1141 0 : if (!this->expect(Token::CONTINUE, "'continue'", &start)) {
1142 0 : return nullptr;
1143 : }
1144 0 : if (!this->expect(Token::SEMICOLON, "';'")) {
1145 0 : return nullptr;
1146 : }
1147 0 : return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fPosition));
1148 : }
1149 :
1150 : /* DISCARD SEMICOLON */
1151 0 : std::unique_ptr<ASTDiscardStatement> Parser::discardStatement() {
1152 0 : Token start;
1153 0 : if (!this->expect(Token::DISCARD, "'continue'", &start)) {
1154 0 : return nullptr;
1155 : }
1156 0 : if (!this->expect(Token::SEMICOLON, "';'")) {
1157 0 : return nullptr;
1158 : }
1159 0 : return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fPosition));
1160 : }
1161 :
1162 : /* LBRACE statement* RBRACE */
1163 0 : std::unique_ptr<ASTBlock> Parser::block() {
1164 0 : AutoDepth depth(this);
1165 0 : if (!depth.checkValid()) {
1166 0 : return nullptr;
1167 : }
1168 0 : Token start;
1169 0 : if (!this->expect(Token::LBRACE, "'{'", &start)) {
1170 0 : return nullptr;
1171 : }
1172 0 : std::vector<std::unique_ptr<ASTStatement>> statements;
1173 : for (;;) {
1174 0 : switch (this->peek().fKind) {
1175 : case Token::RBRACE:
1176 0 : this->nextToken();
1177 0 : return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition,
1178 0 : std::move(statements)));
1179 : case Token::END_OF_FILE:
1180 0 : this->error(this->peek().fPosition, "expected '}', but found end of file");
1181 0 : return nullptr;
1182 : default: {
1183 0 : std::unique_ptr<ASTStatement> statement = this->statement();
1184 0 : if (!statement) {
1185 0 : return nullptr;
1186 : }
1187 0 : statements.push_back(std::move(statement));
1188 : }
1189 : }
1190 0 : }
1191 : }
1192 :
1193 : /* expression SEMICOLON */
1194 0 : std::unique_ptr<ASTExpressionStatement> Parser::expressionStatement() {
1195 0 : std::unique_ptr<ASTExpression> expr = this->expression();
1196 0 : if (expr) {
1197 0 : if (this->expect(Token::SEMICOLON, "';'")) {
1198 0 : ASTExpressionStatement* result = new ASTExpressionStatement(std::move(expr));
1199 0 : return std::unique_ptr<ASTExpressionStatement>(result);
1200 : }
1201 : }
1202 0 : return nullptr;
1203 : }
1204 :
1205 : /* assignmentExpression */
1206 0 : std::unique_ptr<ASTExpression> Parser::expression() {
1207 0 : AutoDepth depth(this);
1208 0 : if (!depth.checkValid()) {
1209 0 : return nullptr;
1210 : }
1211 0 : return this->assignmentExpression();
1212 : }
1213 :
1214 : /* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ |
1215 : BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
1216 : assignmentExpression)*
1217 : */
1218 0 : std::unique_ptr<ASTExpression> Parser::assignmentExpression() {
1219 0 : std::unique_ptr<ASTExpression> result = this->ternaryExpression();
1220 0 : if (!result) {
1221 0 : return nullptr;
1222 : }
1223 : for (;;) {
1224 0 : switch (this->peek().fKind) {
1225 : case Token::EQ: // fall through
1226 : case Token::STAREQ: // fall through
1227 : case Token::SLASHEQ: // fall through
1228 : case Token::PERCENTEQ: // fall through
1229 : case Token::PLUSEQ: // fall through
1230 : case Token::MINUSEQ: // fall through
1231 : case Token::SHLEQ: // fall through
1232 : case Token::SHREQ: // fall through
1233 : case Token::BITWISEANDEQ: // fall through
1234 : case Token::BITWISEXOREQ: // fall through
1235 : case Token::BITWISEOREQ: // fall through
1236 : case Token::LOGICALANDEQ: // fall through
1237 : case Token::LOGICALXOREQ: // fall through
1238 : case Token::LOGICALOREQ: {
1239 0 : Token t = this->nextToken();
1240 0 : std::unique_ptr<ASTExpression> right = this->assignmentExpression();
1241 0 : if (!right) {
1242 0 : return nullptr;
1243 : }
1244 0 : result = std::unique_ptr<ASTExpression>(new ASTBinaryExpression(std::move(result),
1245 : t,
1246 0 : std::move(right)));
1247 : }
1248 : default:
1249 0 : return result;
1250 : }
1251 : }
1252 : }
1253 :
1254 : /* logicalOrExpression ('?' expression ':' assignmentExpression)? */
1255 0 : std::unique_ptr<ASTExpression> Parser::ternaryExpression() {
1256 0 : std::unique_ptr<ASTExpression> result = this->logicalOrExpression();
1257 0 : if (!result) {
1258 0 : return nullptr;
1259 : }
1260 0 : if (this->peek().fKind == Token::QUESTION) {
1261 0 : Token question = this->nextToken();
1262 0 : std::unique_ptr<ASTExpression> trueExpr = this->expression();
1263 0 : if (!trueExpr) {
1264 0 : return nullptr;
1265 : }
1266 0 : if (this->expect(Token::COLON, "':'")) {
1267 0 : std::unique_ptr<ASTExpression> falseExpr = this->assignmentExpression();
1268 0 : return std::unique_ptr<ASTExpression>(new ASTTernaryExpression(std::move(result),
1269 0 : std::move(trueExpr),
1270 0 : std::move(falseExpr)));
1271 : }
1272 0 : return nullptr;
1273 : }
1274 0 : return result;
1275 : }
1276 :
1277 : /* logicalXorExpression (LOGICALOR logicalXorExpression)* */
1278 0 : std::unique_ptr<ASTExpression> Parser::logicalOrExpression() {
1279 0 : std::unique_ptr<ASTExpression> result = this->logicalXorExpression();
1280 0 : if (!result) {
1281 0 : return nullptr;
1282 : }
1283 0 : while (this->peek().fKind == Token::LOGICALOR) {
1284 0 : Token t = this->nextToken();
1285 0 : std::unique_ptr<ASTExpression> right = this->logicalXorExpression();
1286 0 : if (!right) {
1287 0 : return nullptr;
1288 : }
1289 0 : result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1290 : }
1291 0 : return result;
1292 : }
1293 :
1294 : /* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
1295 0 : std::unique_ptr<ASTExpression> Parser::logicalXorExpression() {
1296 0 : std::unique_ptr<ASTExpression> result = this->logicalAndExpression();
1297 0 : if (!result) {
1298 0 : return nullptr;
1299 : }
1300 0 : while (this->peek().fKind == Token::LOGICALXOR) {
1301 0 : Token t = this->nextToken();
1302 0 : std::unique_ptr<ASTExpression> right = this->logicalAndExpression();
1303 0 : if (!right) {
1304 0 : return nullptr;
1305 : }
1306 0 : result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1307 : }
1308 0 : return result;
1309 : }
1310 :
1311 : /* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
1312 0 : std::unique_ptr<ASTExpression> Parser::logicalAndExpression() {
1313 0 : std::unique_ptr<ASTExpression> result = this->bitwiseOrExpression();
1314 0 : if (!result) {
1315 0 : return nullptr;
1316 : }
1317 0 : while (this->peek().fKind == Token::LOGICALAND) {
1318 0 : Token t = this->nextToken();
1319 0 : std::unique_ptr<ASTExpression> right = this->bitwiseOrExpression();
1320 0 : if (!right) {
1321 0 : return nullptr;
1322 : }
1323 0 : result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1324 : }
1325 0 : return result;
1326 : }
1327 :
1328 : /* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
1329 0 : std::unique_ptr<ASTExpression> Parser::bitwiseOrExpression() {
1330 0 : std::unique_ptr<ASTExpression> result = this->bitwiseXorExpression();
1331 0 : if (!result) {
1332 0 : return nullptr;
1333 : }
1334 0 : while (this->peek().fKind == Token::BITWISEOR) {
1335 0 : Token t = this->nextToken();
1336 0 : std::unique_ptr<ASTExpression> right = this->bitwiseXorExpression();
1337 0 : if (!right) {
1338 0 : return nullptr;
1339 : }
1340 0 : result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1341 : }
1342 0 : return result;
1343 : }
1344 :
1345 : /* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
1346 0 : std::unique_ptr<ASTExpression> Parser::bitwiseXorExpression() {
1347 0 : std::unique_ptr<ASTExpression> result = this->bitwiseAndExpression();
1348 0 : if (!result) {
1349 0 : return nullptr;
1350 : }
1351 0 : while (this->peek().fKind == Token::BITWISEXOR) {
1352 0 : Token t = this->nextToken();
1353 0 : std::unique_ptr<ASTExpression> right = this->bitwiseAndExpression();
1354 0 : if (!right) {
1355 0 : return nullptr;
1356 : }
1357 0 : result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1358 : }
1359 0 : return result;
1360 : }
1361 :
1362 : /* equalityExpression (BITWISEAND equalityExpression)* */
1363 0 : std::unique_ptr<ASTExpression> Parser::bitwiseAndExpression() {
1364 0 : std::unique_ptr<ASTExpression> result = this->equalityExpression();
1365 0 : if (!result) {
1366 0 : return nullptr;
1367 : }
1368 0 : while (this->peek().fKind == Token::BITWISEAND) {
1369 0 : Token t = this->nextToken();
1370 0 : std::unique_ptr<ASTExpression> right = this->equalityExpression();
1371 0 : if (!right) {
1372 0 : return nullptr;
1373 : }
1374 0 : result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1375 : }
1376 0 : return result;
1377 : }
1378 :
1379 : /* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
1380 0 : std::unique_ptr<ASTExpression> Parser::equalityExpression() {
1381 0 : std::unique_ptr<ASTExpression> result = this->relationalExpression();
1382 0 : if (!result) {
1383 0 : return nullptr;
1384 : }
1385 : for (;;) {
1386 0 : switch (this->peek().fKind) {
1387 : case Token::EQEQ: // fall through
1388 : case Token::NEQ: {
1389 0 : Token t = this->nextToken();
1390 0 : std::unique_ptr<ASTExpression> right = this->relationalExpression();
1391 0 : if (!right) {
1392 0 : return nullptr;
1393 : }
1394 0 : result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1395 0 : break;
1396 : }
1397 : default:
1398 0 : return result;
1399 : }
1400 0 : }
1401 : }
1402 :
1403 : /* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
1404 0 : std::unique_ptr<ASTExpression> Parser::relationalExpression() {
1405 0 : std::unique_ptr<ASTExpression> result = this->shiftExpression();
1406 0 : if (!result) {
1407 0 : return nullptr;
1408 : }
1409 : for (;;) {
1410 0 : switch (this->peek().fKind) {
1411 : case Token::LT: // fall through
1412 : case Token::GT: // fall through
1413 : case Token::LTEQ: // fall through
1414 : case Token::GTEQ: {
1415 0 : Token t = this->nextToken();
1416 0 : std::unique_ptr<ASTExpression> right = this->shiftExpression();
1417 0 : if (!right) {
1418 0 : return nullptr;
1419 : }
1420 0 : result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1421 0 : break;
1422 : }
1423 : default:
1424 0 : return result;
1425 : }
1426 0 : }
1427 : }
1428 :
1429 : /* additiveExpression ((SHL | SHR) additiveExpression)* */
1430 0 : std::unique_ptr<ASTExpression> Parser::shiftExpression() {
1431 0 : std::unique_ptr<ASTExpression> result = this->additiveExpression();
1432 0 : if (!result) {
1433 0 : return nullptr;
1434 : }
1435 : for (;;) {
1436 0 : switch (this->peek().fKind) {
1437 : case Token::SHL: // fall through
1438 : case Token::SHR: {
1439 0 : Token t = this->nextToken();
1440 0 : std::unique_ptr<ASTExpression> right = this->additiveExpression();
1441 0 : if (!right) {
1442 0 : return nullptr;
1443 : }
1444 0 : result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1445 0 : break;
1446 : }
1447 : default:
1448 0 : return result;
1449 : }
1450 0 : }
1451 : }
1452 :
1453 : /* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
1454 0 : std::unique_ptr<ASTExpression> Parser::additiveExpression() {
1455 0 : std::unique_ptr<ASTExpression> result = this->multiplicativeExpression();
1456 0 : if (!result) {
1457 0 : return nullptr;
1458 : }
1459 : for (;;) {
1460 0 : switch (this->peek().fKind) {
1461 : case Token::PLUS: // fall through
1462 : case Token::MINUS: {
1463 0 : Token t = this->nextToken();
1464 0 : std::unique_ptr<ASTExpression> right = this->multiplicativeExpression();
1465 0 : if (!right) {
1466 0 : return nullptr;
1467 : }
1468 0 : result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1469 0 : break;
1470 : }
1471 : default:
1472 0 : return result;
1473 : }
1474 0 : }
1475 : }
1476 :
1477 : /* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
1478 0 : std::unique_ptr<ASTExpression> Parser::multiplicativeExpression() {
1479 0 : std::unique_ptr<ASTExpression> result = this->unaryExpression();
1480 0 : if (!result) {
1481 0 : return nullptr;
1482 : }
1483 : for (;;) {
1484 0 : switch (this->peek().fKind) {
1485 : case Token::STAR: // fall through
1486 : case Token::SLASH: // fall through
1487 : case Token::PERCENT: {
1488 0 : Token t = this->nextToken();
1489 0 : std::unique_ptr<ASTExpression> right = this->unaryExpression();
1490 0 : if (!right) {
1491 0 : return nullptr;
1492 : }
1493 0 : result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right)));
1494 0 : break;
1495 : }
1496 : default:
1497 0 : return result;
1498 : }
1499 0 : }
1500 : }
1501 :
1502 : /* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
1503 0 : std::unique_ptr<ASTExpression> Parser::unaryExpression() {
1504 0 : switch (this->peek().fKind) {
1505 : case Token::PLUS: // fall through
1506 : case Token::MINUS: // fall through
1507 : case Token::LOGICALNOT: // fall through
1508 : case Token::BITWISENOT: // fall through
1509 : case Token::PLUSPLUS: // fall through
1510 : case Token::MINUSMINUS: {
1511 0 : Token t = this->nextToken();
1512 0 : std::unique_ptr<ASTExpression> expr = this->unaryExpression();
1513 0 : if (!expr) {
1514 0 : return nullptr;
1515 : }
1516 0 : return std::unique_ptr<ASTExpression>(new ASTPrefixExpression(t, std::move(expr)));
1517 : }
1518 : default:
1519 0 : return this->postfixExpression();
1520 : }
1521 : }
1522 :
1523 : /* term suffix* */
1524 0 : std::unique_ptr<ASTExpression> Parser::postfixExpression() {
1525 0 : std::unique_ptr<ASTExpression> result = this->term();
1526 0 : if (!result) {
1527 0 : return nullptr;
1528 : }
1529 : for (;;) {
1530 0 : switch (this->peek().fKind) {
1531 : case Token::LBRACKET: // fall through
1532 : case Token::DOT: // fall through
1533 : case Token::LPAREN: // fall through
1534 : case Token::PLUSPLUS: // fall through
1535 : case Token::MINUSMINUS: {
1536 0 : std::unique_ptr<ASTSuffix> s = this->suffix();
1537 0 : if (!s) {
1538 0 : return nullptr;
1539 : }
1540 0 : result.reset(new ASTSuffixExpression(std::move(result), std::move(s)));
1541 0 : break;
1542 : }
1543 : default:
1544 0 : return result;
1545 : }
1546 0 : }
1547 : }
1548 :
1549 : /* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
1550 : PLUSPLUS | MINUSMINUS */
1551 0 : std::unique_ptr<ASTSuffix> Parser::suffix() {
1552 0 : Token next = this->nextToken();
1553 0 : switch (next.fKind) {
1554 : case Token::LBRACKET: {
1555 0 : if (this->peek().fKind == Token::RBRACKET) {
1556 0 : this->nextToken();
1557 0 : return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fPosition));
1558 : }
1559 0 : std::unique_ptr<ASTExpression> e = this->expression();
1560 0 : if (!e) {
1561 0 : return nullptr;
1562 : }
1563 0 : this->expect(Token::RBRACKET, "']' to complete array access expression");
1564 0 : return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e)));
1565 : }
1566 : case Token::DOT: {
1567 0 : Position pos = this->peek().fPosition;
1568 0 : String text;
1569 0 : if (this->identifier(&text)) {
1570 0 : return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(pos, std::move(text)));
1571 : }
1572 0 : return nullptr;
1573 : }
1574 : case Token::LPAREN: {
1575 0 : std::vector<std::unique_ptr<ASTExpression>> parameters;
1576 0 : if (this->peek().fKind != Token::RPAREN) {
1577 : for (;;) {
1578 0 : std::unique_ptr<ASTExpression> expr = this->expression();
1579 0 : if (!expr) {
1580 0 : return nullptr;
1581 : }
1582 0 : parameters.push_back(std::move(expr));
1583 0 : if (this->peek().fKind != Token::COMMA) {
1584 0 : break;
1585 : }
1586 0 : this->nextToken();
1587 0 : }
1588 : }
1589 0 : this->expect(Token::RPAREN, "')' to complete function parameters");
1590 0 : return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition,
1591 0 : std::move(parameters)));
1592 : }
1593 : case Token::PLUSPLUS:
1594 0 : return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
1595 0 : ASTSuffix::kPostIncrement_Kind));
1596 : case Token::MINUSMINUS:
1597 0 : return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
1598 0 : ASTSuffix::kPostDecrement_Kind));
1599 : default: {
1600 0 : this->error(next.fPosition, "expected expression suffix, but found '" + next.fText +
1601 0 : "'\n");
1602 0 : return nullptr;
1603 : }
1604 : }
1605 : }
1606 :
1607 : /* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */
1608 0 : std::unique_ptr<ASTExpression> Parser::term() {
1609 0 : std::unique_ptr<ASTExpression> result;
1610 0 : Token t = this->peek();
1611 0 : switch (t.fKind) {
1612 : case Token::IDENTIFIER: {
1613 0 : String text;
1614 0 : if (this->identifier(&text)) {
1615 0 : result.reset(new ASTIdentifier(t.fPosition, std::move(text)));
1616 : }
1617 0 : break;
1618 : }
1619 : case Token::INT_LITERAL: {
1620 : int64_t i;
1621 0 : if (this->intLiteral(&i)) {
1622 0 : result.reset(new ASTIntLiteral(t.fPosition, i));
1623 : }
1624 0 : break;
1625 : }
1626 : case Token::FLOAT_LITERAL: {
1627 : double f;
1628 0 : if (this->floatLiteral(&f)) {
1629 0 : result.reset(new ASTFloatLiteral(t.fPosition, f));
1630 : }
1631 0 : break;
1632 : }
1633 : case Token::TRUE_LITERAL: // fall through
1634 : case Token::FALSE_LITERAL: {
1635 : bool b;
1636 0 : if (this->boolLiteral(&b)) {
1637 0 : result.reset(new ASTBoolLiteral(t.fPosition, b));
1638 : }
1639 0 : break;
1640 : }
1641 : case Token::LPAREN: {
1642 0 : this->nextToken();
1643 0 : result = this->expression();
1644 0 : if (result) {
1645 0 : this->expect(Token::RPAREN, "')' to complete expression");
1646 : }
1647 0 : break;
1648 : }
1649 : default:
1650 0 : this->nextToken();
1651 0 : this->error(t.fPosition, "expected expression, but found '" + t.fText + "'\n");
1652 0 : result = nullptr;
1653 : }
1654 0 : return result;
1655 : }
1656 :
1657 : /* INT_LITERAL */
1658 0 : bool Parser::intLiteral(int64_t* dest) {
1659 0 : Token t;
1660 0 : if (this->expect(Token::INT_LITERAL, "integer literal", &t)) {
1661 0 : *dest = SkSL::stol(t.fText);
1662 0 : return true;
1663 : }
1664 0 : return false;
1665 : }
1666 :
1667 : /* FLOAT_LITERAL */
1668 0 : bool Parser::floatLiteral(double* dest) {
1669 0 : Token t;
1670 0 : if (this->expect(Token::FLOAT_LITERAL, "float literal", &t)) {
1671 0 : *dest = SkSL::stod(t.fText);
1672 0 : return true;
1673 : }
1674 0 : return false;
1675 : }
1676 :
1677 : /* TRUE_LITERAL | FALSE_LITERAL */
1678 0 : bool Parser::boolLiteral(bool* dest) {
1679 0 : Token t = this->nextToken();
1680 0 : switch (t.fKind) {
1681 : case Token::TRUE_LITERAL:
1682 0 : *dest = true;
1683 0 : return true;
1684 : case Token::FALSE_LITERAL:
1685 0 : *dest = false;
1686 0 : return true;
1687 : default:
1688 0 : this->error(t.fPosition, "expected 'true' or 'false', but found '" + t.fText + "'\n");
1689 0 : return false;
1690 : }
1691 : }
1692 :
1693 : /* IDENTIFIER */
1694 0 : bool Parser::identifier(String* dest) {
1695 0 : Token t;
1696 0 : if (this->expect(Token::IDENTIFIER, "identifier", &t)) {
1697 0 : *dest = t.fText;
1698 0 : return true;
1699 : }
1700 0 : return false;
1701 : }
1702 :
1703 : } // namespace
|