[parser] Refactor of Parse*Statement*, part 5
This patch moves the following parsing methods to ParserBase: - ParseDoExpression - ParseDoWhileStatement - ParseWhileStatement - ParseThrowStatement R=adamk@chromium.org, marja@chromium.org BUG= LOG=N Review-Url: https://codereview.chromium.org/2321103002 Cr-Commit-Position: refs/heads/master@{#39326}
This commit is contained in:
parent
40ba1db51f
commit
bf85ca5315
@ -1198,6 +1198,8 @@ class ParserBase {
|
||||
// Magical syntax support.
|
||||
ExpressionT ParseV8Intrinsic(bool* ok);
|
||||
|
||||
ExpressionT ParseDoExpression(bool* ok);
|
||||
|
||||
StatementT ParseDebuggerStatement(bool* ok);
|
||||
|
||||
StatementT ParseExpressionOrLabelledStatement(
|
||||
@ -1210,6 +1212,11 @@ class ParserBase {
|
||||
StatementT ParseReturnStatement(bool* ok);
|
||||
StatementT ParseWithStatement(ZoneList<const AstRawString*>* labels,
|
||||
bool* ok);
|
||||
StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
|
||||
bool* ok);
|
||||
StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels,
|
||||
bool* ok);
|
||||
StatementT ParseThrowStatement(bool* ok);
|
||||
|
||||
bool IsNextLetKeyword();
|
||||
bool IsTrivialExpression();
|
||||
@ -1759,7 +1766,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
|
||||
case Token::DO:
|
||||
if (allow_harmony_do_expressions()) {
|
||||
BindingPatternUnexpectedToken();
|
||||
return impl()->ParseDoExpression(ok);
|
||||
return ParseDoExpression(ok);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -4053,6 +4060,18 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseV8Intrinsic(
|
||||
return impl()->NewV8Intrinsic(name, args, pos, ok);
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseDoExpression(
|
||||
bool* ok) {
|
||||
// AssignmentExpression ::
|
||||
// do '{' StatementList '}'
|
||||
|
||||
int pos = peek_position();
|
||||
Expect(Token::DO, CHECK_OK);
|
||||
BlockT block = ParseBlock(nullptr, CHECK_OK);
|
||||
return impl()->RewriteDoExpression(block, pos, ok);
|
||||
}
|
||||
|
||||
// Redefinition of CHECK_OK for parsing statements.
|
||||
#undef CHECK_OK
|
||||
#define CHECK_OK CHECK_OK_CUSTOM(NullStatement)
|
||||
@ -4235,9 +4254,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
|
||||
case Token::IF:
|
||||
return ParseIfStatement(labels, ok);
|
||||
case Token::DO:
|
||||
return impl()->ParseDoWhileStatement(labels, ok);
|
||||
return ParseDoWhileStatement(labels, ok);
|
||||
case Token::WHILE:
|
||||
return impl()->ParseWhileStatement(labels, ok);
|
||||
return ParseWhileStatement(labels, ok);
|
||||
case Token::FOR:
|
||||
return impl()->ParseForStatement(labels, ok);
|
||||
case Token::CONTINUE:
|
||||
@ -4300,7 +4319,7 @@ ParserBase<Impl>::ParseStatementAsUnlabelled(
|
||||
case Token::RETURN:
|
||||
return ParseReturnStatement(ok);
|
||||
case Token::THROW:
|
||||
return impl()->ParseThrowStatement(ok);
|
||||
return ParseThrowStatement(ok);
|
||||
case Token::TRY:
|
||||
return impl()->ParseTryStatement(ok);
|
||||
default:
|
||||
@ -4634,6 +4653,71 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWithStatement(
|
||||
return factory()->NewWithStatement(with_scope, expr, body, pos);
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDoWhileStatement(
|
||||
ZoneList<const AstRawString*>* labels, bool* ok) {
|
||||
// DoStatement ::
|
||||
// 'do' Statement 'while' '(' Expression ')' ';'
|
||||
|
||||
auto loop = factory()->NewDoWhileStatement(labels, peek_position());
|
||||
typename Types::Target target(this, loop);
|
||||
|
||||
Expect(Token::DO, CHECK_OK);
|
||||
StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
|
||||
Expect(Token::WHILE, CHECK_OK);
|
||||
Expect(Token::LPAREN, CHECK_OK);
|
||||
|
||||
ExpressionT cond = ParseExpression(true, CHECK_OK);
|
||||
Expect(Token::RPAREN, CHECK_OK);
|
||||
|
||||
// Allow do-statements to be terminated with and without
|
||||
// semi-colons. This allows code such as 'do;while(0)return' to
|
||||
// parse, which would not be the case if we had used the
|
||||
// ExpectSemicolon() functionality here.
|
||||
Check(Token::SEMICOLON);
|
||||
|
||||
loop->Initialize(cond, body);
|
||||
return loop;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWhileStatement(
|
||||
ZoneList<const AstRawString*>* labels, bool* ok) {
|
||||
// WhileStatement ::
|
||||
// 'while' '(' Expression ')' Statement
|
||||
|
||||
auto loop = factory()->NewWhileStatement(labels, peek_position());
|
||||
typename Types::Target target(this, loop);
|
||||
|
||||
Expect(Token::WHILE, CHECK_OK);
|
||||
Expect(Token::LPAREN, CHECK_OK);
|
||||
ExpressionT cond = ParseExpression(true, CHECK_OK);
|
||||
Expect(Token::RPAREN, CHECK_OK);
|
||||
StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
|
||||
|
||||
loop->Initialize(cond, body);
|
||||
return loop;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseThrowStatement(
|
||||
bool* ok) {
|
||||
// ThrowStatement ::
|
||||
// 'throw' Expression ';'
|
||||
|
||||
Expect(Token::THROW, CHECK_OK);
|
||||
int pos = position();
|
||||
if (scanner()->HasAnyLineTerminatorBeforeNext()) {
|
||||
ReportMessage(MessageTemplate::kNewlineAfterThrow);
|
||||
*ok = false;
|
||||
return impl()->NullStatement();
|
||||
}
|
||||
ExpressionT exception = ParseExpression(true, CHECK_OK);
|
||||
ExpectSemicolon(CHECK_OK);
|
||||
|
||||
return impl()->NewThrowStatement(exception, pos);
|
||||
}
|
||||
|
||||
#undef CHECK_OK
|
||||
#undef CHECK_OK_CUSTOM
|
||||
|
||||
|
@ -1702,6 +1702,16 @@ Expression* Parser::RewriteReturn(Expression* return_value, int pos) {
|
||||
return return_value;
|
||||
}
|
||||
|
||||
Expression* Parser::RewriteDoExpression(Block* body, int pos, bool* ok) {
|
||||
Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
|
||||
DoExpression* expr = factory()->NewDoExpression(body, result, pos);
|
||||
if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) {
|
||||
*ok = false;
|
||||
return nullptr;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
Statement* Parser::ParseFunctionDeclaration(bool* ok) {
|
||||
Consume(Token::FUNCTION);
|
||||
int pos = position();
|
||||
@ -1825,26 +1835,6 @@ Statement* Parser::ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
|
||||
return switch_block;
|
||||
}
|
||||
|
||||
|
||||
Statement* Parser::ParseThrowStatement(bool* ok) {
|
||||
// ThrowStatement ::
|
||||
// 'throw' Expression ';'
|
||||
|
||||
Expect(Token::THROW, CHECK_OK);
|
||||
int pos = position();
|
||||
if (scanner()->HasAnyLineTerminatorBeforeNext()) {
|
||||
ReportMessage(MessageTemplate::kNewlineAfterThrow);
|
||||
*ok = false;
|
||||
return NULL;
|
||||
}
|
||||
Expression* exception = ParseExpression(true, CHECK_OK);
|
||||
ExpectSemicolon(CHECK_OK);
|
||||
|
||||
return factory()->NewExpressionStatement(
|
||||
factory()->NewThrow(exception, pos), pos);
|
||||
}
|
||||
|
||||
|
||||
TryStatement* Parser::ParseTryStatement(bool* ok) {
|
||||
// TryStatement ::
|
||||
// 'try' Block Catch
|
||||
@ -2038,53 +2028,6 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
||||
}
|
||||
|
||||
|
||||
DoWhileStatement* Parser::ParseDoWhileStatement(
|
||||
ZoneList<const AstRawString*>* labels, bool* ok) {
|
||||
// DoStatement ::
|
||||
// 'do' Statement 'while' '(' Expression ')' ';'
|
||||
|
||||
DoWhileStatement* loop =
|
||||
factory()->NewDoWhileStatement(labels, peek_position());
|
||||
ParserTarget target(this, loop);
|
||||
|
||||
Expect(Token::DO, CHECK_OK);
|
||||
Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
|
||||
Expect(Token::WHILE, CHECK_OK);
|
||||
Expect(Token::LPAREN, CHECK_OK);
|
||||
|
||||
Expression* cond = ParseExpression(true, CHECK_OK);
|
||||
Expect(Token::RPAREN, CHECK_OK);
|
||||
|
||||
// Allow do-statements to be terminated with and without
|
||||
// semi-colons. This allows code such as 'do;while(0)return' to
|
||||
// parse, which would not be the case if we had used the
|
||||
// ExpectSemicolon() functionality here.
|
||||
if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
|
||||
|
||||
if (loop != NULL) loop->Initialize(cond, body);
|
||||
return loop;
|
||||
}
|
||||
|
||||
|
||||
WhileStatement* Parser::ParseWhileStatement(
|
||||
ZoneList<const AstRawString*>* labels, bool* ok) {
|
||||
// WhileStatement ::
|
||||
// 'while' '(' Expression ')' Statement
|
||||
|
||||
WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
|
||||
ParserTarget target(this, loop);
|
||||
|
||||
Expect(Token::WHILE, CHECK_OK);
|
||||
Expect(Token::LPAREN, CHECK_OK);
|
||||
Expression* cond = ParseExpression(true, CHECK_OK);
|
||||
Expect(Token::RPAREN, CHECK_OK);
|
||||
Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
|
||||
|
||||
if (loop != NULL) loop->Initialize(cond, body);
|
||||
return loop;
|
||||
}
|
||||
|
||||
|
||||
// !%_IsJSReceiver(result = iterator.next()) &&
|
||||
// %ThrowIteratorResultNotAnObject(result)
|
||||
Expression* Parser::BuildIteratorNextResult(Expression* iterator,
|
||||
@ -2959,22 +2902,6 @@ void Parser::DesugarAsyncFunctionBody(Scope* scope, ZoneList<Statement*>* body,
|
||||
scope->set_end_position(scanner()->location().end_pos);
|
||||
}
|
||||
|
||||
DoExpression* Parser::ParseDoExpression(bool* ok) {
|
||||
// AssignmentExpression ::
|
||||
// do '{' StatementList '}'
|
||||
int pos = peek_position();
|
||||
|
||||
Expect(Token::DO, CHECK_OK);
|
||||
Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
|
||||
Block* block = ParseBlock(nullptr, CHECK_OK);
|
||||
DoExpression* expr = factory()->NewDoExpression(block, result, pos);
|
||||
if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) {
|
||||
*ok = false;
|
||||
return nullptr;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
void Parser::ParseArrowFunctionFormalParameterList(
|
||||
ParserFormalParameters* parameters, Expression* expr,
|
||||
const Scanner::Location& params_loc, Scanner::Location* duplicate_loc,
|
||||
|
@ -287,7 +287,6 @@ class Parser : public ParserBase<Parser> {
|
||||
bool is_generator, bool is_async,
|
||||
ZoneList<const AstRawString*>* names, bool* ok);
|
||||
|
||||
DoExpression* ParseDoExpression(bool* ok);
|
||||
Expression* ParseYieldStarExpression(bool* ok);
|
||||
|
||||
class PatternRewriter final : public AstVisitor<PatternRewriter> {
|
||||
@ -374,12 +373,7 @@ class Parser : public ParserBase<Parser> {
|
||||
CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
|
||||
Statement* ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
|
||||
bool* ok);
|
||||
DoWhileStatement* ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
|
||||
bool* ok);
|
||||
WhileStatement* ParseWhileStatement(ZoneList<const AstRawString*>* labels,
|
||||
bool* ok);
|
||||
Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
|
||||
Statement* ParseThrowStatement(bool* ok);
|
||||
Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
|
||||
TryStatement* ParseTryStatement(bool* ok);
|
||||
|
||||
@ -407,7 +401,7 @@ class Parser : public ParserBase<Parser> {
|
||||
FunctionKind kind, FunctionBodyType type,
|
||||
bool accept_IN, int pos, bool* ok);
|
||||
|
||||
void RewriteDoExpression(Expression* expr, bool* ok);
|
||||
Expression* RewriteDoExpression(Block* body, int pos, bool* ok);
|
||||
|
||||
FunctionLiteral* ParseFunctionLiteral(
|
||||
const AstRawString* name, Scanner::Location function_name_location,
|
||||
@ -955,6 +949,11 @@ class Parser : public ParserBase<Parser> {
|
||||
ZoneList<Expression*>* args, int pos,
|
||||
bool* ok);
|
||||
|
||||
V8_INLINE Statement* NewThrowStatement(Expression* exception, int pos) {
|
||||
return factory()->NewExpressionStatement(
|
||||
factory()->NewThrow(exception, pos), pos);
|
||||
}
|
||||
|
||||
V8_INLINE void AddParameterInitializationBlock(
|
||||
const ParserFormalParameters& parameters, ZoneList<Statement*>* body,
|
||||
bool is_async, bool* ok) {
|
||||
|
@ -200,34 +200,6 @@ PreParser::Statement PreParser::ParseSwitchStatement(
|
||||
return Statement::Default();
|
||||
}
|
||||
|
||||
PreParser::Statement PreParser::ParseDoWhileStatement(
|
||||
ZoneList<const AstRawString*>* labels, bool* ok) {
|
||||
// DoStatement ::
|
||||
// 'do' Statement 'while' '(' Expression ')' ';'
|
||||
|
||||
Expect(Token::DO, CHECK_OK);
|
||||
ParseScopedStatement(nullptr, true, CHECK_OK);
|
||||
Expect(Token::WHILE, CHECK_OK);
|
||||
Expect(Token::LPAREN, CHECK_OK);
|
||||
ParseExpression(true, CHECK_OK);
|
||||
Expect(Token::RPAREN, ok);
|
||||
if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
|
||||
return Statement::Default();
|
||||
}
|
||||
|
||||
PreParser::Statement PreParser::ParseWhileStatement(
|
||||
ZoneList<const AstRawString*>* labels, bool* ok) {
|
||||
// WhileStatement ::
|
||||
// 'while' '(' Expression ')' Statement
|
||||
|
||||
Expect(Token::WHILE, CHECK_OK);
|
||||
Expect(Token::LPAREN, CHECK_OK);
|
||||
ParseExpression(true, CHECK_OK);
|
||||
Expect(Token::RPAREN, CHECK_OK);
|
||||
ParseScopedStatement(nullptr, true, ok);
|
||||
return Statement::Default();
|
||||
}
|
||||
|
||||
PreParser::Statement PreParser::ParseForStatement(
|
||||
ZoneList<const AstRawString*>* labels, bool* ok) {
|
||||
// ForStatement ::
|
||||
@ -362,22 +334,6 @@ PreParser::Statement PreParser::ParseForStatement(
|
||||
}
|
||||
|
||||
|
||||
PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
|
||||
// ThrowStatement ::
|
||||
// 'throw' [no line terminator] Expression ';'
|
||||
|
||||
Expect(Token::THROW, CHECK_OK);
|
||||
if (scanner()->HasAnyLineTerminatorBeforeNext()) {
|
||||
ReportMessageAt(scanner()->location(), MessageTemplate::kNewlineAfterThrow);
|
||||
*ok = false;
|
||||
return Statement::Default();
|
||||
}
|
||||
ParseExpression(true, CHECK_OK);
|
||||
ExpectSemicolon(ok);
|
||||
return Statement::Jump();
|
||||
}
|
||||
|
||||
|
||||
PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
|
||||
// TryStatement ::
|
||||
// 'try' Block Catch
|
||||
@ -609,18 +565,6 @@ PreParserExpression PreParser::ParseClassLiteral(
|
||||
return Expression::Default();
|
||||
}
|
||||
|
||||
PreParserExpression PreParser::ParseDoExpression(bool* ok) {
|
||||
// AssignmentExpression ::
|
||||
// do '{' StatementList '}'
|
||||
Expect(Token::DO, CHECK_OK);
|
||||
Expect(Token::LBRACE, CHECK_OK);
|
||||
while (peek() != Token::RBRACE) {
|
||||
ParseStatementListItem(CHECK_OK);
|
||||
}
|
||||
Expect(Token::RBRACE, CHECK_OK);
|
||||
return PreParserExpression::Default();
|
||||
}
|
||||
|
||||
void PreParser::ParseAsyncArrowSingleExpressionBody(PreParserStatementList body,
|
||||
bool accept_IN, int pos,
|
||||
bool* ok) {
|
||||
|
@ -448,6 +448,7 @@ class PreParserStatement {
|
||||
|
||||
PreParserStatementList statements() { return PreParserStatementList(); }
|
||||
void set_scope(Scope* scope) {}
|
||||
void Initialize(PreParserExpression cond, PreParserStatement body) {}
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
@ -640,6 +641,16 @@ class PreParserFactory {
|
||||
return PreParserStatement::Default();
|
||||
}
|
||||
|
||||
PreParserStatement NewDoWhileStatement(ZoneList<const AstRawString*>* labels,
|
||||
int pos) {
|
||||
return PreParserStatement::Default();
|
||||
}
|
||||
|
||||
PreParserStatement NewWhileStatement(ZoneList<const AstRawString*>* labels,
|
||||
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; }
|
||||
@ -805,16 +816,10 @@ class PreParser : public ParserBase<PreParser> {
|
||||
bool default_export, bool* ok);
|
||||
Statement ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
|
||||
bool* ok);
|
||||
Statement ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
|
||||
bool* ok);
|
||||
Statement ParseWhileStatement(ZoneList<const AstRawString*>* labels,
|
||||
bool* ok);
|
||||
Statement ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
|
||||
Statement ParseThrowStatement(bool* ok);
|
||||
Statement ParseTryStatement(bool* ok);
|
||||
Expression ParseConditionalExpression(bool accept_IN, bool* ok);
|
||||
Expression ParseObjectLiteral(bool* ok);
|
||||
Expression ParseDoExpression(bool* ok);
|
||||
|
||||
V8_INLINE PreParserStatementList ParseEagerFunctionBody(
|
||||
PreParserIdentifier function_name, int pos,
|
||||
@ -929,6 +934,11 @@ class PreParser : public ParserBase<PreParser> {
|
||||
return return_value;
|
||||
}
|
||||
|
||||
V8_INLINE PreParserExpression RewriteDoExpression(PreParserStatement body,
|
||||
int pos, bool* ok) {
|
||||
return PreParserExpression::Default();
|
||||
}
|
||||
|
||||
// TODO(nikolaos): The preparser currently does not keep track of labels
|
||||
// and targets.
|
||||
V8_INLINE PreParserStatement LookupBreakTarget(PreParserIdentifier label,
|
||||
@ -1258,6 +1268,11 @@ class PreParser : public ParserBase<PreParser> {
|
||||
return PreParserExpression::Default();
|
||||
}
|
||||
|
||||
V8_INLINE PreParserStatement NewThrowStatement(PreParserExpression exception,
|
||||
int pos) {
|
||||
return PreParserStatement::Jump();
|
||||
}
|
||||
|
||||
V8_INLINE void AddParameterInitializationBlock(
|
||||
const PreParserFormalParameters& parameters, PreParserStatementList body,
|
||||
bool is_async, bool* ok) {}
|
||||
|
@ -35,9 +35,9 @@ bytecode array length: 13
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 55 S> */ B(LdaSmi), U8(100),
|
||||
B(Star), R(1),
|
||||
/* 42 S> */ B(LdrUndefined), R(0),
|
||||
B(Ldar), R(0),
|
||||
B(Star), R(0),
|
||||
/* 42 S> */ B(LdrUndefined), R(1),
|
||||
B(Ldar), R(1),
|
||||
B(Star), R(2),
|
||||
/* 63 S> */ B(Nop),
|
||||
/* 73 S> */ B(Return),
|
||||
|
Loading…
Reference in New Issue
Block a user