| Index: src/preparser.cc
|
| diff --git a/src/preparser.cc b/src/preparser.cc
|
| index c461d8a4bd2e3f5ed0084c6616a3e3d44601dada..9f68317b442ccdbb70b88a5c0528063f1f4f0423 100644
|
| --- a/src/preparser.cc
|
| +++ b/src/preparser.cc
|
| @@ -53,12 +53,13 @@ int isfinite(double value);
|
| namespace preparser {
|
|
|
| PreParser::PreParseResult PreParser::PreParseLazyFunction(
|
| - i::LanguageMode mode, i::ParserRecorder* log) {
|
| + i::LanguageMode mode, bool is_generator, i::ParserRecorder* log) {
|
| log_ = log;
|
| // Lazy functions always have trivial outer scopes (no with/catch scopes).
|
| Scope top_scope(&scope_, kTopLevelScope);
|
| set_language_mode(mode);
|
| Scope function_scope(&scope_, kFunctionScope);
|
| + function_scope.set_is_generator(is_generator);
|
| ASSERT_EQ(i::Token::LBRACE, scanner_->current_token());
|
| bool ok = true;
|
| int start_position = scanner_->peek_location().beg_pos;
|
| @@ -154,6 +155,7 @@ PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
|
| // SourceElement:
|
| // LetDeclaration
|
| // ConstDeclaration
|
| + // GeneratorDeclaration
|
|
|
| switch (peek()) {
|
| case i::Token::FUNCTION:
|
| @@ -296,10 +298,11 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
|
| // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
|
| Expect(i::Token::FUNCTION, CHECK_OK);
|
|
|
| + bool is_generator = Check(i::Token::MUL);
|
| Identifier identifier = ParseIdentifier(CHECK_OK);
|
| i::Scanner::Location location = scanner_->location();
|
|
|
| - Expression function_value = ParseFunctionLiteral(CHECK_OK);
|
| + Expression function_value = ParseFunctionLiteral(is_generator, CHECK_OK);
|
|
|
| if (function_value.IsStrictFunction() &&
|
| !identifier.IsValidStrictVariable()) {
|
| @@ -810,8 +813,13 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
|
| bool* ok) {
|
| // AssignmentExpression ::
|
| // ConditionalExpression
|
| + // YieldExpression
|
| // LeftHandSideExpression AssignmentOperator AssignmentExpression
|
|
|
| + if (scope_->is_generator() && peek() == i::Token::YIELD) {
|
| + return ParseYieldExpression(ok);
|
| + }
|
| +
|
| i::Scanner::Location before = scanner_->peek_location();
|
| Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
|
|
|
| @@ -842,6 +850,19 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
|
|
|
|
|
| // Precedence = 3
|
| +PreParser::Expression PreParser::ParseYieldExpression(bool* ok) {
|
| + // YieldExpression ::
|
| + // 'yield' '*'? AssignmentExpression
|
| + Consume(i::Token::YIELD);
|
| + Check(i::Token::MUL);
|
| +
|
| + ParseAssignmentExpression(false, CHECK_OK);
|
| +
|
| + return Expression::Default();
|
| +}
|
| +
|
| +
|
| +// Precedence = 3
|
| PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
|
| bool* ok) {
|
| // ConditionalExpression ::
|
| @@ -1034,11 +1055,13 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
|
| Expression result = Expression::Default();
|
| if (peek() == i::Token::FUNCTION) {
|
| Consume(i::Token::FUNCTION);
|
| +
|
| + bool is_generator = Check(i::Token::MUL);
|
| Identifier identifier = Identifier::Default();
|
| if (peek_any_identifier()) {
|
| identifier = ParseIdentifier(CHECK_OK);
|
| }
|
| - result = ParseFunctionLiteral(CHECK_OK);
|
| + result = ParseFunctionLiteral(is_generator, CHECK_OK);
|
| if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
|
| StrictModeIdentifierViolation(scanner_->location(),
|
| "strict_function_name",
|
| @@ -1112,6 +1135,7 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
|
|
|
| case i::Token::FUTURE_RESERVED_WORD:
|
| case i::Token::FUTURE_STRICT_RESERVED_WORD:
|
| + case i::Token::YIELD:
|
| case i::Token::IDENTIFIER: {
|
| Identifier id = ParseIdentifier(CHECK_OK);
|
| result = Expression::FromIdentifier(id);
|
| @@ -1257,7 +1281,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
|
| }
|
| PropertyType type = is_getter ? kGetterProperty : kSetterProperty;
|
| CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
|
| - ParseFunctionLiteral(CHECK_OK);
|
| + ParseFunctionLiteral(false, CHECK_OK);
|
| if (peek() != i::Token::RBRACE) {
|
| Expect(i::Token::COMMA, CHECK_OK);
|
| }
|
| @@ -1344,7 +1368,8 @@ PreParser::Arguments PreParser::ParseArguments(bool* ok) {
|
| }
|
|
|
|
|
| -PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
|
| +PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator,
|
| + bool* ok) {
|
| // Function ::
|
| // '(' FormalParameterList? ')' '{' FunctionBody '}'
|
|
|
| @@ -1352,6 +1377,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
|
| ScopeType outer_scope_type = scope_->type();
|
| bool inside_with = scope_->IsInsideWith();
|
| Scope function_scope(&scope_, kFunctionScope);
|
| + function_scope.set_is_generator(is_generator);
|
| // FormalParameterList ::
|
| // '(' (Identifier)*[','] ')'
|
| Expect(i::Token::LPAREN, CHECK_OK);
|
| @@ -1497,6 +1523,8 @@ PreParser::Identifier PreParser::GetIdentifierSymbol() {
|
| } else if (scanner_->current_token() ==
|
| i::Token::FUTURE_STRICT_RESERVED_WORD) {
|
| return Identifier::FutureStrictReserved();
|
| + } else if (scanner_->current_token() == i::Token::YIELD) {
|
| + return Identifier::Yield();
|
| }
|
| if (scanner_->is_literal_ascii()) {
|
| // Detect strict-mode poison words.
|
| @@ -1523,6 +1551,14 @@ PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
|
| *ok = false;
|
| return GetIdentifierSymbol();
|
| }
|
| + case i::Token::YIELD:
|
| + if (scope_->is_generator()) {
|
| + // 'yield' in a generator is only valid as part of a YieldExpression.
|
| + ReportMessageAt(scanner_->location(), "unexpected_token", "yield");
|
| + *ok = false;
|
| + return Identifier::Yield();
|
| + }
|
| + // FALLTHROUGH
|
| case i::Token::FUTURE_STRICT_RESERVED_WORD:
|
| if (!is_classic_mode()) {
|
| i::Scanner::Location location = scanner_->location();
|
| @@ -1580,7 +1616,7 @@ void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
|
| const char* type = eval_args_type;
|
| if (identifier.IsFutureReserved()) {
|
| type = "reserved_word";
|
| - } else if (identifier.IsFutureStrictReserved()) {
|
| + } else if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
|
| type = "strict_reserved_word";
|
| }
|
| if (!is_classic_mode()) {
|
| @@ -1634,7 +1670,8 @@ bool PreParser::peek_any_identifier() {
|
| i::Token::Value next = peek();
|
| return next == i::Token::IDENTIFIER ||
|
| next == i::Token::FUTURE_RESERVED_WORD ||
|
| - next == i::Token::FUTURE_STRICT_RESERVED_WORD;
|
| + next == i::Token::FUTURE_STRICT_RESERVED_WORD ||
|
| + next == i::Token::YIELD;
|
| }
|
|
|
|
|
|
|