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

Unified Diff: src/parser.cc

Issue 12646003: Add parser support for generators. (Closed) Base URL: git://github.com/v8/v8.git@bleeding_edge
Patch Set: Fix bad initialization list in last preparser commit Created 7 years, 9 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
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);
}
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | test/mjsunit/harmony/generators-parsing.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698