| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "stdio.h" | 8 #include "stdio.h" |
| 9 #include "SkSLParser.h" | 9 #include "SkSLParser.h" |
| 10 #include "SkSLToken.h" | 10 #include "SkSLToken.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 #include "ast/SkSLASTExtension.h" | 49 #include "ast/SkSLASTExtension.h" |
| 50 #include "ast/SkSLASTFieldSuffix.h" | 50 #include "ast/SkSLASTFieldSuffix.h" |
| 51 #include "ast/SkSLASTFloatLiteral.h" | 51 #include "ast/SkSLASTFloatLiteral.h" |
| 52 #include "ast/SkSLASTForStatement.h" | 52 #include "ast/SkSLASTForStatement.h" |
| 53 #include "ast/SkSLASTFunction.h" | 53 #include "ast/SkSLASTFunction.h" |
| 54 #include "ast/SkSLASTIdentifier.h" | 54 #include "ast/SkSLASTIdentifier.h" |
| 55 #include "ast/SkSLASTIfStatement.h" | 55 #include "ast/SkSLASTIfStatement.h" |
| 56 #include "ast/SkSLASTIndexSuffix.h" | 56 #include "ast/SkSLASTIndexSuffix.h" |
| 57 #include "ast/SkSLASTInterfaceBlock.h" | 57 #include "ast/SkSLASTInterfaceBlock.h" |
| 58 #include "ast/SkSLASTIntLiteral.h" | 58 #include "ast/SkSLASTIntLiteral.h" |
| 59 #include "ast/SkSLASTModifiersDeclaration.h" |
| 59 #include "ast/SkSLASTParameter.h" | 60 #include "ast/SkSLASTParameter.h" |
| 61 #include "ast/SkSLASTPrecision.h" |
| 60 #include "ast/SkSLASTPrefixExpression.h" | 62 #include "ast/SkSLASTPrefixExpression.h" |
| 61 #include "ast/SkSLASTReturnStatement.h" | 63 #include "ast/SkSLASTReturnStatement.h" |
| 62 #include "ast/SkSLASTStatement.h" | 64 #include "ast/SkSLASTStatement.h" |
| 63 #include "ast/SkSLASTSuffixExpression.h" | 65 #include "ast/SkSLASTSuffixExpression.h" |
| 64 #include "ast/SkSLASTTernaryExpression.h" | 66 #include "ast/SkSLASTTernaryExpression.h" |
| 65 #include "ast/SkSLASTType.h" | 67 #include "ast/SkSLASTType.h" |
| 66 #include "ast/SkSLASTVarDeclaration.h" | 68 #include "ast/SkSLASTVarDeclaration.h" |
| 67 #include "ast/SkSLASTVarDeclarationStatement.h" | 69 #include "ast/SkSLASTVarDeclarationStatement.h" |
| 68 #include "ast/SkSLASTWhileStatement.h" | 70 #include "ast/SkSLASTWhileStatement.h" |
| 69 #include "ir/SkSLSymbolTable.h" | 71 #include "ir/SkSLSymbolTable.h" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 90 sksllex_destroy(fScanner); | 92 sksllex_destroy(fScanner); |
| 91 } | 93 } |
| 92 | 94 |
| 93 /* (precision | directive | declaration)* END_OF_FILE */ | 95 /* (precision | directive | declaration)* END_OF_FILE */ |
| 94 std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { | 96 std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { |
| 95 std::vector<std::unique_ptr<ASTDeclaration>> result; | 97 std::vector<std::unique_ptr<ASTDeclaration>> result; |
| 96 for (;;) { | 98 for (;;) { |
| 97 switch (this->peek().fKind) { | 99 switch (this->peek().fKind) { |
| 98 case Token::END_OF_FILE: | 100 case Token::END_OF_FILE: |
| 99 return result; | 101 return result; |
| 100 case Token::PRECISION: | 102 case Token::PRECISION: { |
| 101 this->precision(); | 103 std::unique_ptr<ASTDeclaration> precision = this->precision(); |
| 104 if (precision) { |
| 105 result.push_back(std::move(precision)); |
| 106 } |
| 102 break; | 107 break; |
| 108 } |
| 103 case Token::DIRECTIVE: { | 109 case Token::DIRECTIVE: { |
| 104 std::unique_ptr<ASTDeclaration> decl = this->directive(); | 110 std::unique_ptr<ASTDeclaration> decl = this->directive(); |
| 105 if (decl) { | 111 if (decl) { |
| 106 result.push_back(std::move(decl)); | 112 result.push_back(std::move(decl)); |
| 107 } | 113 } |
| 108 break; | 114 break; |
| 109 } | 115 } |
| 110 default: { | 116 default: { |
| 111 std::unique_ptr<ASTDeclaration> decl = this->declaration(); | 117 std::unique_ptr<ASTDeclaration> decl = this->declaration(); |
| 112 if (!decl) { | 118 if (!decl) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 | 162 |
| 157 void Parser::error(Position p, std::string msg) { | 163 void Parser::error(Position p, std::string msg) { |
| 158 fErrors.error(p, msg); | 164 fErrors.error(p, msg); |
| 159 } | 165 } |
| 160 | 166 |
| 161 bool Parser::isType(std::string name) { | 167 bool Parser::isType(std::string name) { |
| 162 return nullptr != fTypes[name]; | 168 return nullptr != fTypes[name]; |
| 163 } | 169 } |
| 164 | 170 |
| 165 /* PRECISION (LOWP | MEDIUMP | HIGHP) type SEMICOLON */ | 171 /* PRECISION (LOWP | MEDIUMP | HIGHP) type SEMICOLON */ |
| 166 void Parser::precision() { | 172 std::unique_ptr<ASTDeclaration> Parser::precision() { |
| 167 if (!this->expect(Token::PRECISION, "'precision'")) { | 173 if (!this->expect(Token::PRECISION, "'precision'")) { |
| 168 return; | 174 return nullptr; |
| 169 } | 175 } |
| 176 Modifiers::Flag result; |
| 170 Token p = this->nextToken(); | 177 Token p = this->nextToken(); |
| 171 switch (p.fKind) { | 178 switch (p.fKind) { |
| 172 case Token::LOWP: // fall through | 179 case Token::LOWP: |
| 173 case Token::MEDIUMP: // fall through | 180 result = Modifiers::kLowp_Flag; |
| 181 break; |
| 182 case Token::MEDIUMP: |
| 183 result = Modifiers::kMediump_Flag; |
| 184 break; |
| 174 case Token::HIGHP: | 185 case Token::HIGHP: |
| 175 // ignored for now | 186 result = Modifiers::kHighp_Flag; |
| 176 break; | 187 break; |
| 177 default: | 188 default: |
| 178 this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', bu
t found '" + | 189 this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', bu
t found '" + |
| 179 p.fText + "'"); | 190 p.fText + "'"); |
| 180 return; | 191 return nullptr; |
| 181 } | 192 } |
| 193 // FIXME handle the type |
| 182 if (!this->type()) { | 194 if (!this->type()) { |
| 183 return; | 195 return nullptr; |
| 184 } | 196 } |
| 185 this->expect(Token::SEMICOLON, "';'"); | 197 this->expect(Token::SEMICOLON, "';'"); |
| 198 return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result)
); |
| 186 } | 199 } |
| 187 | 200 |
| 188 /* DIRECTIVE(#version) INT_LITERAL | DIRECTIVE(#extension) IDENTIFIER COLON IDEN
TIFIER */ | 201 /* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? | |
| 202 DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */ |
| 189 std::unique_ptr<ASTDeclaration> Parser::directive() { | 203 std::unique_ptr<ASTDeclaration> Parser::directive() { |
| 190 Token start; | 204 Token start; |
| 191 if (!this->expect(Token::DIRECTIVE, "a directive", &start)) { | 205 if (!this->expect(Token::DIRECTIVE, "a directive", &start)) { |
| 192 return nullptr; | 206 return nullptr; |
| 193 } | 207 } |
| 194 if (start.fText == "#version") { | 208 if (start.fText == "#version") { |
| 195 this->expect(Token::INT_LITERAL, "a version number"); | 209 this->expect(Token::INT_LITERAL, "a version number"); |
| 196 // ignored for now | 210 Token next = this->peek(); |
| 211 if (next.fText == "es" || next.fText == "compatibility") { |
| 212 this->nextToken(); |
| 213 } |
| 214 // version is ignored for now; it will eventually become an error when w
e stop pretending |
| 215 // to be GLSL |
| 197 return nullptr; | 216 return nullptr; |
| 198 } else if (start.fText == "#extension") { | 217 } else if (start.fText == "#extension") { |
| 199 Token name; | 218 Token name; |
| 200 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { | 219 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { |
| 201 return nullptr; | 220 return nullptr; |
| 202 } | 221 } |
| 203 if (!this->expect(Token::COLON, "':'")) { | 222 if (!this->expect(Token::COLON, "':'")) { |
| 204 return nullptr; | 223 return nullptr; |
| 205 } | 224 } |
| 206 // FIXME: need to start paying attention to this token | 225 // FIXME: need to start paying attention to this token |
| (...skipping 13 matching lines...) Expand all Loading... |
| 220 std::unique_ptr<ASTDeclaration> Parser::declaration() { | 239 std::unique_ptr<ASTDeclaration> Parser::declaration() { |
| 221 ASTModifiers modifiers = this->modifiers(); | 240 ASTModifiers modifiers = this->modifiers(); |
| 222 Token lookahead = this->peek(); | 241 Token lookahead = this->peek(); |
| 223 if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText))
{ | 242 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 int
erface block | 243 // we have an identifier that's not a type, could be the start of an int
erface block |
| 225 return this->interfaceBlock(modifiers); | 244 return this->interfaceBlock(modifiers); |
| 226 } | 245 } |
| 227 if (lookahead.fKind == Token::STRUCT) { | 246 if (lookahead.fKind == Token::STRUCT) { |
| 228 return this->structVarDeclaration(modifiers); | 247 return this->structVarDeclaration(modifiers); |
| 229 } | 248 } |
| 249 if (lookahead.fKind == Token::SEMICOLON) { |
| 250 this->nextToken(); |
| 251 return std::unique_ptr<ASTDeclaration>(new ASTModifiersDeclaration(modif
iers)); |
| 252 } |
| 230 std::unique_ptr<ASTType> type(this->type()); | 253 std::unique_ptr<ASTType> type(this->type()); |
| 231 if (!type) { | 254 if (!type) { |
| 232 return nullptr; | 255 return nullptr; |
| 233 } | 256 } |
| 234 if (type->fKind == ASTType::kStruct_Kind && peek().fKind == Token::SEMICOLON
) { | 257 if (type->fKind == ASTType::kStruct_Kind && peek().fKind == Token::SEMICOLON
) { |
| 235 this->nextToken(); | 258 this->nextToken(); |
| 236 return nullptr; | 259 return nullptr; |
| 237 } | 260 } |
| 238 Token name; | 261 Token name; |
| 239 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { | 262 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 | 493 |
| 471 /* LAYOUT LPAREN IDENTIFIER EQ INT_LITERAL (COMMA IDENTIFIER EQ INT_LITERAL)* | 494 /* LAYOUT LPAREN IDENTIFIER EQ INT_LITERAL (COMMA IDENTIFIER EQ INT_LITERAL)* |
| 472 RPAREN */ | 495 RPAREN */ |
| 473 ASTLayout Parser::layout() { | 496 ASTLayout Parser::layout() { |
| 474 int location = -1; | 497 int location = -1; |
| 475 int binding = -1; | 498 int binding = -1; |
| 476 int index = -1; | 499 int index = -1; |
| 477 int set = -1; | 500 int set = -1; |
| 478 int builtin = -1; | 501 int builtin = -1; |
| 479 bool originUpperLeft = false; | 502 bool originUpperLeft = false; |
| 503 bool overrideCoverage = false; |
| 504 bool blendSupportAllEquations = false; |
| 480 if (this->peek().fKind == Token::LAYOUT) { | 505 if (this->peek().fKind == Token::LAYOUT) { |
| 481 this->nextToken(); | 506 this->nextToken(); |
| 482 if (!this->expect(Token::LPAREN, "'('")) { | 507 if (!this->expect(Token::LPAREN, "'('")) { |
| 483 return ASTLayout(location, binding, index, set, builtin, originUpper
Left); | 508 return ASTLayout(location, binding, index, set, builtin, originUpper
Left, |
| 509 overrideCoverage, blendSupportAllEquations); |
| 484 } | 510 } |
| 485 for (;;) { | 511 for (;;) { |
| 486 Token t = this->nextToken(); | 512 Token t = this->nextToken(); |
| 487 if (t.fText == "location") { | 513 if (t.fText == "location") { |
| 488 location = this->layoutInt(); | 514 location = this->layoutInt(); |
| 489 } else if (t.fText == "binding") { | 515 } else if (t.fText == "binding") { |
| 490 binding = this->layoutInt(); | 516 binding = this->layoutInt(); |
| 491 } else if (t.fText == "index") { | 517 } else if (t.fText == "index") { |
| 492 index = this->layoutInt(); | 518 index = this->layoutInt(); |
| 493 } else if (t.fText == "set") { | 519 } else if (t.fText == "set") { |
| 494 set = this->layoutInt(); | 520 set = this->layoutInt(); |
| 495 } else if (t.fText == "builtin") { | 521 } else if (t.fText == "builtin") { |
| 496 builtin = this->layoutInt(); | 522 builtin = this->layoutInt(); |
| 497 } else if (t.fText == "origin_upper_left") { | 523 } else if (t.fText == "origin_upper_left") { |
| 498 originUpperLeft = true; | 524 originUpperLeft = true; |
| 525 } else if (t.fText == "override_coverage") { |
| 526 overrideCoverage = true; |
| 527 } else if (t.fText == "blend_support_all_equations") { |
| 528 blendSupportAllEquations = true; |
| 499 } else { | 529 } else { |
| 500 this->error(t.fPosition, ("'" + t.fText + | 530 this->error(t.fPosition, ("'" + t.fText + |
| 501 "' is not a valid layout qualifier").c
_str()); | 531 "' is not a valid layout qualifier").c
_str()); |
| 502 } | 532 } |
| 503 if (this->peek().fKind == Token::RPAREN) { | 533 if (this->peek().fKind == Token::RPAREN) { |
| 504 this->nextToken(); | 534 this->nextToken(); |
| 505 break; | 535 break; |
| 506 } | 536 } |
| 507 if (!this->expect(Token::COMMA, "','")) { | 537 if (!this->expect(Token::COMMA, "','")) { |
| 508 break; | 538 break; |
| 509 } | 539 } |
| 510 } | 540 } |
| 511 } | 541 } |
| 512 return ASTLayout(location, binding, index, set, builtin, originUpperLeft); | 542 return ASTLayout(location, binding, index, set, builtin, originUpperLeft, ov
errideCoverage, |
| 543 blendSupportAllEquations); |
| 513 } | 544 } |
| 514 | 545 |
| 515 /* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT |
NOPERSPECTIVE)* */ | 546 /* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT |
NOPERSPECTIVE)* */ |
| 516 ASTModifiers Parser::modifiers() { | 547 ASTModifiers Parser::modifiers() { |
| 517 ASTLayout layout = this->layout(); | 548 ASTLayout layout = this->layout(); |
| 518 int flags = 0; | 549 int flags = 0; |
| 519 for (;;) { | 550 for (;;) { |
| 520 // TODO: handle duplicate / incompatible flags | 551 // TODO: handle duplicate / incompatible flags |
| 521 switch (peek().fKind) { | 552 switch (peek().fKind) { |
| 522 case Token::UNIFORM: | 553 case Token::UNIFORM: |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1204 } | 1235 } |
| 1205 default: | 1236 default: |
| 1206 return result; | 1237 return result; |
| 1207 } | 1238 } |
| 1208 } | 1239 } |
| 1209 } | 1240 } |
| 1210 | 1241 |
| 1211 /* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpress
ion */ | 1242 /* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpress
ion */ |
| 1212 std::unique_ptr<ASTExpression> Parser::unaryExpression() { | 1243 std::unique_ptr<ASTExpression> Parser::unaryExpression() { |
| 1213 switch (this->peek().fKind) { | 1244 switch (this->peek().fKind) { |
| 1214 case Token::PLUS: // fall through | 1245 case Token::PLUS: // fall through |
| 1215 case Token::MINUS: // fall through | 1246 case Token::MINUS: // fall through |
| 1216 case Token::NOT: // fall through | 1247 case Token::LOGICALNOT: // fall through |
| 1217 case Token::PLUSPLUS: // fall through | 1248 case Token::BITWISENOT: // fall through |
| 1249 case Token::PLUSPLUS: // fall through |
| 1218 case Token::MINUSMINUS: { | 1250 case Token::MINUSMINUS: { |
| 1219 Token t = this->nextToken(); | 1251 Token t = this->nextToken(); |
| 1220 std::unique_ptr<ASTExpression> expr = this->unaryExpression(); | 1252 std::unique_ptr<ASTExpression> expr = this->unaryExpression(); |
| 1221 if (!expr) { | 1253 if (!expr) { |
| 1222 return nullptr; | 1254 return nullptr; |
| 1223 } | 1255 } |
| 1224 return std::unique_ptr<ASTExpression>(new ASTPrefixExpression(t, std
::move(expr))); | 1256 return std::unique_ptr<ASTExpression>(new ASTPrefixExpression(t, std
::move(expr))); |
| 1225 } | 1257 } |
| 1226 default: | 1258 default: |
| 1227 return this->postfixExpression(); | 1259 return this->postfixExpression(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1247 } | 1279 } |
| 1248 result.reset(new ASTSuffixExpression(std::move(result), std::mov
e(s))); | 1280 result.reset(new ASTSuffixExpression(std::move(result), std::mov
e(s))); |
| 1249 break; | 1281 break; |
| 1250 } | 1282 } |
| 1251 default: | 1283 default: |
| 1252 return result; | 1284 return result; |
| 1253 } | 1285 } |
| 1254 } | 1286 } |
| 1255 } | 1287 } |
| 1256 | 1288 |
| 1257 /* LBRACKET expression RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN | | 1289 /* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN | |
| 1258 PLUSPLUS | MINUSMINUS */ | 1290 PLUSPLUS | MINUSMINUS */ |
| 1259 std::unique_ptr<ASTSuffix> Parser::suffix() { | 1291 std::unique_ptr<ASTSuffix> Parser::suffix() { |
| 1260 Token next = this->nextToken(); | 1292 Token next = this->nextToken(); |
| 1261 switch (next.fKind) { | 1293 switch (next.fKind) { |
| 1262 case Token::LBRACKET: { | 1294 case Token::LBRACKET: { |
| 1295 if (this->peek().fKind == Token::RBRACKET) { |
| 1296 this->nextToken(); |
| 1297 return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fPosit
ion)); |
| 1298 } |
| 1263 std::unique_ptr<ASTExpression> e = this->expression(); | 1299 std::unique_ptr<ASTExpression> e = this->expression(); |
| 1264 if (!e) { | 1300 if (!e) { |
| 1265 return nullptr; | 1301 return nullptr; |
| 1266 } | 1302 } |
| 1267 this->expect(Token::RBRACKET, "']' to complete array access expressi
on"); | 1303 this->expect(Token::RBRACKET, "']' to complete array access expressi
on"); |
| 1268 return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e))); | 1304 return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e))); |
| 1269 } | 1305 } |
| 1270 case Token::DOT: { | 1306 case Token::DOT: { |
| 1271 Position pos = this->peek().fPosition; | 1307 Position pos = this->peek().fPosition; |
| 1272 std::string text; | 1308 std::string text; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1398 bool Parser::identifier(std::string* dest) { | 1434 bool Parser::identifier(std::string* dest) { |
| 1399 Token t; | 1435 Token t; |
| 1400 if (this->expect(Token::IDENTIFIER, "identifier", &t)) { | 1436 if (this->expect(Token::IDENTIFIER, "identifier", &t)) { |
| 1401 *dest = t.fText; | 1437 *dest = t.fText; |
| 1402 return true; | 1438 return true; |
| 1403 } | 1439 } |
| 1404 return false; | 1440 return false; |
| 1405 } | 1441 } |
| 1406 | 1442 |
| 1407 } // namespace | 1443 } // namespace |
| OLD | NEW |