Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: src/parser.cc

Issue 887843002: Implement new syntax for ImportDeclarations (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add more negative tests Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parser.h ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
(...skipping 1281 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 Interface* interface = scope->interface(); 1292 Interface* interface = scope->interface();
1293 Module* result = factory()->NewModuleLiteral(body, interface, pos); 1293 Module* result = factory()->NewModuleLiteral(body, interface, pos);
1294 interface->Freeze(ok); 1294 interface->Freeze(ok);
1295 DCHECK(*ok); 1295 DCHECK(*ok);
1296 interface->Unify(scope->interface(), zone(), ok); 1296 interface->Unify(scope->interface(), zone(), ok);
1297 DCHECK(*ok); 1297 DCHECK(*ok);
1298 return result; 1298 return result;
1299 } 1299 }
1300 1300
1301 1301
1302 void* Parser::ParseModuleDeclarationClause(ZoneList<const AstRawString*>* names, 1302 void* Parser::ParseExportClause(ZoneList<const AstRawString*>* names,
1303 bool* ok) { 1303 Scanner::Location* reserved_loc, bool* ok) {
1304 // Handles both imports and exports: 1304 // ExportClause :
1305 // '{' '}'
1306 // '{' ExportsList '}'
1307 // '{' ExportsList ',' '}'
1305 // 1308 //
1306 // ImportOrExportClause : 1309 // ExportsList :
1307 // '{' '}' 1310 // ExportSpecifier
1308 // '{' ImportOrExportsList '}' 1311 // ExportsList ',' ExportSpecifier
1309 // '{' ImportOrExportsList ',' '}'
1310 // 1312 //
1311 // ImportOrExportsList : 1313 // ExportSpecifier :
1312 // ImportOrExportSpecifier
1313 // ImportOrExportsList ',' ImportOrExportSpecifier
1314 //
1315 // ImportOrExportSpecifier :
1316 // IdentifierName 1314 // IdentifierName
1317 // IdentifierName 'as' IdentifierName 1315 // IdentifierName 'as' IdentifierName
1318 1316
1319 Expect(Token::LBRACE, CHECK_OK); 1317 Expect(Token::LBRACE, CHECK_OK);
1320 1318
1321 while (peek() != Token::RBRACE) { 1319 Token::Value name_tok;
1320 while ((name_tok = peek()) != Token::RBRACE) {
1321 // Keep track of the first reserved word encountered in case our
1322 // caller needs to report an error.
1323 if (!reserved_loc->IsValid() &&
1324 !Token::IsIdentifier(name_tok, STRICT, false)) {
1325 *reserved_loc = scanner()->location();
1326 }
1322 const AstRawString* name = ParseIdentifierName(CHECK_OK); 1327 const AstRawString* name = ParseIdentifierName(CHECK_OK);
1323 names->Add(name, zone()); 1328 names->Add(name, zone());
1324 const AstRawString* export_name = NULL; 1329 const AstRawString* export_name = NULL;
1325 if (CheckContextualKeyword(CStrVector("as"))) { 1330 if (CheckContextualKeyword(CStrVector("as"))) {
1326 export_name = ParseIdentifierName(CHECK_OK); 1331 export_name = ParseIdentifierName(CHECK_OK);
1327 } 1332 }
1328 // TODO(ES6): Return the export_name as well as the name. 1333 // TODO(ES6): Return the export_name as well as the name.
1329 USE(export_name); 1334 USE(export_name);
1330 if (peek() == Token::RBRACE) break; 1335 if (peek() == Token::RBRACE) break;
1331 Expect(Token::COMMA, CHECK_OK); 1336 Expect(Token::COMMA, CHECK_OK);
1332 } 1337 }
1333 1338
1334 Expect(Token::RBRACE, CHECK_OK); 1339 Expect(Token::RBRACE, CHECK_OK);
1335 1340
1336 return 0; 1341 return 0;
1337 } 1342 }
1338 1343
1339 1344
1345 void* Parser::ParseNamedImports(ZoneList<const AstRawString*>* names,
1346 bool* ok) {
1347 // NamedImports :
1348 // '{' '}'
1349 // '{' ImportsList '}'
1350 // '{' ImportsList ',' '}'
1351 //
1352 // ImportsList :
1353 // ImportSpecifier
1354 // ImportsList ',' ImportSpecifier
1355 //
1356 // ImportSpecifier :
1357 // BindingIdentifier
1358 // IdentifierName 'as' BindingIdentifier
1359
1360 Expect(Token::LBRACE, CHECK_OK);
1361
1362 Token::Value name_tok;
1363 while ((name_tok = peek()) != Token::RBRACE) {
1364 const AstRawString* name = ParseIdentifierName(CHECK_OK);
1365 const AstRawString* import_name = NULL;
1366 // In the presence of 'as', the left-side of the 'as' can
1367 // be any IdentifierName. But without 'as', it must be a valid
1368 // BindingIdentiifer.
1369 if (CheckContextualKeyword(CStrVector("as"))) {
1370 import_name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
1371 } else if (!Token::IsIdentifier(name_tok, STRICT, false)) {
1372 *ok = false;
1373 ReportMessageAt(scanner()->location(), "unexpected_reserved");
1374 return NULL;
1375 } else if (IsEvalOrArguments(name)) {
1376 *ok = false;
1377 ReportMessageAt(scanner()->location(), "strict_eval_arguments");
1378 return NULL;
1379 }
1380 // TODO(ES6): Return the import_name as well as the name.
1381 names->Add(name, zone());
1382 USE(import_name);
1383 if (peek() == Token::RBRACE) break;
1384 Expect(Token::COMMA, CHECK_OK);
1385 }
1386
1387 Expect(Token::RBRACE, CHECK_OK);
1388
1389 return NULL;
1390 }
1391
1392
1340 Statement* Parser::ParseImportDeclaration(bool* ok) { 1393 Statement* Parser::ParseImportDeclaration(bool* ok) {
1341 // ImportDeclaration: 1394 // ImportDeclaration :
1342 // 'import' IdentifierName (',' IdentifierName)* 'from' ModuleUrl ';' 1395 // 'import' ImportClause 'from' ModuleSpecifier ';'
1396 // 'import' ModuleSpecifier ';'
1343 // 1397 //
1344 // TODO(ES6): implement current syntax 1398 // ImportClause :
1399 // NameSpaceImport
1400 // NamedImports
1401 // ImportedDefaultBinding
1402 // ImportedDefaultBinding ',' NameSpaceImport
1403 // ImportedDefaultBinding ',' NamedImports
1404 //
1405 // NameSpaceImport :
1406 // '*' 'as' ImportedBinding
1345 1407
1346 int pos = peek_position(); 1408 int pos = peek_position();
1347 Expect(Token::IMPORT, CHECK_OK); 1409 Expect(Token::IMPORT, CHECK_OK);
1410
1411 Token::Value tok = peek();
1412
1413 // 'import' ModuleSpecifier ';'
1414 if (tok == Token::STRING) {
1415 ParseModuleSpecifier(CHECK_OK);
1416 ExpectSemicolon(CHECK_OK);
1417 return factory()->NewEmptyStatement(pos);
1418 }
1419
1420 // Parse ImportedDefaultBinding if present.
1421 const AstRawString* imported_default_binding = NULL;
1422 if (tok != Token::MUL && tok != Token::LBRACE) {
1423 imported_default_binding =
1424 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
1425 }
1426
1427 const AstRawString* module_instance_binding = NULL;
1348 ZoneList<const AstRawString*> names(1, zone()); 1428 ZoneList<const AstRawString*> names(1, zone());
1429 if (imported_default_binding == NULL || Check(Token::COMMA)) {
1430 switch (peek()) {
1431 case Token::MUL: {
1432 Consume(Token::MUL);
1433 ExpectContextualKeyword(CStrVector("as"), CHECK_OK);
1434 module_instance_binding =
1435 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
1436 break;
1437 }
1349 1438
1350 const AstRawString* name = ParseIdentifierName(CHECK_OK); 1439 case Token::LBRACE:
1351 names.Add(name, zone()); 1440 ParseNamedImports(&names, CHECK_OK);
1352 while (peek() == Token::COMMA) { 1441 break;
1353 Consume(Token::COMMA); 1442
1354 name = ParseIdentifierName(CHECK_OK); 1443 default:
1355 names.Add(name, zone()); 1444 *ok = false;
1445 ReportUnexpectedToken(scanner()->current_token());
1446 return NULL;
1447 }
1356 } 1448 }
1357 1449
1358 ExpectContextualKeyword(CStrVector("from"), CHECK_OK); 1450 ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1359 Module* module = ParseModuleSpecifier(CHECK_OK); 1451 Module* module = ParseModuleSpecifier(CHECK_OK);
1452 USE(module);
1453
1360 ExpectSemicolon(CHECK_OK); 1454 ExpectSemicolon(CHECK_OK);
1361 1455
1362 // TODO(ES6): Do something with ParseModuleSpecifier's return value. 1456 if (module_instance_binding != NULL) {
1363 USE(module); 1457 // TODO(ES6): Bind name to the Module Instance Object of module.
1458 }
1459
1460 if (imported_default_binding != NULL) {
1461 // TODO(ES6): Add an appropriate declaration.
1462 }
1364 1463
1365 for (int i = 0; i < names.length(); ++i) { 1464 for (int i = 0; i < names.length(); ++i) {
1366 // TODO(ES6): Add an appropriate declaration for each name 1465 // TODO(ES6): Add an appropriate declaration for each name
1367 } 1466 }
1368 1467
1369 return factory()->NewEmptyStatement(pos); 1468 return factory()->NewEmptyStatement(pos);
1370 } 1469 }
1371 1470
1372 1471
1373 Statement* Parser::ParseExportDefault(bool* ok) { 1472 Statement* Parser::ParseExportDefault(bool* ok) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1428 Module* module = ParseModuleSpecifier(CHECK_OK); 1527 Module* module = ParseModuleSpecifier(CHECK_OK);
1429 ExpectSemicolon(CHECK_OK); 1528 ExpectSemicolon(CHECK_OK);
1430 // TODO(ES6): Do something with the return value 1529 // TODO(ES6): Do something with the return value
1431 // of ParseModuleSpecifier. 1530 // of ParseModuleSpecifier.
1432 USE(module); 1531 USE(module);
1433 is_export_from = true; 1532 is_export_from = true;
1434 result = factory()->NewEmptyStatement(pos); 1533 result = factory()->NewEmptyStatement(pos);
1435 break; 1534 break;
1436 } 1535 }
1437 1536
1438 case Token::LBRACE: 1537 case Token::LBRACE: {
1439 ParseModuleDeclarationClause(&names, CHECK_OK); 1538 // There are two cases here:
1539 //
1540 // 'export' ExportClause ';'
1541 // and
1542 // 'export' ExportClause FromClause ';'
1543 //
1544 // In the first case, the exported identifiers in ExportClause must
1545 // not be reserved words, while in the latter they may be. We
1546 // pass in a location that gets filled with the first reserved word
1547 // encountered, and then throw a SyntaxError if we are in the
1548 // non-FromClause case.
1549 Scanner::Location reserved_loc = Scanner::Location::invalid();
1550 ParseExportClause(&names, &reserved_loc, CHECK_OK);
1440 if (CheckContextualKeyword(CStrVector("from"))) { 1551 if (CheckContextualKeyword(CStrVector("from"))) {
1441 Module* module = ParseModuleSpecifier(CHECK_OK); 1552 Module* module = ParseModuleSpecifier(CHECK_OK);
1442 // TODO(ES6): Do something with the return value 1553 // TODO(ES6): Do something with the return value
1443 // of ParseModuleSpecifier. 1554 // of ParseModuleSpecifier.
1444 USE(module); 1555 USE(module);
1445 is_export_from = true; 1556 is_export_from = true;
1557 } else if (reserved_loc.IsValid()) {
1558 // No FromClause, so reserved words are invalid in ExportClause.
1559 *ok = false;
1560 ReportMessageAt(reserved_loc, "unexpected_reserved");
1561 return NULL;
1446 } 1562 }
1447 ExpectSemicolon(CHECK_OK); 1563 ExpectSemicolon(CHECK_OK);
1448 result = factory()->NewEmptyStatement(pos); 1564 result = factory()->NewEmptyStatement(pos);
1449 break; 1565 break;
1566 }
1450 1567
1451 case Token::FUNCTION: 1568 case Token::FUNCTION:
1452 result = ParseFunctionDeclaration(&names, CHECK_OK); 1569 result = ParseFunctionDeclaration(&names, CHECK_OK);
1453 break; 1570 break;
1454 1571
1455 case Token::CLASS: 1572 case Token::CLASS:
1456 result = ParseClassDeclaration(&names, CHECK_OK); 1573 result = ParseClassDeclaration(&names, CHECK_OK);
1457 break; 1574 break;
1458 1575
1459 case Token::VAR: 1576 case Token::VAR:
(...skipping 3772 matching lines...) Expand 10 before | Expand all | Expand 10 after
5232 } else { 5349 } else {
5233 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); 5350 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
5234 running_hash = StringHasher::ComputeRunningHash(running_hash, data, 5351 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
5235 raw_string->length()); 5352 raw_string->length());
5236 } 5353 }
5237 } 5354 }
5238 5355
5239 return running_hash; 5356 return running_hash;
5240 } 5357 }
5241 } } // namespace v8::internal 5358 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698