Commit bf85ca53 authored by nikolaos's avatar nikolaos Committed by Commit bot

[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}
parent 40ba1db5
......@@ -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),
......
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