Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index dff7de9e6b25c9c9370c866ab5bd4f52646852a6..9539d3891f02a61d269376629185a01acf905ef5 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -1270,7 +1270,7 @@ Module* Parser::ParseModule(bool* ok) { |
} |
-Module* Parser::ParseModuleUrl(bool* ok) { |
+Module* Parser::ParseModuleSpecifier(bool* ok) { |
// Module: |
// String |
@@ -1299,6 +1299,44 @@ Module* Parser::ParseModuleUrl(bool* ok) { |
} |
+void* Parser::ParseModuleDeclarationClause(ZoneList<const AstRawString*>* names, |
+ bool* ok) { |
+ // Handles both imports and exports: |
+ // |
+ // ImportOrExportClause : |
+ // '{' '}' |
+ // '{' ImportOrExportsList '}' |
+ // '{' ImportOrExportsList ',' '}' |
+ // |
+ // ImportOrExportsList : |
+ // ImportOrExportSpecifier |
+ // ImportOrExportsList ',' ImportOrExportSpecifier |
+ // |
+ // ImportOrExportSpecifier : |
+ // IdentifierName |
+ // IdentifierName 'as' IdentifierName |
+ |
+ Expect(Token::LBRACE, CHECK_OK); |
+ |
+ while (peek() != Token::RBRACE) { |
+ const AstRawString* name = ParseIdentifierName(CHECK_OK); |
+ names->Add(name, zone()); |
+ const AstRawString* export_name = NULL; |
+ if (CheckContextualKeyword(CStrVector("as"))) { |
+ export_name = ParseIdentifierName(CHECK_OK); |
+ } |
+ // TODO(ES6): Return the export_name as well as the name. |
+ USE(export_name); |
+ if (peek() == Token::RBRACE) break; |
+ Expect(Token::COMMA, CHECK_OK); |
+ } |
+ |
+ Expect(Token::RBRACE, CHECK_OK); |
+ |
+ return 0; |
+} |
+ |
+ |
Statement* Parser::ParseImportDeclaration(bool* ok) { |
// ImportDeclaration: |
// 'import' IdentifierName (',' IdentifierName)* 'from' ModuleUrl ';' |
@@ -1318,10 +1356,10 @@ Statement* Parser::ParseImportDeclaration(bool* ok) { |
} |
ExpectContextualKeyword(CStrVector("from"), CHECK_OK); |
- Module* module = ParseModuleUrl(CHECK_OK); |
+ Module* module = ParseModuleSpecifier(CHECK_OK); |
ExpectSemicolon(CHECK_OK); |
- // TODO(ES6): Do something with ParseModuleUrl's return value. |
+ // TODO(ES6): Do something with ParseModuleSpecifier's return value. |
USE(module); |
for (int i = 0; i < names.length(); ++i) { |
@@ -1332,36 +1370,84 @@ Statement* Parser::ParseImportDeclaration(bool* ok) { |
} |
+Statement* Parser::ParseExportDefault(bool* ok) { |
+ // Supports the following productions, starting after the 'default' token: |
+ // 'export' 'default' FunctionDeclaration |
+ // 'export' 'default' ClassDeclaration |
+ // 'export' 'default' AssignmentExpression[In] ';' |
+ |
+ Statement* result = NULL; |
+ switch (peek()) { |
+ case Token::FUNCTION: |
+ // TODO(ES6): Support parsing anonymous function declarations here. |
+ result = ParseFunctionDeclaration(NULL, CHECK_OK); |
+ break; |
+ |
+ case Token::CLASS: |
+ // TODO(ES6): Support parsing anonymous class declarations here. |
+ result = ParseClassDeclaration(NULL, CHECK_OK); |
+ break; |
+ |
+ default: { |
+ int pos = peek_position(); |
+ Expression* expr = ParseAssignmentExpression(true, CHECK_OK); |
+ ExpectSemicolon(CHECK_OK); |
+ result = factory()->NewExpressionStatement(expr, pos); |
+ break; |
+ } |
+ } |
+ |
+ // TODO(ES6): Add default export to scope_->interface() |
+ |
+ return result; |
+} |
+ |
+ |
Statement* Parser::ParseExportDeclaration(bool* ok) { |
// ExportDeclaration: |
- // 'export' Identifier (',' Identifier)* ';' |
- // 'export' VariableDeclaration |
- // 'export' FunctionDeclaration |
- // 'export' GeneratorDeclaration |
- // 'export' ModuleDeclaration |
- // |
- // TODO(ES6): implement current syntax |
+ // 'export' '*' 'from' ModuleSpecifier ';' |
+ // 'export' ExportClause ('from' ModuleSpecifier)? ';' |
+ // 'export' VariableStatement |
+ // 'export' Declaration |
+ // 'export' 'default' ... (handled in ParseExportDefault) |
+ int pos = peek_position(); |
Expect(Token::EXPORT, CHECK_OK); |
Statement* result = NULL; |
ZoneList<const AstRawString*> names(1, zone()); |
+ bool is_export_from = false; |
switch (peek()) { |
- case Token::IDENTIFIER: { |
- int pos = position(); |
- const AstRawString* name = |
- ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
- names.Add(name, zone()); |
- while (peek() == Token::COMMA) { |
- Consume(Token::COMMA); |
- name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
- names.Add(name, zone()); |
- } |
+ case Token::DEFAULT: |
+ Consume(Token::DEFAULT); |
+ return ParseExportDefault(ok); |
+ |
+ case Token::MUL: { |
+ Consume(Token::MUL); |
+ ExpectContextualKeyword(CStrVector("from"), CHECK_OK); |
+ Module* module = ParseModuleSpecifier(CHECK_OK); |
ExpectSemicolon(CHECK_OK); |
+ // TODO(ES6): Do something with the return value |
+ // of ParseModuleSpecifier. |
+ USE(module); |
+ is_export_from = true; |
result = factory()->NewEmptyStatement(pos); |
break; |
} |
+ case Token::LBRACE: |
+ ParseModuleDeclarationClause(&names, 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; |
+ } |
+ ExpectSemicolon(CHECK_OK); |
+ result = factory()->NewEmptyStatement(pos); |
+ break; |
+ |
case Token::FUNCTION: |
result = ParseFunctionDeclaration(&names, CHECK_OK); |
break; |
@@ -1395,24 +1481,27 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { |
} |
} |
- // Extract declared names into export declarations and interface. |
- Interface* interface = scope_->interface(); |
- for (int i = 0; i < names.length(); ++i) { |
+ // TODO(ES6): Handle 'export from' once imports are properly implemented. |
+ // For now we just drop such exports on the floor. |
+ if (!is_export_from) { |
+ // Extract declared names into export declarations and interface. |
+ Interface* interface = scope_->interface(); |
+ for (int i = 0; i < names.length(); ++i) { |
#ifdef DEBUG |
- if (FLAG_print_interface_details) |
- PrintF("# Export %.*s ", names[i]->length(), names[i]->raw_data()); |
+ if (FLAG_print_interface_details) |
+ PrintF("# Export %.*s ", names[i]->length(), names[i]->raw_data()); |
#endif |
- Interface* inner = Interface::NewUnknown(zone()); |
- interface->Add(names[i], inner, zone(), CHECK_OK); |
- if (!*ok) |
- return NULL; |
- VariableProxy* proxy = NewUnresolved(names[i], LET, inner); |
- USE(proxy); |
- // TODO(rossberg): Rethink whether we actually need to store export |
- // declarations (for compilation?). |
- // ExportDeclaration* declaration = |
- // factory()->NewExportDeclaration(proxy, scope_, position); |
- // scope_->AddDeclaration(declaration); |
+ Interface* inner = Interface::NewUnknown(zone()); |
+ interface->Add(names[i], inner, zone(), CHECK_OK); |
+ if (!*ok) return NULL; |
+ VariableProxy* proxy = NewUnresolved(names[i], LET, inner); |
+ USE(proxy); |
+ // TODO(rossberg): Rethink whether we actually need to store export |
+ // declarations (for compilation?). |
+ // ExportDeclaration* declaration = |
+ // factory()->NewExportDeclaration(proxy, scope_, position); |
+ // scope_->AddDeclaration(declaration); |
+ } |
} |
DCHECK(result != NULL); |