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

Unified 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, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.h ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 9539d3891f02a61d269376629185a01acf905ef5..044e0d2b4f7fab42c60a601b106d6256a9a3a1b3 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1299,26 +1299,31 @@ Module* Parser::ParseModuleSpecifier(bool* ok) {
}
-void* Parser::ParseModuleDeclarationClause(ZoneList<const AstRawString*>* names,
- bool* ok) {
- // Handles both imports and exports:
- //
- // ImportOrExportClause :
+void* Parser::ParseExportClause(ZoneList<const AstRawString*>* names,
+ Scanner::Location* reserved_loc, bool* ok) {
+ // ExportClause :
// '{' '}'
- // '{' ImportOrExportsList '}'
- // '{' ImportOrExportsList ',' '}'
+ // '{' ExportsList '}'
+ // '{' ExportsList ',' '}'
//
- // ImportOrExportsList :
- // ImportOrExportSpecifier
- // ImportOrExportsList ',' ImportOrExportSpecifier
+ // ExportsList :
+ // ExportSpecifier
+ // ExportsList ',' ExportSpecifier
//
- // ImportOrExportSpecifier :
+ // ExportSpecifier :
// IdentifierName
// IdentifierName 'as' IdentifierName
Expect(Token::LBRACE, CHECK_OK);
- while (peek() != Token::RBRACE) {
+ Token::Value name_tok;
+ while ((name_tok = peek()) != Token::RBRACE) {
+ // Keep track of the first reserved word encountered in case our
+ // caller needs to report an error.
+ if (!reserved_loc->IsValid() &&
+ !Token::IsIdentifier(name_tok, STRICT, false)) {
+ *reserved_loc = scanner()->location();
+ }
const AstRawString* name = ParseIdentifierName(CHECK_OK);
names->Add(name, zone());
const AstRawString* export_name = NULL;
@@ -1337,30 +1342,124 @@ void* Parser::ParseModuleDeclarationClause(ZoneList<const AstRawString*>* names,
}
+void* Parser::ParseNamedImports(ZoneList<const AstRawString*>* names,
+ bool* ok) {
+ // NamedImports :
+ // '{' '}'
+ // '{' ImportsList '}'
+ // '{' ImportsList ',' '}'
+ //
+ // ImportsList :
+ // ImportSpecifier
+ // ImportsList ',' ImportSpecifier
+ //
+ // ImportSpecifier :
+ // BindingIdentifier
+ // IdentifierName 'as' BindingIdentifier
+
+ Expect(Token::LBRACE, CHECK_OK);
+
+ Token::Value name_tok;
+ while ((name_tok = peek()) != Token::RBRACE) {
+ const AstRawString* name = ParseIdentifierName(CHECK_OK);
+ const AstRawString* import_name = NULL;
+ // In the presence of 'as', the left-side of the 'as' can
+ // be any IdentifierName. But without 'as', it must be a valid
+ // BindingIdentiifer.
+ if (CheckContextualKeyword(CStrVector("as"))) {
+ import_name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+ } else if (!Token::IsIdentifier(name_tok, STRICT, false)) {
+ *ok = false;
+ ReportMessageAt(scanner()->location(), "unexpected_reserved");
+ return NULL;
+ } else if (IsEvalOrArguments(name)) {
+ *ok = false;
+ ReportMessageAt(scanner()->location(), "strict_eval_arguments");
+ return NULL;
+ }
+ // TODO(ES6): Return the import_name as well as the name.
+ names->Add(name, zone());
+ USE(import_name);
+ if (peek() == Token::RBRACE) break;
+ Expect(Token::COMMA, CHECK_OK);
+ }
+
+ Expect(Token::RBRACE, CHECK_OK);
+
+ return NULL;
+}
+
+
Statement* Parser::ParseImportDeclaration(bool* ok) {
- // ImportDeclaration:
- // 'import' IdentifierName (',' IdentifierName)* 'from' ModuleUrl ';'
+ // ImportDeclaration :
+ // 'import' ImportClause 'from' ModuleSpecifier ';'
+ // 'import' ModuleSpecifier ';'
+ //
+ // ImportClause :
+ // NameSpaceImport
+ // NamedImports
+ // ImportedDefaultBinding
+ // ImportedDefaultBinding ',' NameSpaceImport
+ // ImportedDefaultBinding ',' NamedImports
//
- // TODO(ES6): implement current syntax
+ // NameSpaceImport :
+ // '*' 'as' ImportedBinding
int pos = peek_position();
Expect(Token::IMPORT, CHECK_OK);
+
+ Token::Value tok = peek();
+
+ // 'import' ModuleSpecifier ';'
+ if (tok == Token::STRING) {
+ ParseModuleSpecifier(CHECK_OK);
+ ExpectSemicolon(CHECK_OK);
+ return factory()->NewEmptyStatement(pos);
+ }
+
+ // Parse ImportedDefaultBinding if present.
+ const AstRawString* imported_default_binding = NULL;
+ if (tok != Token::MUL && tok != Token::LBRACE) {
+ imported_default_binding =
+ ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+ }
+
+ const AstRawString* module_instance_binding = NULL;
ZoneList<const AstRawString*> names(1, zone());
+ if (imported_default_binding == NULL || Check(Token::COMMA)) {
+ switch (peek()) {
+ case Token::MUL: {
+ Consume(Token::MUL);
+ ExpectContextualKeyword(CStrVector("as"), CHECK_OK);
+ module_instance_binding =
+ ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+ break;
+ }
- const AstRawString* name = ParseIdentifierName(CHECK_OK);
- names.Add(name, zone());
- while (peek() == Token::COMMA) {
- Consume(Token::COMMA);
- name = ParseIdentifierName(CHECK_OK);
- names.Add(name, zone());
+ case Token::LBRACE:
+ ParseNamedImports(&names, CHECK_OK);
+ break;
+
+ default:
+ *ok = false;
+ ReportUnexpectedToken(scanner()->current_token());
+ return NULL;
+ }
}
ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
Module* module = ParseModuleSpecifier(CHECK_OK);
+ USE(module);
+
ExpectSemicolon(CHECK_OK);
- // TODO(ES6): Do something with ParseModuleSpecifier's return value.
- USE(module);
+ if (module_instance_binding != NULL) {
+ // TODO(ES6): Bind name to the Module Instance Object of module.
+ }
+
+ if (imported_default_binding != NULL) {
+ // TODO(ES6): Add an appropriate declaration.
+ }
for (int i = 0; i < names.length(); ++i) {
// TODO(ES6): Add an appropriate declaration for each name
@@ -1435,18 +1534,36 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
break;
}
- case Token::LBRACE:
- ParseModuleDeclarationClause(&names, CHECK_OK);
+ case Token::LBRACE: {
+ // There are two cases here:
+ //
+ // 'export' ExportClause ';'
+ // and
+ // 'export' ExportClause FromClause ';'
+ //
+ // In the first case, the exported identifiers in ExportClause must
+ // not be reserved words, while in the latter they may be. We
+ // pass in a location that gets filled with the first reserved word
+ // encountered, and then throw a SyntaxError if we are in the
+ // non-FromClause case.
+ Scanner::Location reserved_loc = Scanner::Location::invalid();
+ ParseExportClause(&names, &reserved_loc, CHECK_OK);
if (CheckContextualKeyword(CStrVector("from"))) {
Module* module = ParseModuleSpecifier(CHECK_OK);
// TODO(ES6): Do something with the return value
// of ParseModuleSpecifier.
USE(module);
is_export_from = true;
+ } else if (reserved_loc.IsValid()) {
+ // No FromClause, so reserved words are invalid in ExportClause.
+ *ok = false;
+ ReportMessageAt(reserved_loc, "unexpected_reserved");
+ return NULL;
}
ExpectSemicolon(CHECK_OK);
result = factory()->NewEmptyStatement(pos);
break;
+ }
case Token::FUNCTION:
result = ParseFunctionDeclaration(&names, CHECK_OK);
« 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