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

Unified Diff: src/parser.cc

Issue 9401008: Parsing of basic module declarations (no imports/exports yet). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed Lasse's comments. Created 8 years, 10 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/prettyprinter.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 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
« no previous file with comments | « src/parser.h ('k') | src/prettyprinter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698