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 |