Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 17d5a461de2a4ee3f6c19d34342e84494cb44fce..8ed1adb204fa4a7736452ae1e0b4887c4c31578c 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -486,10 +486,12 @@ class Parser::BlockState BASE_EMBEDDED { |
Parser::FunctionState::FunctionState(Parser* parser, |
Scope* scope, |
+ bool is_generator, |
Isolate* isolate) |
: next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize), |
next_handler_index_(0), |
expected_property_count_(0), |
+ is_generator_(is_generator), |
only_simple_this_property_assignments_(false), |
this_property_assignments_(isolate->factory()->empty_fixed_array()), |
parser_(parser), |
@@ -642,7 +644,10 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, |
} |
ParsingModeScope parsing_mode(this, mode); |
- FunctionState function_state(this, scope, isolate()); // Enters 'scope'. |
+ bool is_generator = false; |
+ // Enters 'scope'. |
+ FunctionState function_state(this, scope, is_generator, isolate()); |
+ |
top_scope_->SetLanguageMode(info->language_mode()); |
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); |
bool ok = true; |
@@ -680,7 +685,8 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, |
FunctionLiteral::kNoDuplicateParameters, |
FunctionLiteral::ANONYMOUS_EXPRESSION, |
FunctionLiteral::kGlobalOrEval, |
- FunctionLiteral::kNotParenthesized); |
+ FunctionLiteral::kNotParenthesized, |
+ FunctionLiteral::kNotGenerator); |
result->set_ast_properties(factory()->visitor()->ast_properties()); |
} else if (stack_overflow_) { |
isolate()->StackOverflow(); |
@@ -754,7 +760,8 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source, |
scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope, |
zone()); |
} |
- FunctionState function_state(this, scope, isolate()); |
+ bool is_generator = false; // Top scope is not a generator. |
+ FunctionState function_state(this, scope, is_generator, isolate()); |
ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode()); |
ASSERT(scope->language_mode() != EXTENDED_MODE || |
info()->is_extended_mode()); |
@@ -768,6 +775,7 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source, |
bool ok = true; |
result = ParseFunctionLiteral(name, |
false, // Strict mode name already checked. |
+ shared_info->is_generator(), |
RelocInfo::kNoPosition, |
type, |
&ok); |
@@ -1132,6 +1140,7 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels, |
// ModuleDeclaration |
// ImportDeclaration |
// ExportDeclaration |
+ // GeneratorDeclaration |
switch (peek()) { |
case Token::FUNCTION: |
@@ -1430,6 +1439,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { |
// 'export' Identifier (',' Identifier)* ';' |
// 'export' VariableDeclaration |
// 'export' FunctionDeclaration |
+ // 'export' GeneratorDeclaration |
// 'export' ModuleDeclaration |
// |
// TODO(ES6): implement structuring ExportSpecifiers |
@@ -1509,6 +1519,7 @@ Statement* Parser::ParseBlockElement(ZoneStringList* labels, |
// BlockElement (aka SourceElement): |
// LetDeclaration |
// ConstDeclaration |
+ // GeneratorDeclaration |
switch (peek()) { |
case Token::FUNCTION: |
@@ -1628,6 +1639,10 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { |
// FunctionDeclaration |
// Common language extension is to allow function declaration in place |
// of any statement. This language extension is disabled in strict mode. |
+ // |
+ // In Harmony mode, this case also handles the extension: |
+ // Statement: |
+ // GeneratorDeclaration |
if (!top_scope_->is_classic_mode()) { |
ReportMessageAt(scanner().peek_location(), "strict_function", |
Vector<const char*>::empty()); |
@@ -1890,13 +1905,18 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) { |
Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) { |
// FunctionDeclaration :: |
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
+ // GeneratorDeclaration :: |
+ // 'function' '*' Identifier '(' FormalParameterListopt ')' |
+ // '{' FunctionBody '}' |
Expect(Token::FUNCTION, CHECK_OK); |
int function_token_position = scanner().location().beg_pos; |
+ bool is_generator = FLAG_harmony_generators && Check(Token::MUL); |
bool is_strict_reserved = false; |
Handle<String> name = ParseIdentifierOrStrictReservedWord( |
&is_strict_reserved, CHECK_OK); |
FunctionLiteral* fun = ParseFunctionLiteral(name, |
is_strict_reserved, |
+ is_generator, |
function_token_position, |
FunctionLiteral::DECLARATION, |
CHECK_OK); |
@@ -3004,8 +3024,13 @@ Expression* Parser::ParseExpression(bool accept_IN, bool* ok) { |
Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
// AssignmentExpression :: |
// ConditionalExpression |
+ // YieldExpression |
// LeftHandSideExpression AssignmentOperator AssignmentExpression |
+ if (peek() == Token::YIELD && is_generator()) { |
+ return ParseYieldExpression(ok); |
+ } |
+ |
if (fni_ != NULL) fni_->Enter(); |
Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK); |
@@ -3074,6 +3099,17 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
} |
+Expression* Parser::ParseYieldExpression(bool* ok) { |
+ // YieldExpression :: |
+ // 'yield' '*'? AssignmentExpression |
+ int position = scanner().peek_location().beg_pos; |
+ Expect(Token::YIELD, CHECK_OK); |
+ bool is_yield_star = Check(Token::MUL); |
+ Expression* expression = ParseAssignmentExpression(false, CHECK_OK); |
+ return factory()->NewYield(expression, is_yield_star, position); |
+} |
+ |
+ |
// Precedence = 3 |
Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) { |
// ConditionalExpression :: |
@@ -3450,6 +3486,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack, |
if (peek() == Token::FUNCTION) { |
Expect(Token::FUNCTION, CHECK_OK); |
int function_token_position = scanner().location().beg_pos; |
+ bool is_generator = FLAG_harmony_generators && Check(Token::MUL); |
Handle<String> name; |
bool is_strict_reserved_name = false; |
if (peek_any_identifier()) { |
@@ -3461,6 +3498,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack, |
: FunctionLiteral::NAMED_EXPRESSION; |
result = ParseFunctionLiteral(name, |
is_strict_reserved_name, |
+ is_generator, |
function_token_position, |
type, |
CHECK_OK); |
@@ -3604,6 +3642,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) { |
break; |
case Token::IDENTIFIER: |
+ case Token::YIELD: |
case Token::FUTURE_STRICT_RESERVED_WORD: { |
Handle<String> name = ParseIdentifier(CHECK_OK); |
if (fni_ != NULL) fni_->PushVariableName(name); |
@@ -4009,6 +4048,7 @@ ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, |
FunctionLiteral* value = |
ParseFunctionLiteral(name, |
false, // reserved words are allowed here |
+ false, // not a generator |
RelocInfo::kNoPosition, |
FunctionLiteral::ANONYMOUS_EXPRESSION, |
CHECK_OK); |
@@ -4310,6 +4350,7 @@ class SingletonLogger : public ParserRecorder { |
FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name, |
bool name_is_strict_reserved, |
+ bool is_generator, |
int function_token_position, |
FunctionLiteral::Type type, |
bool* ok) { |
@@ -4344,9 +4385,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name, |
FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_ |
? FunctionLiteral::kIsParenthesized |
: FunctionLiteral::kNotParenthesized; |
+ FunctionLiteral::IsGeneratorFlag generator = is_generator |
+ ? FunctionLiteral::kIsGenerator |
+ : FunctionLiteral::kNotGenerator; |
AstProperties ast_properties; |
// Parse function body. |
- { FunctionState function_state(this, scope, isolate()); |
+ { FunctionState function_state(this, scope, is_generator, isolate()); |
top_scope_->SetScopeName(function_name); |
// FormalParameterList :: |
@@ -4584,7 +4628,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name, |
duplicate_parameters, |
type, |
FunctionLiteral::kIsFunction, |
- parenthesized); |
+ parenthesized, |
+ generator); |
function_literal->set_function_token_position(function_token_position); |
function_literal->set_ast_properties(&ast_properties); |
@@ -4606,10 +4651,12 @@ preparser::PreParser::PreParseResult Parser::LazyParseFunctionLiteral( |
stack_limit, |
do_allow_lazy, |
allow_natives_syntax_, |
- allow_modules_); |
+ allow_modules_, |
+ FLAG_harmony_generators); |
} |
preparser::PreParser::PreParseResult result = |
reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(), |
+ is_generator(), |
logger); |
return result; |
} |
@@ -4672,7 +4719,8 @@ bool Parser::peek_any_identifier() { |
Token::Value next = peek(); |
return next == Token::IDENTIFIER || |
next == Token::FUTURE_RESERVED_WORD || |
- next == Token::FUTURE_STRICT_RESERVED_WORD; |
+ next == Token::FUTURE_STRICT_RESERVED_WORD || |
+ next == Token::YIELD; |
} |
@@ -4744,13 +4792,17 @@ Literal* Parser::GetLiteralTheHole() { |
// Parses an identifier that is valid for the current scope, in particular it |
// fails on strict mode future reserved keywords in a strict scope. |
Handle<String> Parser::ParseIdentifier(bool* ok) { |
- if (!top_scope_->is_classic_mode()) { |
- Expect(Token::IDENTIFIER, ok); |
- } else if (!Check(Token::IDENTIFIER)) { |
- Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); |
+ Token::Value next = Next(); |
+ if (next == Token::IDENTIFIER || |
+ (top_scope_->is_classic_mode() && |
+ (next == Token::FUTURE_STRICT_RESERVED_WORD || |
+ (next == Token::YIELD && !is_generator())))) { |
+ return GetSymbol(ok); |
+ } else { |
+ ReportUnexpectedToken(next); |
+ *ok = false; |
+ return Handle<String>(); |
} |
- if (!*ok) return Handle<String>(); |
- return GetSymbol(ok); |
} |
@@ -4758,12 +4810,17 @@ Handle<String> Parser::ParseIdentifier(bool* ok) { |
// whether it is strict mode future reserved. |
Handle<String> Parser::ParseIdentifierOrStrictReservedWord( |
bool* is_strict_reserved, bool* ok) { |
- *is_strict_reserved = false; |
- if (!Check(Token::IDENTIFIER)) { |
- Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); |
+ Token::Value next = Next(); |
+ if (next == Token::IDENTIFIER) { |
+ *is_strict_reserved = false; |
+ } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || |
+ (next == Token::YIELD && !is_generator())) { |
*is_strict_reserved = true; |
+ } else { |
+ ReportUnexpectedToken(next); |
+ *ok = false; |
+ return Handle<String>(); |
} |
- if (!*ok) return Handle<String>(); |
return GetSymbol(ok); |
} |
@@ -5875,6 +5932,9 @@ ScriptDataImpl* ParserApi::PreParse(Utf16CharacterStream* source, |
if (FLAG_lazy && (extension == NULL)) { |
flags |= kAllowLazy; |
} |
+ if (FLAG_harmony_generators) { |
+ flags |= kAllowGenerators; |
+ } |
CompleteParserRecorder recorder; |
return DoPreParse(source, flags, &recorder); |
} |