Chromium Code Reviews| Index: src/parser.cc | 
| diff --git a/src/parser.cc b/src/parser.cc | 
| index 3b9b69b4fac4d4a1ac5ae5614f0422fa12954953..3dfab294c8b4610c98c3db3edeac3469c8d767ba 100644 | 
| --- a/src/parser.cc | 
| +++ b/src/parser.cc | 
| @@ -654,6 +654,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, | 
| return result; | 
| } | 
| + | 
| FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) { | 
| ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT); | 
| HistogramTimerScope timer(isolate()->counters()->parse_lazy()); | 
| @@ -1087,32 +1088,11 @@ class ThisNamedPropertyAssignmentFinder : public ParserFinder { | 
| }; | 
| -Statement* Parser::ParseSourceElement(ZoneStringList* labels, | 
| - bool* ok) { | 
| - // (Ecma 262 5th Edition, clause 14): | 
| - // SourceElement: | 
| - // Statement | 
| - // FunctionDeclaration | 
| - // | 
| - // In harmony mode we allow additionally the following productions | 
| - // SourceElement: | 
| - // LetDeclaration | 
| - // ConstDeclaration | 
| - | 
| - if (peek() == Token::FUNCTION) { | 
| - return ParseFunctionDeclaration(ok); | 
| - } else if (peek() == Token::LET || peek() == Token::CONST) { | 
| - return ParseVariableStatement(kSourceElement, ok); | 
| - } | 
| - return ParseStatement(labels, ok); | 
| -} | 
| - | 
| - | 
| void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, | 
| int end_token, | 
| bool* ok) { | 
| // SourceElements :: | 
| - // (SourceElement)* <end_token> | 
| + // (ModuleElement)* <end_token> | 
| // Allocate a target stack to use for this set of source | 
| // elements. This way, all scripts and functions get their own | 
| @@ -1131,7 +1111,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, | 
| } | 
| Scanner::Location token_loc = scanner().peek_location(); | 
| - Statement* stat = ParseSourceElement(NULL, CHECK_OK); | 
| + Statement* stat = ParseModuleElement(NULL, CHECK_OK); | 
| if (stat == NULL || stat->IsEmpty()) { | 
| directive_prologue = false; // End of directive prologue. | 
| continue; | 
| @@ -1187,6 +1167,194 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, | 
| } | 
| +Statement* Parser::ParseModuleElement(ZoneStringList* labels, | 
| + bool* ok) { | 
| + // (Ecma 262 5th Edition, clause 14): | 
| + // SourceElement: | 
| + // Statement | 
| + // FunctionDeclaration | 
| + // | 
| + // In harmony mode we allow additionally the following productions | 
| + // ModuleElement: | 
| + // LetDeclaration | 
| + // ConstDeclaration | 
| + // ModuleDeclaration | 
| + // ImportDeclaration | 
| + // ExportDeclaration | 
| + | 
| + switch (peek()) { | 
| + case Token::FUNCTION: | 
| + return ParseFunctionDeclaration(ok); | 
| + case Token::LET: | 
| + case Token::CONST: | 
| + return ParseVariableStatement(kModuleElement, ok); | 
| + case Token::MODULE: | 
| + return ParseModuleDeclaration(ok); | 
| + case Token::IMPORT: | 
| + return ParseImportDeclaration(ok); | 
| + case Token::EXPORT: | 
| + return ParseExportDeclaration(ok); | 
| + default: | 
| + return ParseStatement(labels, ok); | 
| + } | 
| +} | 
| + | 
| + | 
| +Block* Parser::ParseModuleDeclaration(bool* ok) { | 
| + // ModuleDeclaration: | 
| + // 'module' Identifier Module | 
| + | 
| + // Create new block with one expected declaration. | 
| + Block* block = factory()->NewBlock(NULL, 1, true); | 
| + Expect(Token::MODULE, CHECK_OK); | 
| + Handle<String> name = ParseIdentifier(CHECK_OK); | 
| + // top_scope_->AddDeclaration( | 
| + // factory()->NewModuleDeclaration(proxy, module, top_scope_)); | 
| + VariableProxy* proxy = Declare(name, LET, NULL, true, CHECK_OK); | 
| + Module* module = ParseModule(ok); | 
| + // TODO(rossberg): Add initialization statement to block. | 
| + USE(proxy); | 
| + USE(module); | 
| + return block; | 
| +} | 
| + | 
| + | 
| +Module* Parser::ParseModule(bool* ok) { | 
| + // Module: | 
| + // '{' ModuleElement '}' | 
| + // '=' ModulePath | 
| + // 'at' String | 
| + | 
| + switch (peek()) { | 
| + case Token::LBRACE: | 
| + return ParseModuleLiteral(ok); | 
| + | 
| + case Token::ASSIGN: | 
| + Expect(Token::ASSIGN, CHECK_OK); | 
| + return ParseModulePath(ok); | 
| + | 
| + default: | 
| + return ParseModuleUrl(ok); | 
| + } | 
| +} | 
| + | 
| + | 
| +Module* Parser::ParseModuleLiteral(bool* ok) { | 
| + // Module: | 
| + // '{' ModuleElement '}' | 
| + | 
| + // Construct block expecting 16 statements. | 
| + Block* body = factory()->NewBlock(NULL, 16, false); | 
| + Scope* scope = NewScope(top_scope_, MODULE_SCOPE); | 
| + | 
| + Expect(Token::LBRACE, CHECK_OK); | 
| + scope->set_start_position(scanner().location().beg_pos); | 
| + scope->SetLanguageMode(EXTENDED_MODE); | 
| + | 
| + { | 
| + BlockState block_state(this, scope); | 
| + TargetCollector collector; | 
| + Target target(&this->target_stack_, &collector); | 
| + Target target_body(&this->target_stack_, body); | 
| + InitializationBlockFinder block_finder(top_scope_, target_stack_); | 
| + | 
| + while (peek() != Token::RBRACE) { | 
| + Statement* stat = ParseModuleElement(NULL, CHECK_OK); | 
| + if (stat && !stat->IsEmpty()) { | 
| + body->AddStatement(stat); | 
| + block_finder.Update(stat); | 
| + } | 
| + } | 
| + } | 
| + | 
| + Expect(Token::RBRACE, CHECK_OK); | 
| + scope->set_end_position(scanner().location().end_pos); | 
| + body->set_block_scope(scope); | 
| + return factory()->NewModuleLiteral(body); | 
| +} | 
| + | 
| + | 
| +Module* Parser::ParseModulePath(bool* ok) { | 
| + // ModulePath: | 
| + // Identifier | 
| + // ModulePath '.' Identifier | 
| + | 
| + Module* result = ParseModuleVariable(CHECK_OK); | 
| + | 
| + while (Check(Token::PERIOD)) { | 
| + Handle<String> name = ParseIdentifierName(CHECK_OK); | 
| + result = factory()->NewModulePath(result, name); | 
| + } | 
| + | 
| + return result; | 
| +} | 
| + | 
| + | 
| +Module* Parser::ParseModuleVariable(bool* ok) { | 
| + // ModulePath: | 
| + // Identifier | 
| + | 
| + Handle<String> name = ParseIdentifier(CHECK_OK); | 
| + VariableProxy* proxy = top_scope_->NewUnresolved( | 
| + factory(), name, scanner().location().beg_pos); | 
| + return factory()->NewModuleVariable(proxy); | 
| +} | 
| + | 
| + | 
| +Module* Parser::ParseModuleUrl(bool* ok) { | 
| + // Module: | 
| + // 'at' String | 
| + | 
| + Expect(Token::IDENTIFIER, CHECK_OK); | 
| + Handle<String> symbol = GetSymbol(CHECK_OK); | 
| + if (!symbol->IsEqualTo(CStrVector("at"))) { | 
| + *ok = false; | 
| + ReportUnexpectedToken(scanner().current_token()); | 
| + return NULL; | 
| + } | 
| + Expect(Token::STRING, CHECK_OK); | 
| + symbol = GetSymbol(CHECK_OK); | 
| 
 
Lasse Reichstein Nielsen
2012/02/21 13:46:02
Great! :)
 
 | 
| + | 
| + return factory()->NewModuleUrl(symbol); | 
| +} | 
| + | 
| + | 
| +Block* Parser::ParseImportDeclaration(bool* ok) { | 
| + // TODO(rossberg) | 
| + return NULL; | 
| +} | 
| + | 
| + | 
| +Block* Parser::ParseExportDeclaration(bool* ok) { | 
| + // TODO(rossberg) | 
| + return NULL; | 
| +} | 
| + | 
| + | 
| +Statement* Parser::ParseBlockElement(ZoneStringList* 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 | 
| + | 
| + switch (peek()) { | 
| + case Token::FUNCTION: | 
| + return ParseFunctionDeclaration(ok); | 
| + case Token::LET: | 
| + case Token::CONST: | 
| + return ParseVariableStatement(kModuleElement, ok); | 
| + default: | 
| + return ParseStatement(labels, ok); | 
| + } | 
| +} | 
| + | 
| + | 
| Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { | 
| // Statement :: | 
| // Block | 
| @@ -1344,7 +1512,8 @@ VariableProxy* Parser::Declare(Handle<String> name, | 
| // statically declared. | 
| if (declaration_scope->is_function_scope() || | 
| declaration_scope->is_strict_or_extended_eval_scope() || | 
| - declaration_scope->is_block_scope()) { | 
| + declaration_scope->is_block_scope() || | 
| + declaration_scope->is_module_scope()) { | 
| // Declare the variable in the function scope. | 
| var = declaration_scope->LocalLookup(name); | 
| if (var == NULL) { | 
| @@ -1574,10 +1743,10 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { | 
| Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { | 
| - // The harmony mode uses source elements instead of statements. | 
| + // The harmony mode uses block elements instead of statements. | 
| // | 
| // Block :: | 
| - // '{' SourceElement* '}' | 
| + // '{' BlockElement* '}' | 
| // Construct block expecting 16 statements. | 
| Block* body = factory()->NewBlock(labels, 16, false); | 
| @@ -1593,7 +1762,7 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { | 
| InitializationBlockFinder block_finder(top_scope_, target_stack_); | 
| while (peek() != Token::RBRACE) { | 
| - Statement* stat = ParseSourceElement(NULL, CHECK_OK); | 
| + Statement* stat = ParseBlockElement(NULL, CHECK_OK); | 
| if (stat && !stat->IsEmpty()) { | 
| body->AddStatement(stat); | 
| block_finder.Update(stat); | 
| @@ -1614,10 +1783,8 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, | 
| // VariableDeclarations ';' | 
| Handle<String> ignore; | 
| - Block* result = ParseVariableDeclarations(var_context, | 
| - NULL, | 
| - &ignore, | 
| - CHECK_OK); | 
| + Block* result = | 
| + ParseVariableDeclarations(var_context, NULL, &ignore, CHECK_OK); | 
| ExpectSemicolon(CHECK_OK); | 
| return result; | 
| } | 
| @@ -1684,8 +1851,7 @@ Block* Parser::ParseVariableDeclarations( | 
| *ok = false; | 
| return NULL; | 
| case EXTENDED_MODE: | 
| - if (var_context != kSourceElement && | 
| - var_context != kForStatement) { | 
| + if (var_context == kStatement) { | 
| // In extended mode 'const' declarations are only allowed in source | 
| // element positions. | 
| ReportMessage("unprotected_const", Vector<const char*>::empty()); | 
| @@ -1710,10 +1876,8 @@ Block* Parser::ParseVariableDeclarations( | 
| return NULL; | 
| } | 
| Consume(Token::LET); | 
| - if (var_context != kSourceElement && | 
| - var_context != kForStatement) { | 
| + if (var_context == kStatement) { | 
| // Let declarations are only allowed in source element positions. | 
| - ASSERT(var_context == kStatement); | 
| ReportMessage("unprotected_let", Vector<const char*>::empty()); | 
| *ok = false; | 
| return NULL; | 
| @@ -2453,10 +2617,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { | 
| Handle<String> name; | 
| VariableDeclarationProperties decl_props = kHasNoInitializers; | 
| Block* variable_statement = | 
| - ParseVariableDeclarations(kForStatement, | 
| - &decl_props, | 
| - &name, | 
| - CHECK_OK); | 
| + ParseVariableDeclarations(kForStatement, &decl_props, &name, CHECK_OK); | 
| bool accept_IN = !name.is_null() && decl_props != kHasInitializers; | 
| if (peek() == Token::IN && accept_IN) { | 
| // Rewrite a for-in statement of the form |