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

Unified Diff: src/parser.cc

Issue 881623002: Begin modernization of --harmony-modules (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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') | src/scopes.cc » ('j') | test/cctest/test-parsing.cc » ('J')
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 51e79bb14cf1c6519de925d6bb1434e06ccc225f..a7d9a88f6c5d675b8cecc177b63f664a8f171e82 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -265,6 +265,7 @@ void Parser::SetCachedData() {
Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) {
DCHECK(ast_value_factory());
+ DCHECK(scope_type != MODULE_SCOPE || allow_harmony_modules());
Scope* result = new (zone())
Scope(isolate(), zone(), parent, scope_type, ast_value_factory());
result->Initialize();
@@ -934,8 +935,17 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
bool ok = true;
int beg_pos = scanner()->location().beg_pos;
- ParseSourceElements(body, Token::EOS, info->is_eval(), true, eval_scope,
- &ok);
+ if (info->is_module()) {
+ DCHECK(allow_harmony_modules());
+ Module* module = ParseModule(&ok);
+ if (ok) {
+ // TODO(adamk): Do something with returned Module
+ CHECK(module);
+ body->Add(factory()->NewEmptyStatement(RelocInfo::kNoPosition), zone());
+ }
+ } else {
+ ParseStatementList(body, Token::EOS, info->is_eval(), eval_scope, &ok);
+ }
if (ok && strict_mode() == STRICT) {
CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
@@ -1080,11 +1090,10 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
}
-void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
- int end_token, bool is_eval, bool is_global,
- Scope** eval_scope, bool* ok) {
- // SourceElements ::
- // (ModuleElement)* <end_token>
+void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
+ bool is_eval, Scope** eval_scope, bool* ok) {
+ // StatementList ::
+ // (StatementListItem)* <end_token>
// Allocate a target stack to use for this set of source
// elements. This way, all scripts and functions get their own
@@ -1092,7 +1101,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
// functions.
TargetScope scope(&this->target_stack_);
- DCHECK(processor != NULL);
+ DCHECK(body != NULL);
bool directive_prologue = true; // Parsing directive prologue.
while (peek() != end_token) {
@@ -1101,12 +1110,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
}
Scanner::Location token_loc = scanner()->peek_location();
- Statement* stat;
- if (is_global && !is_eval) {
- stat = ParseModuleElement(NULL, CHECK_OK);
- } else {
- stat = ParseBlockElement(NULL, CHECK_OK);
- }
+ Statement* stat = ParseStatementListItem(CHECK_OK);
if (stat == NULL || stat->IsEmpty()) {
directive_prologue = false; // End of directive prologue.
continue;
@@ -1162,134 +1166,64 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
}
}
- processor->Add(stat, zone());
+ body->Add(stat, zone());
}
return 0;
}
-Statement* Parser::ParseModuleElement(ZoneList<const AstRawString*>* labels,
- bool* ok) {
- // (Ecma 262 5th Edition, clause 14):
- // SourceElement:
+Statement* Parser::ParseStatementListItem(bool* ok) {
+ // (Ecma 262 6th Edition, 13.1):
+ // StatementListItem:
// Statement
- // FunctionDeclaration
- //
- // In harmony mode we allow additionally the following productions
- // ModuleElement:
- // LetDeclaration
- // ConstDeclaration
- // ModuleDeclaration
- // ImportDeclaration
- // ExportDeclaration
- // GeneratorDeclaration
+ // Declaration
switch (peek()) {
case Token::FUNCTION:
return ParseFunctionDeclaration(NULL, ok);
case Token::CLASS:
return ParseClassDeclaration(NULL, ok);
- case Token::IMPORT:
- return ParseImportDeclaration(ok);
- case Token::EXPORT:
- return ParseExportDeclaration(ok);
case Token::CONST:
- return ParseVariableStatement(kModuleElement, NULL, ok);
+ case Token::VAR:
+ return ParseVariableStatement(kStatementListItem, NULL, ok);
case Token::LET:
DCHECK(allow_harmony_scoping());
if (strict_mode() == STRICT) {
- return ParseVariableStatement(kModuleElement, NULL, ok);
+ return ParseVariableStatement(kStatementListItem, NULL, ok);
}
// Fall through.
- default: {
- Statement* stmt = ParseStatement(labels, CHECK_OK);
- // Handle 'module' as a context-sensitive keyword.
- if (FLAG_harmony_modules &&
- peek() == Token::IDENTIFIER &&
- !scanner()->HasAnyLineTerminatorBeforeNext() &&
- stmt != NULL) {
- ExpressionStatement* estmt = stmt->AsExpressionStatement();
- if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL &&
- estmt->expression()->AsVariableProxy()->raw_name() ==
- ast_value_factory()->module_string() &&
- !scanner()->literal_contains_escapes()) {
- return ParseModuleDeclaration(NULL, ok);
- }
- }
- return stmt;
- }
- }
-}
-
-
-Statement* Parser::ParseModuleDeclaration(ZoneList<const AstRawString*>* names,
- bool* ok) {
- // ModuleDeclaration:
- // 'module' Identifier Module
-
- int pos = peek_position();
- const AstRawString* name =
- ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
-
-#ifdef DEBUG
- if (FLAG_print_interface_details)
- PrintF("# Module %.*s ", name->length(), name->raw_data());
-#endif
-
- Module* module = ParseModule(CHECK_OK);
- VariableProxy* proxy = NewUnresolved(name, MODULE, module->interface());
- Declaration* declaration =
- factory()->NewModuleDeclaration(proxy, module, scope_, pos);
- Declare(declaration, true, CHECK_OK);
-
-#ifdef DEBUG
- if (FLAG_print_interface_details)
- PrintF("# Module %.*s ", name->length(), name->raw_data());
- if (FLAG_print_interfaces) {
- PrintF("module %.*s: ", name->length(), name->raw_data());
- module->interface()->Print();
+ default:
+ return ParseStatement(NULL, ok);
}
-#endif
-
- if (names) names->Add(name, zone());
- if (module->body() == NULL)
- return factory()->NewEmptyStatement(pos);
- else
- return factory()->NewModuleStatement(proxy, module->body(), pos);
}
-Module* Parser::ParseModule(bool* ok) {
- // Module:
- // '{' ModuleElement '}'
- // '=' ModulePath ';'
- // 'at' String ';'
+Statement* Parser::ParseModuleItem(bool* ok) {
+ // (Ecma 262 6th Edition, 15.2):
+ // ModuleItem :
+ // ImportDeclaration
+ // ExportDeclaration
+ // StatementListItem
switch (peek()) {
- case Token::LBRACE:
- return ParseModuleLiteral(ok);
-
- case Token::ASSIGN: {
- Expect(Token::ASSIGN, CHECK_OK);
- Module* result = ParseModulePath(CHECK_OK);
- ExpectSemicolon(CHECK_OK);
- return result;
- }
-
- default: {
- ExpectContextualKeyword(CStrVector("at"), CHECK_OK);
- Module* result = ParseModuleUrl(CHECK_OK);
- ExpectSemicolon(CHECK_OK);
- return result;
- }
+ case Token::IMPORT:
+ return ParseImportDeclaration(ok);
+ case Token::EXPORT:
+ return ParseExportDeclaration(ok);
+ default:
+ return ParseStatementListItem(ok);
}
}
-Module* Parser::ParseModuleLiteral(bool* ok) {
- // Module:
- // '{' ModuleElement '}'
+Module* Parser::ParseModule(bool* ok) {
+ // (Ecma 262 6th Edition, 15.2):
+ // Module :
+ // ModuleBody?
+ //
+ // ModuleBody :
+ // ModuleItem*
int pos = peek_position();
// Construct block expecting 16 statements.
@@ -1299,7 +1233,6 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
#endif
Scope* scope = NewScope(scope_, MODULE_SCOPE);
- Expect(Token::LBRACE, CHECK_OK);
scope->set_start_position(scanner()->location().beg_pos);
scope->SetStrictMode(STRICT);
@@ -1307,15 +1240,14 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
BlockState block_state(&scope_, scope);
Target target(&this->target_stack_, body);
- while (peek() != Token::RBRACE) {
- Statement* stat = ParseModuleElement(NULL, CHECK_OK);
+ while (peek() != Token::EOS) {
+ Statement* stat = ParseModuleItem(CHECK_OK);
if (stat && !stat->IsEmpty()) {
body->AddStatement(stat, zone());
}
}
}
- Expect(Token::RBRACE, CHECK_OK);
scope->set_end_position(scanner()->location().end_pos);
body->set_scope(scope);
@@ -1338,41 +1270,6 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
}
-Module* Parser::ParseModulePath(bool* ok) {
- // ModulePath:
- // Identifier
- // ModulePath '.' Identifier
-
- int pos = peek_position();
- Module* result = ParseModuleVariable(CHECK_OK);
- while (Check(Token::PERIOD)) {
- const AstRawString* name = ParseIdentifierName(CHECK_OK);
-#ifdef DEBUG
- if (FLAG_print_interface_details)
- PrintF("# Path .%.*s ", name->length(), name->raw_data());
-#endif
- Module* member = factory()->NewModulePath(result, name, pos);
- result->interface()->Add(name, member->interface(), zone(), ok);
- if (!*ok) {
-#ifdef DEBUG
- if (FLAG_print_interfaces) {
- PrintF("PATH TYPE ERROR at '%.*s'\n", name->length(), name->raw_data());
- PrintF("result: ");
- result->interface()->Print();
- PrintF("member: ");
- member->interface()->Print();
- }
-#endif
- ParserTraits::ReportMessage("invalid_module_path", name);
- return NULL;
- }
- result = member;
- }
-
- return result;
-}
-
-
Module* Parser::ParseModuleVariable(bool* ok) {
rossberg 2015/01/27 20:00:56 Is this still used?
adamk 2015/01/27 20:11:02 No, it's not. I thought it might be useful for "im
// ModulePath:
// Identifier
@@ -1421,24 +1318,11 @@ Module* Parser::ParseModuleUrl(bool* ok) {
}
-Module* Parser::ParseModuleSpecifier(bool* ok) {
- // ModuleSpecifier:
- // String
- // ModulePath
-
- if (peek() == Token::STRING) {
- return ParseModuleUrl(ok);
- } else {
- return ParseModulePath(ok);
- }
-}
-
-
-Block* Parser::ParseImportDeclaration(bool* ok) {
+Statement* Parser::ParseImportDeclaration(bool* ok) {
// ImportDeclaration:
- // 'import' IdentifierName (',' IdentifierName)* 'from' ModuleSpecifier ';'
+ // 'import' IdentifierName (',' IdentifierName)* 'from' ModuleUrl ';'
//
- // TODO(ES6): implement destructuring ImportSpecifiers
+ // TODO(ES6): implement current syntax
int pos = peek_position();
Expect(Token::IMPORT, CHECK_OK);
@@ -1453,38 +1337,17 @@ Block* Parser::ParseImportDeclaration(bool* ok) {
}
ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
- Module* module = ParseModuleSpecifier(CHECK_OK);
+ Module* module = ParseModuleUrl(CHECK_OK);
arv (Not doing code reviews) 2015/01/27 01:17:17 This is fine for now but this should not return a
adamk 2015/01/27 01:58:37 Yeah, the API probably just needs to match ParseSt
ExpectSemicolon(CHECK_OK);
- // Generate a separate declaration for each identifier.
- // TODO(ES6): once we implement destructuring, make that one declaration.
- Block* block = factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
+ // TODO(ES6): Do something with ParseModuleUrl's return value.
+ USE(module);
+
for (int i = 0; i < names.length(); ++i) {
-#ifdef DEBUG
- if (FLAG_print_interface_details)
- PrintF("# Import %.*s ", name->length(), name->raw_data());
-#endif
- Interface* interface = Interface::NewUnknown(zone());
- module->interface()->Add(names[i], interface, zone(), ok);
- if (!*ok) {
-#ifdef DEBUG
- if (FLAG_print_interfaces) {
- PrintF("IMPORT TYPE ERROR at '%.*s'\n", name->length(),
- name->raw_data());
- PrintF("module: ");
- module->interface()->Print();
- }
-#endif
- ParserTraits::ReportMessage("invalid_module_path", name);
- return NULL;
- }
- VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
- Declaration* declaration =
- factory()->NewImportDeclaration(proxy, module, scope_, pos);
- Declare(declaration, true, CHECK_OK);
+ // TODO(ES6): Add a let declaration for each name
rossberg 2015/01/27 20:00:55 Nit: misleading comment, as imports cannot be let-
adamk 2015/01/27 20:11:02 Fair enough, s/let/appropriate/
}
- return block;
+ return factory()->NewEmptyStatement(pos);
}
@@ -1496,7 +1359,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
// 'export' GeneratorDeclaration
// 'export' ModuleDeclaration
//
- // TODO(ES6): implement structuring ExportSpecifiers
+ // TODO(ES6): implement current syntax
Expect(Token::EXPORT, CHECK_OK);
@@ -1507,19 +1370,14 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
int pos = position();
const AstRawString* name =
ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
- // Handle 'module' as a context-sensitive keyword.
- if (name != ast_value_factory()->module_string()) {
+ names.Add(name, zone());
+ while (peek() == Token::COMMA) {
+ Consume(Token::COMMA);
+ 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());
- }
- ExpectSemicolon(CHECK_OK);
- result = factory()->NewEmptyStatement(pos);
- } else {
- result = ParseModuleDeclaration(&names, CHECK_OK);
}
+ ExpectSemicolon(CHECK_OK);
+ result = factory()->NewEmptyStatement(pos);
break;
}
@@ -1534,7 +1392,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
case Token::VAR:
case Token::LET:
case Token::CONST:
- result = ParseVariableStatement(kModuleElement, &names, CHECK_OK);
+ result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK);
break;
default:
@@ -1581,39 +1439,6 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
}
-Statement* Parser::ParseBlockElement(ZoneList<const AstRawString*>* labels,
- bool* ok) {
- // (Ecma 262 5th Edition, clause 14):
- // SourceElement:
- // Statement
- // FunctionDeclaration
- //
- // In harmony mode we allow additionally the following productions
- // BlockElement (aka SourceElement):
- // LetDeclaration
- // ConstDeclaration
- // GeneratorDeclaration
- // ClassDeclaration
-
- switch (peek()) {
- case Token::FUNCTION:
- return ParseFunctionDeclaration(NULL, ok);
- case Token::CLASS:
- return ParseClassDeclaration(NULL, ok);
- case Token::CONST:
- return ParseVariableStatement(kModuleElement, NULL, ok);
- case Token::LET:
- DCHECK(allow_harmony_scoping());
- if (strict_mode() == STRICT) {
- return ParseVariableStatement(kModuleElement, NULL, ok);
- }
- // Fall through.
- default:
- return ParseStatement(labels, ok);
- }
-}
-
-
Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
bool* ok) {
// Statement ::
@@ -2067,7 +1892,7 @@ Block* Parser::ParseScopedBlock(ZoneList<const AstRawString*>* labels,
Target target(&this->target_stack_, body);
while (peek() != Token::RBRACE) {
- Statement* stat = ParseBlockElement(NULL, CHECK_OK);
+ Statement* stat = ParseStatementListItem(CHECK_OK);
if (stat && !stat->IsEmpty()) {
body->AddStatement(stat, zone());
}
@@ -2482,24 +2307,16 @@ Statement* Parser::ParseExpressionOrLabelledStatement(
return ParseNativeDeclaration(ok);
}
- // Parsed expression statement, or the context-sensitive 'module' keyword.
- // Only expect semicolon in the former case.
+ // Parsed expression statement, followed by semicolon.
// Also detect attempts at 'let' declarations in sloppy mode.
rossberg 2015/01/27 20:00:56 Nit: remove the "also"
adamk 2015/01/27 20:11:02 Done.
- if (!FLAG_harmony_modules || peek() != Token::IDENTIFIER ||
- scanner()->HasAnyLineTerminatorBeforeNext() ||
- expr->AsVariableProxy() == NULL ||
- expr->AsVariableProxy()->raw_name() !=
- ast_value_factory()->module_string() ||
- scanner()->literal_contains_escapes()) {
- if (peek() == Token::IDENTIFIER && expr->AsVariableProxy() != NULL &&
- expr->AsVariableProxy()->raw_name() ==
- ast_value_factory()->let_string()) {
- ReportMessage("sloppy_lexical", NULL);
- *ok = false;
- return NULL;
- }
- ExpectSemicolon(CHECK_OK);
+ if (peek() == Token::IDENTIFIER && expr->AsVariableProxy() != NULL &&
+ expr->AsVariableProxy()->raw_name() ==
+ ast_value_factory()->let_string()) {
+ ReportMessage("sloppy_lexical", NULL);
+ *ok = false;
+ return NULL;
}
+ ExpectSemicolon(CHECK_OK);
return factory()->NewExpressionStatement(expr, pos);
}
@@ -3913,7 +3730,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
yield, RelocInfo::kNoPosition), zone());
}
- ParseSourceElements(body, Token::RBRACE, false, false, NULL, CHECK_OK);
+ ParseStatementList(body, Token::RBRACE, false, NULL, CHECK_OK);
if (is_generator) {
VariableProxy* get_proxy = factory()->NewVariableProxy(
« no previous file with comments | « src/parser.h ('k') | src/scopes.cc » ('j') | test/cctest/test-parsing.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698