Commit 40ba1db5 authored by nikolaos's avatar nikolaos Committed by Commit bot

[parser] Refactor of Parse*Statement*, part 4

This patch moves the following parsing methods to ParserBase:

- ParseExpressionOrLabelledStatement
- ParseIfStatement
- ParseContinueStatement
- ParseBreakStatement
- ParseReturnStatement
- ParseWithStatement

R=adamk@chromium.org, marja@chromium.org
BUG=
LOG=N

Review-Url: https://codereview.chromium.org/2323763002
Cr-Commit-Position: refs/heads/master@{#39325}
parent b4c9706e
This diff is collapsed.
This diff is collapsed.
......@@ -157,6 +157,8 @@ struct ParserTypes<Parser> {
typedef v8::internal::Statement* Statement;
typedef ZoneList<v8::internal::Statement*>* StatementList;
typedef v8::internal::Block* Block;
typedef v8::internal::BreakableStatement* BreakableStatementT;
typedef v8::internal::IterationStatement* IterationStatementT;
// For constructing objects returned by the traversing functions.
typedef AstNodeFactory Factory;
......@@ -203,12 +205,6 @@ class Parser : public ParserBase<Parser> {
enum class FunctionBodyType { kNormal, kSingleExpression };
DeclarationScope* GetDeclarationScope() const {
return scope()->GetDeclarationScope();
}
DeclarationScope* GetClosureScope() const {
return scope()->GetClosureScope();
}
Variable* NewTemporary(const AstRawString* name) {
return scope()->NewTemporary(name);
}
......@@ -280,6 +276,11 @@ class Parser : public ParserBase<Parser> {
Block* block, const DeclarationDescriptor* declaration_descriptor,
const DeclarationParsingResult::Declaration* declaration,
ZoneList<const AstRawString*>* names, bool* ok);
ZoneList<const AstRawString*>* DeclareLabel(
ZoneList<const AstRawString*>* labels, VariableProxy* expr, bool* ok);
bool ContainsLabel(ZoneList<const AstRawString*>* labels,
const AstRawString* label);
Expression* RewriteReturn(Expression* return_value, int pos);
Statement* DeclareFunction(const AstRawString* variable_name,
FunctionLiteral* function, int pos,
......@@ -370,17 +371,6 @@ class Parser : public ParserBase<Parser> {
DEFINE_AST_VISITOR_MEMBERS_WITHOUT_STACKOVERFLOW()
};
Statement* ParseExpressionOrLabelledStatement(
ZoneList<const AstRawString*>* labels,
AllowLabelledFunctionStatement allow_function, bool* ok);
IfStatement* ParseIfStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement* ParseContinueStatement(bool* ok);
Statement* ParseBreakStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement* ParseReturnStatement(bool* ok);
Statement* ParseWithStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
Statement* ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
......@@ -641,9 +631,13 @@ class Parser : public ParserBase<Parser> {
property->obj()->AsVariableProxy()->is_this();
}
// This returns true if the expression is an indentifier (wrapped
// inside a variable proxy). We exclude the case of 'this', which
// has been converted to a variable proxy.
V8_INLINE static bool IsIdentifier(Expression* expression) {
DCHECK_NOT_NULL(expression);
VariableProxy* operand = expression->AsVariableProxy();
return operand != NULL && !operand->is_this();
return operand != nullptr && !operand->is_this();
}
V8_INLINE static const AstRawString* AsIdentifier(Expression* expression) {
......@@ -651,6 +645,10 @@ class Parser : public ParserBase<Parser> {
return expression->AsVariableProxy()->raw_name();
}
V8_INLINE VariableProxy* AsIdentifierExpression(Expression* expression) {
return expression->AsVariableProxy();
}
V8_INLINE bool IsPrototype(const AstRawString* identifier) const {
return identifier == ast_value_factory()->prototype_string();
}
......@@ -670,6 +668,13 @@ class Parser : public ParserBase<Parser> {
return ObjectLiteral::IsBoilerplateProperty(property);
}
V8_INLINE bool IsNative(Expression* expr) const {
DCHECK_NOT_NULL(expr);
return expr->IsVariableProxy() &&
expr->AsVariableProxy()->raw_name() ==
ast_value_factory()->native_string();
}
V8_INLINE static bool IsArrayIndex(const AstRawString* string,
uint32_t* index) {
return string->AsArrayIndex(index);
......@@ -835,6 +840,9 @@ class Parser : public ParserBase<Parser> {
// "null" return type creators.
V8_INLINE static const AstRawString* EmptyIdentifier() { return nullptr; }
V8_INLINE static bool IsEmptyIdentifier(const AstRawString* name) {
return name == nullptr;
}
V8_INLINE static Expression* EmptyExpression() { return nullptr; }
V8_INLINE static Literal* EmptyLiteral() { return nullptr; }
V8_INLINE static ObjectLiteralProperty* EmptyObjectLiteralProperty() {
......@@ -862,8 +870,10 @@ class Parser : public ParserBase<Parser> {
return stmts == nullptr;
}
V8_INLINE static Statement* NullStatement() { return nullptr; }
V8_INLINE bool IsNullOrEmptyStatement(Statement* stmt) {
return stmt == nullptr || stmt->IsEmpty();
V8_INLINE bool IsNullStatement(Statement* stmt) { return stmt == nullptr; }
V8_INLINE bool IsEmptyStatement(Statement* stmt) {
DCHECK_NOT_NULL(stmt);
return stmt->IsEmpty();
}
// Non-NULL empty string.
......
......@@ -164,175 +164,6 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
return ParseHoistableDeclaration(pos, flags, nullptr, false, ok);
}
PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(
ZoneList<const AstRawString*>* names,
AllowLabelledFunctionStatement allow_function, bool* ok) {
// ExpressionStatement | LabelledStatement ::
// Expression ';'
// Identifier ':' Statement
switch (peek()) {
case Token::FUNCTION:
case Token::LBRACE:
UNREACHABLE(); // Always handled by the callers.
case Token::CLASS:
ReportUnexpectedToken(Next());
*ok = false;
return Statement::Default();
default:
break;
}
bool starts_with_identifier = peek_any_identifier();
ExpressionClassifier classifier(this);
Expression expr = ParseExpressionCoverGrammar(true, CHECK_OK);
ValidateExpression(CHECK_OK);
// Even if the expression starts with an identifier, it is not necessarily an
// identifier. For example, "foo + bar" starts with an identifier but is not
// an identifier.
if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
// Expression is a single identifier, and not, e.g., a parenthesized
// identifier.
DCHECK(!expr.AsIdentifier().IsEnum());
DCHECK(!parsing_module_ || !expr.AsIdentifier().IsAwait());
DCHECK(is_sloppy(language_mode()) ||
!IsFutureStrictReserved(expr.AsIdentifier()));
Consume(Token::COLON);
// ES#sec-labelled-function-declarations Labelled Function Declarations
if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
if (allow_function == kAllowLabelledFunctionStatement) {
return ParseFunctionDeclaration(ok);
} else {
return ParseScopedStatement(names, true, ok);
}
}
Statement statement =
ParseStatement(nullptr, kDisallowLabelledFunctionStatement, ok);
return statement.IsJumpStatement() ? Statement::Default() : statement;
// Preparsing is disabled for extensions (because the extension details
// aren't passed to lazily compiled functions), so we don't
// accept "native function" in the preparser.
}
// Parsed expression statement.
ExpectSemicolon(CHECK_OK);
return Statement::ExpressionStatement(expr);
}
PreParser::Statement PreParser::ParseIfStatement(
ZoneList<const AstRawString*>* labels, bool* ok) {
// IfStatement ::
// 'if' '(' Expression ')' Statement ('else' Statement)?
Expect(Token::IF, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
Statement stat = ParseScopedStatement(labels, false, CHECK_OK);
if (peek() == Token::ELSE) {
Next();
Statement else_stat = ParseScopedStatement(labels, false, CHECK_OK);
stat = (stat.IsJumpStatement() && else_stat.IsJumpStatement()) ?
Statement::Jump() : Statement::Default();
} else {
stat = Statement::Default();
}
return stat;
}
PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
// ContinueStatement ::
// 'continue' [no line terminator] Identifier? ';'
Expect(Token::CONTINUE, CHECK_OK);
Token::Value tok = peek();
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON &&
tok != Token::RBRACE &&
tok != Token::EOS) {
// ECMA allows "eval" or "arguments" as labels even in strict mode.
ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
}
ExpectSemicolon(CHECK_OK);
return Statement::Jump();
}
PreParser::Statement PreParser::ParseBreakStatement(
ZoneList<const AstRawString*>* labels, bool* ok) {
// BreakStatement ::
// 'break' [no line terminator] Identifier? ';'
Expect(Token::BREAK, CHECK_OK);
Token::Value tok = peek();
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON &&
tok != Token::RBRACE &&
tok != Token::EOS) {
// ECMA allows "eval" or "arguments" as labels even in strict mode.
ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
}
ExpectSemicolon(CHECK_OK);
return Statement::Jump();
}
PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
// ReturnStatement ::
// 'return' [no line terminator] Expression? ';'
// Consume the return token. It is necessary to do before
// reporting any errors on it, because of the way errors are
// reported (underlining).
Expect(Token::RETURN, CHECK_OK);
// An ECMAScript program is considered syntactically incorrect if it
// contains a return statement that is not within the body of a
// function. See ECMA-262, section 12.9, page 67.
// This is not handled during preparsing.
Token::Value tok = peek();
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON &&
tok != Token::RBRACE &&
tok != Token::EOS) {
// Because of the return code rewriting that happens in case of a subclass
// constructor we don't want to accept tail calls, therefore we don't set
// ReturnExprScope to kInsideValidReturnStatement here.
ReturnExprContext return_expr_context =
IsSubclassConstructor(function_state_->kind())
? function_state_->return_expr_context()
: ReturnExprContext::kInsideValidReturnStatement;
ReturnExprScope maybe_allow_tail_calls(function_state_,
return_expr_context);
ParseExpression(true, CHECK_OK);
}
ExpectSemicolon(CHECK_OK);
return Statement::Jump();
}
PreParser::Statement PreParser::ParseWithStatement(
ZoneList<const AstRawString*>* labels, bool* ok) {
// WithStatement ::
// 'with' '(' Expression ')' Statement
Expect(Token::WITH, CHECK_OK);
if (is_strict(language_mode())) {
ReportMessageAt(scanner()->location(), MessageTemplate::kStrictWith);
*ok = false;
return Statement::Default();
}
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
Scope* with_scope = NewScope(WITH_SCOPE);
BlockState block_state(&scope_state_, with_scope);
ParseScopedStatement(labels, true, CHECK_OK);
return Statement::Default();
}
PreParser::Statement PreParser::ParseSwitchStatement(
ZoneList<const AstRawString*>* labels, bool* ok) {
// SwitchStatement ::
......
......@@ -25,6 +25,9 @@ class PreParserIdentifier {
static PreParserIdentifier Default() {
return PreParserIdentifier(kUnknownIdentifier);
}
static PreParserIdentifier Empty() {
return PreParserIdentifier(kEmptyIdentifier);
}
static PreParserIdentifier Eval() {
return PreParserIdentifier(kEvalIdentifier);
}
......@@ -64,6 +67,7 @@ class PreParserIdentifier {
static PreParserIdentifier Async() {
return PreParserIdentifier(kAsyncIdentifier);
}
bool IsEmpty() const { return type_ == kEmptyIdentifier; }
bool IsEval() const { return type_ == kEvalIdentifier; }
bool IsArguments() const { return type_ == kArgumentsIdentifier; }
bool IsEvalOrArguments() const { return IsEval() || IsArguments(); }
......@@ -91,6 +95,7 @@ class PreParserIdentifier {
private:
enum Type {
kEmptyIdentifier,
kUnknownIdentifier,
kFutureReservedIdentifier,
kFutureStrictReservedIdentifier,
......@@ -389,6 +394,14 @@ class PreParserStatement {
return PreParserStatement(kUnknownStatement);
}
static PreParserStatement Null() {
return PreParserStatement(kNullStatement);
}
static PreParserStatement Empty() {
return PreParserStatement(kEmptyStatement);
}
static PreParserStatement Jump() {
return PreParserStatement(kJumpStatement);
}
......@@ -425,6 +438,10 @@ class PreParserStatement {
return code_ == kJumpStatement;
}
bool IsNullStatement() { return code_ == kNullStatement; }
bool IsEmptyStatement() { return code_ == kEmptyStatement; }
// Dummy implementation for making statement->somefunc() work in both Parser
// and PreParser.
PreParserStatement* operator->() { return this; }
......@@ -434,6 +451,8 @@ class PreParserStatement {
private:
enum Type {
kNullStatement,
kEmptyStatement,
kUnknownStatement,
kJumpStatement,
kStringLiteralExpressionStatement,
......@@ -559,7 +578,7 @@ class PreParserFactory {
}
PreParserStatement NewReturnStatement(PreParserExpression expression,
int pos) {
return PreParserStatement::Default();
return PreParserStatement::Jump();
}
PreParserExpression NewFunctionLiteral(
PreParserIdentifier name, Scope* scope, PreParserStatementList body,
......@@ -595,6 +614,32 @@ class PreParserFactory {
return PreParserStatement::Default();
}
PreParserStatement NewExpressionStatement(PreParserExpression expr, int pos) {
return PreParserStatement::ExpressionStatement(expr);
}
PreParserStatement NewIfStatement(PreParserExpression condition,
PreParserStatement then_statement,
PreParserStatement else_statement,
int pos) {
// This must return a jump statement iff both clauses are jump statements.
return else_statement.IsJumpStatement() ? then_statement : else_statement;
}
PreParserStatement NewBreakStatement(PreParserStatement target, int pos) {
return PreParserStatement::Jump();
}
PreParserStatement NewContinueStatement(PreParserStatement target, int pos) {
return PreParserStatement::Jump();
}
PreParserStatement NewWithStatement(Scope* scope,
PreParserExpression expression,
PreParserStatement statement, int pos) {
return PreParserStatement::Default();
}
// Return the object itself as AstVisitor and implement the needed
// dummy method right in this class.
PreParserFactory* visitor() { return this; }
......@@ -648,6 +693,8 @@ struct ParserTypes<PreParser> {
typedef PreParserStatement Statement;
typedef PreParserStatementList StatementList;
typedef PreParserStatement Block;
typedef PreParserStatement BreakableStatementT;
typedef PreParserStatement IterationStatementT;
// For constructing objects returned by the traversing functions.
typedef PreParserFactory Factory;
......@@ -756,15 +803,6 @@ class PreParser : public ParserBase<PreParser> {
Expression ParseAsyncFunctionExpression(bool* ok);
Statement ParseClassDeclaration(ZoneList<const AstRawString*>* names,
bool default_export, bool* ok);
Statement ParseExpressionOrLabelledStatement(
ZoneList<const AstRawString*>* names,
AllowLabelledFunctionStatement allow_function, bool* ok);
Statement ParseIfStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement ParseContinueStatement(bool* ok);
Statement ParseBreakStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement ParseReturnStatement(bool* ok);
Statement ParseWithStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
......@@ -865,6 +903,42 @@ class PreParser : public ParserBase<PreParser> {
const DeclarationDescriptor* declaration_descriptor,
const DeclarationParsingResult::Declaration* declaration,
ZoneList<const AstRawString*>* names, bool* ok) {}
V8_INLINE ZoneList<const AstRawString*>* DeclareLabel(
ZoneList<const AstRawString*>* labels, PreParserExpression expr,
bool* ok) {
DCHECK(!expr.AsIdentifier().IsEnum());
DCHECK(!parsing_module_ || !expr.AsIdentifier().IsAwait());
DCHECK(is_sloppy(language_mode()) ||
!IsFutureStrictReserved(expr.AsIdentifier()));
return labels;
}
V8_INLINE PreParserStatement ParseNativeDeclaration(bool* ok) {
UNREACHABLE();
return PreParserStatement::Default();
}
// TODO(nikolaos): The preparser currently does not keep track of labels.
V8_INLINE bool ContainsLabel(ZoneList<const AstRawString*>* labels,
PreParserIdentifier label) {
return false;
}
V8_INLINE PreParserExpression RewriteReturn(PreParserExpression return_value,
int pos) {
return return_value;
}
// TODO(nikolaos): The preparser currently does not keep track of labels
// and targets.
V8_INLINE PreParserStatement LookupBreakTarget(PreParserIdentifier label,
bool* ok) {
return PreParserStatement::Default();
}
V8_INLINE PreParserStatement LookupContinueTarget(PreParserIdentifier label,
bool* ok) {
return PreParserStatement::Default();
}
V8_INLINE PreParserStatement DeclareFunction(
PreParserIdentifier variable_name, PreParserExpression function, int pos,
......@@ -917,6 +991,11 @@ class PreParser : public ParserBase<PreParser> {
return expression.AsIdentifier();
}
V8_INLINE static PreParserExpression AsIdentifierExpression(
PreParserExpression expression) {
return expression;
}
V8_INLINE bool IsPrototype(PreParserIdentifier identifier) const {
return identifier.IsPrototype();
}
......@@ -934,6 +1013,14 @@ class PreParser : public ParserBase<PreParser> {
return false;
}
V8_INLINE bool IsNative(PreParserExpression expr) const {
// Preparsing is disabled for extensions (because the extension
// details aren't passed to lazily compiled functions), so we
// don't accept "native function" in the preparser and there is
// no need to keep track of "native".
return false;
}
V8_INLINE static bool IsArrayIndex(PreParserIdentifier string,
uint32_t* index) {
return false;
......@@ -1021,14 +1108,17 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE void ReportMessageAt(Scanner::Location source_location,
MessageTemplate::Template message,
const AstRawString* arg,
PreParserIdentifier arg,
ParseErrorType error_type = kSyntaxError) {
UNREACHABLE();
}
// "null" return type creators.
V8_INLINE static PreParserIdentifier EmptyIdentifier() {
return PreParserIdentifier::Default();
return PreParserIdentifier::Empty();
}
V8_INLINE static bool IsEmptyIdentifier(PreParserIdentifier name) {
return name.IsEmpty();
}
V8_INLINE static PreParserExpression EmptyExpression() {
return PreParserExpression::Empty();
......@@ -1070,9 +1160,12 @@ class PreParser : public ParserBase<PreParser> {
return PreParserStatement::Default();
}
V8_INLINE bool IsNullOrEmptyStatement(PreParserStatement stmt) {
// TODO(nikolaos): See if this needs to be consistent for the preparser.
return false;
V8_INLINE bool IsNullStatement(PreParserStatement stmt) {
return stmt.IsNullStatement();
}
V8_INLINE bool IsEmptyStatement(PreParserStatement stmt) {
return stmt.IsEmptyStatement();
}
V8_INLINE static PreParserStatement NullBlock() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment