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