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

Unified Diff: src/parsing/parser.cc

Issue 2313703002: Revert of [parser] Refactor of Parse*Statement*, part 1 (Closed)
Patch Set: Created 4 years, 3 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/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/parser.cc
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index 78791ec905d48196e233de3be60258d67fdf262c..9f18790eefce3cc4ff1a4637f29cd039e5b84262 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -231,39 +231,41 @@
// 'continue' statement targets). Upon construction, a new target is
// added; it is removed upon destruction.
-class ParserTarget BASE_EMBEDDED {
+class Target BASE_EMBEDDED {
public:
- ParserTarget(ParserBase<Parser>* parser, BreakableStatement* statement)
- : variable_(&parser->impl()->target_stack_),
- statement_(statement),
- previous_(parser->impl()->target_stack_) {
- parser->impl()->target_stack_ = this;
- }
-
- ~ParserTarget() { *variable_ = previous_; }
-
- ParserTarget* previous() { return previous_; }
+ Target(Target** variable, BreakableStatement* statement)
+ : variable_(variable), statement_(statement), previous_(*variable) {
+ *variable = this;
+ }
+
+ ~Target() {
+ *variable_ = previous_;
+ }
+
+ Target* previous() { return previous_; }
BreakableStatement* statement() { return statement_; }
private:
- ParserTarget** variable_;
+ Target** variable_;
BreakableStatement* statement_;
- ParserTarget* previous_;
+ Target* previous_;
};
-class ParserTargetScope BASE_EMBEDDED {
+
+class TargetScope BASE_EMBEDDED {
public:
- explicit ParserTargetScope(ParserBase<Parser>* parser)
- : variable_(&parser->impl()->target_stack_),
- previous_(parser->impl()->target_stack_) {
- parser->impl()->target_stack_ = nullptr;
- }
-
- ~ParserTargetScope() { *variable_ = previous_; }
+ explicit TargetScope(Target** variable)
+ : variable_(variable), previous_(*variable) {
+ *variable = NULL;
+ }
+
+ ~TargetScope() {
+ *variable_ = previous_;
+ }
private:
- ParserTarget** variable_;
- ParserTarget* previous_;
+ Target** variable_;
+ Target* previous_;
};
@@ -929,6 +931,131 @@
return result;
}
+
+void Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
+ bool* ok) {
+ // StatementList ::
+ // (StatementListItem)* <end_token>
+
+ // Allocate a target stack to use for this set of source
+ // elements. This way, all scripts and functions get their own
+ // target stack thus avoiding illegal breaks and continues across
+ // functions.
+ TargetScope scope(&this->target_stack_);
+
+ DCHECK(body != NULL);
+ bool directive_prologue = true; // Parsing directive prologue.
+
+ while (peek() != end_token) {
+ if (directive_prologue && peek() != Token::STRING) {
+ directive_prologue = false;
+ }
+
+ Scanner::Location token_loc = scanner()->peek_location();
+ Statement* stat = ParseStatementListItem(CHECK_OK_VOID);
+ if (stat == NULL || stat->IsEmpty()) {
+ directive_prologue = false; // End of directive prologue.
+ continue;
+ }
+
+ if (directive_prologue) {
+ // A shot at a directive.
+ ExpressionStatement* e_stat;
+ Literal* literal;
+ // Still processing directive prologue?
+ if ((e_stat = stat->AsExpressionStatement()) != NULL &&
+ (literal = e_stat->expression()->AsLiteral()) != NULL &&
+ literal->raw_value()->IsString()) {
+ // Check "use strict" directive (ES5 14.1), "use asm" directive.
+ bool use_strict_found =
+ literal->raw_value()->AsString() ==
+ ast_value_factory()->use_strict_string() &&
+ token_loc.end_pos - token_loc.beg_pos ==
+ ast_value_factory()->use_strict_string()->length() + 2;
+ if (use_strict_found) {
+ if (is_sloppy(language_mode())) {
+ RaiseLanguageMode(STRICT);
+ }
+
+ if (!this->scope()->HasSimpleParameters()) {
+ // TC39 deemed "use strict" directives to be an error when occurring
+ // in the body of a function with non-simple parameter list, on
+ // 29/7/2015. https://goo.gl/ueA7Ln
+ const AstRawString* string = literal->raw_value()->AsString();
+ ReportMessageAt(token_loc,
+ MessageTemplate::kIllegalLanguageModeDirective,
+ string);
+ *ok = false;
+ return;
+ }
+ // Because declarations in strict eval code don't leak into the scope
+ // of the eval call, it is likely that functions declared in strict
+ // eval code will be used within the eval code, so lazy parsing is
+ // probably not a win.
+ if (this->scope()->is_eval_scope()) mode_ = PARSE_EAGERLY;
+ } else if (literal->raw_value()->AsString() ==
+ ast_value_factory()->use_asm_string() &&
+ token_loc.end_pos - token_loc.beg_pos ==
+ ast_value_factory()->use_asm_string()->length() + 2) {
+ // Store the usage count; The actual use counter on the isolate is
+ // incremented after parsing is done.
+ ++use_counts_[v8::Isolate::kUseAsm];
+ DCHECK(this->scope()->is_declaration_scope());
+ this->scope()->AsDeclarationScope()->set_asm_module();
+ } else {
+ // Should not change mode, but will increment UseCounter
+ // if appropriate. Ditto usages below.
+ RaiseLanguageMode(SLOPPY);
+ }
+ } else {
+ // End of the directive prologue.
+ directive_prologue = false;
+ RaiseLanguageMode(SLOPPY);
+ }
+ } else {
+ RaiseLanguageMode(SLOPPY);
+ }
+
+ body->Add(stat, zone());
+ }
+}
+
+
+Statement* Parser::ParseStatementListItem(bool* ok) {
+ // (Ecma 262 6th Edition, 13.1):
+ // StatementListItem:
+ // Statement
+ // Declaration
+ const Token::Value peeked = peek();
+ switch (peeked) {
+ case Token::FUNCTION:
+ return ParseHoistableDeclaration(NULL, false, ok);
+ case Token::CLASS:
+ Consume(Token::CLASS);
+ return ParseClassDeclaration(NULL, false, ok);
+ case Token::CONST:
+ return ParseVariableStatement(kStatementListItem, NULL, ok);
+ case Token::VAR:
+ return ParseVariableStatement(kStatementListItem, NULL, ok);
+ case Token::LET:
+ if (IsNextLetKeyword()) {
+ return ParseVariableStatement(kStatementListItem, NULL, ok);
+ }
+ break;
+ case Token::ASYNC:
+ if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
+ !scanner()->HasAnyLineTerminatorAfterNext()) {
+ Consume(Token::ASYNC);
+ return ParseAsyncFunctionDeclaration(NULL, false, ok);
+ }
+ /* falls through */
+ default:
+ break;
+ }
+ return ParseStatement(NULL, kAllowLabelledFunctionStatement, ok);
+}
+
+
Statement* Parser::ParseModuleItem(bool* ok) {
// ecma262/#prod-ModuleItem
// ModuleItem :
@@ -1359,6 +1486,139 @@
return result;
}
+Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
+ AllowLabelledFunctionStatement allow_function,
+ bool* ok) {
+ // Statement ::
+ // EmptyStatement
+ // ...
+
+ if (peek() == Token::SEMICOLON) {
+ Next();
+ return factory()->NewEmptyStatement(kNoSourcePosition);
+ }
+ return ParseSubStatement(labels, allow_function, ok);
+}
+
+Statement* Parser::ParseSubStatement(
+ ZoneList<const AstRawString*>* labels,
+ AllowLabelledFunctionStatement allow_function, bool* ok) {
+ // Statement ::
+ // Block
+ // VariableStatement
+ // EmptyStatement
+ // ExpressionStatement
+ // IfStatement
+ // IterationStatement
+ // ContinueStatement
+ // BreakStatement
+ // ReturnStatement
+ // WithStatement
+ // LabelledStatement
+ // SwitchStatement
+ // ThrowStatement
+ // TryStatement
+ // DebuggerStatement
+
+ // Note: Since labels can only be used by 'break' and 'continue'
+ // statements, which themselves are only valid within blocks,
+ // iterations or 'switch' statements (i.e., BreakableStatements),
+ // labels can be simply ignored in all other cases; except for
+ // trivial labeled break statements 'label: break label' which is
+ // parsed into an empty statement.
+ switch (peek()) {
+ case Token::LBRACE:
+ return ParseBlock(labels, ok);
+
+ case Token::SEMICOLON:
+ Next();
+ return factory()->NewEmptyStatement(kNoSourcePosition);
+
+ case Token::IF:
+ return ParseIfStatement(labels, ok);
+
+ case Token::DO:
+ return ParseDoWhileStatement(labels, ok);
+
+ case Token::WHILE:
+ return ParseWhileStatement(labels, ok);
+
+ case Token::FOR:
+ return ParseForStatement(labels, ok);
+
+ case Token::CONTINUE:
+ case Token::BREAK:
+ case Token::RETURN:
+ case Token::THROW:
+ case Token::TRY: {
+ // These statements must have their labels preserved in an enclosing
+ // block
+ if (labels == NULL) {
+ return ParseStatementAsUnlabelled(labels, ok);
+ } else {
+ Block* result =
+ factory()->NewBlock(labels, 1, false, kNoSourcePosition);
+ Target target(&this->target_stack_, result);
+ Statement* statement = ParseStatementAsUnlabelled(labels, CHECK_OK);
+ if (result) result->statements()->Add(statement, zone());
+ return result;
+ }
+ }
+
+ case Token::WITH:
+ return ParseWithStatement(labels, ok);
+
+ case Token::SWITCH:
+ return ParseSwitchStatement(labels, ok);
+
+ case Token::FUNCTION:
+ // FunctionDeclaration only allowed as a StatementListItem, not in
+ // an arbitrary Statement position. Exceptions such as
+ // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
+ // are handled by calling ParseScopedStatement rather than
+ // ParseSubStatement directly.
+ ReportMessageAt(scanner()->peek_location(),
+ is_strict(language_mode())
+ ? MessageTemplate::kStrictFunction
+ : MessageTemplate::kSloppyFunction);
+ *ok = false;
+ return nullptr;
+
+ case Token::DEBUGGER:
+ return ParseDebuggerStatement(ok);
+
+ case Token::VAR:
+ return ParseVariableStatement(kStatement, NULL, ok);
+
+ default:
+ return ParseExpressionOrLabelledStatement(labels, allow_function, ok);
+ }
+}
+
+Statement* Parser::ParseStatementAsUnlabelled(
+ ZoneList<const AstRawString*>* labels, bool* ok) {
+ switch (peek()) {
+ case Token::CONTINUE:
+ return ParseContinueStatement(ok);
+
+ case Token::BREAK:
+ return ParseBreakStatement(labels, ok);
+
+ case Token::RETURN:
+ return ParseReturnStatement(ok);
+
+ case Token::THROW:
+ return ParseThrowStatement(ok);
+
+ case Token::TRY:
+ return ParseTryStatement(ok);
+
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
VariableProxy* Parser::NewUnresolved(const AstRawString* name, int begin_pos,
int end_pos, Variable::Kind kind) {
return scope()->NewUnresolved(factory(), name, begin_pos, end_pos, kind);
@@ -1617,7 +1877,7 @@
{
BlockState block_state(&scope_state_);
block_state.set_start_position(scanner()->location().beg_pos);
- ParserTarget target(this, body);
+ Target target(&this->target_stack_, body);
while (peek() != Token::RBRACE) {
Statement* stat = ParseStatementListItem(CHECK_OK);
@@ -2089,7 +2349,7 @@
BlockState cases_block_state(&scope_state_);
cases_block_state.set_start_position(scanner()->location().beg_pos);
cases_block_state.SetNonlinear();
- ParserTarget target(this, switch_statement);
+ Target target(&this->target_stack_, switch_statement);
Expression* tag_read = factory()->NewVariableProxy(tag_variable);
@@ -2195,7 +2455,7 @@
{
BlockState block_state(&scope_state_);
block_state.set_start_position(scanner()->location().beg_pos);
- ParserTarget target(this, catch_block);
+ Target target(&this->target_stack_, catch_block);
const AstRawString* name = ast_value_factory()->dot_catch_string();
Expression* pattern = nullptr;
@@ -2334,7 +2594,7 @@
DoWhileStatement* loop =
factory()->NewDoWhileStatement(labels, peek_position());
- ParserTarget target(this, loop);
+ Target target(&this->target_stack_, loop);
Expect(Token::DO, CHECK_OK);
Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
@@ -2361,7 +2621,7 @@
// 'while' '(' Expression ')' Statement
WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
- ParserTarget target(this, loop);
+ Target target(&this->target_stack_, loop);
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
@@ -2809,7 +3069,7 @@
bool legacy, bool* ok) {
if (is_strict(language_mode()) || peek() != Token::FUNCTION ||
(legacy && allow_harmony_restrictive_declarations())) {
- return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok);
+ return ParseSubStatement(labels, kDisallowLabelledFunctionStatement, ok);
} else {
if (legacy) {
++use_counts_[v8::Isolate::kLegacyFunctionDeclaration];
@@ -2918,7 +3178,7 @@
Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
ForEachStatement* loop =
factory()->NewForEachStatement(mode, labels, stmt_pos);
- ParserTarget target(this, loop);
+ Target target(&this->target_stack_, loop);
int each_keyword_position = scanner()->location().beg_pos;
@@ -3064,7 +3324,7 @@
ForEachStatement* loop =
factory()->NewForEachStatement(mode, labels, stmt_pos);
- ParserTarget target(this, loop);
+ Target target(&this->target_stack_, loop);
int each_keyword_position = scanner()->location().beg_pos;
@@ -3096,7 +3356,7 @@
// Standard 'for' loop
ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
- ParserTarget target(this, loop);
+ Target target(&this->target_stack_, loop);
// Parsed initializer at this point.
Expect(Token::SEMICOLON, CHECK_OK);
@@ -4555,7 +4815,7 @@
// Parser support
bool Parser::TargetStackContainsLabel(const AstRawString* label) {
- for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
+ for (Target* t = target_stack_; t != NULL; t = t->previous()) {
if (ContainsLabel(t->statement()->labels(), label)) return true;
}
return false;
@@ -4565,7 +4825,7 @@
BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
bool* ok) {
bool anonymous = label == NULL;
- for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
+ for (Target* t = target_stack_; t != NULL; t = t->previous()) {
BreakableStatement* stat = t->statement();
if ((anonymous && stat->is_target_for_anonymous()) ||
(!anonymous && ContainsLabel(stat->labels(), label))) {
@@ -4579,7 +4839,7 @@
IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
bool* ok) {
bool anonymous = label == NULL;
- for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
+ for (Target* t = target_stack_; t != NULL; t = t->previous()) {
IterationStatement* stat = t->statement()->AsIterationStatement();
if (stat == NULL) continue;
@@ -4973,12 +5233,10 @@
scope->SetLanguageMode(mode);
}
-void Parser::SetAsmModule() {
- // Store the usage count; The actual use counter on the isolate is
- // incremented after parsing is done.
- ++use_counts_[v8::Isolate::kUseAsm];
- DCHECK(scope()->is_declaration_scope());
- scope()->AsDeclarationScope()->set_asm_module();
+
+void Parser::RaiseLanguageMode(LanguageMode mode) {
+ LanguageMode old = scope()->language_mode();
+ SetLanguageMode(scope(), old > mode ? old : mode);
}
void Parser::MarkCollectedTailCallExpressions() {
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698