Commit e7b1908d authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

Reland "[parser] Restructure Binary expression parsing"++

Additionally the CL outlines ParseFunctionExpression from
ParseMemberExpression, drops IsTrivialExpression, and inlines
ParsePrimaryExpression. This allows the parser to be turned into a bottom-up
parser through inlining.

Change-Id: Id9247dfb1cc7505ee8398b371d4727316ec8f332
Reviewed-on: https://chromium-review.googlesource.com/c/1270920
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56490}
parent db70e0b3
...@@ -1079,7 +1079,7 @@ class ParserBase { ...@@ -1079,7 +1079,7 @@ class ParserBase {
ExpressionT ParseRegExpLiteral(bool* ok); ExpressionT ParseRegExpLiteral(bool* ok);
ExpressionT ParseBindingPattern(bool* ok); ExpressionT ParseBindingPattern(bool* ok);
ExpressionT ParsePrimaryExpression(bool* is_async, bool* ok); V8_INLINE ExpressionT ParsePrimaryExpression(bool* is_async, bool* ok);
// Use when parsing an expression that is known to not be a pattern or part // Use when parsing an expression that is known to not be a pattern or part
// of a pattern. // of a pattern.
...@@ -1128,7 +1128,10 @@ class ParserBase { ...@@ -1128,7 +1128,10 @@ class ParserBase {
V8_INLINE ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok); V8_INLINE ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
ExpressionT ParseConditionalContinuation(ExpressionT expression, ExpressionT ParseConditionalContinuation(ExpressionT expression,
bool accept_IN, int pos, bool* ok); bool accept_IN, int pos, bool* ok);
ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok); ExpressionT ParseBinaryContinuation(ExpressionT x, int prec, int prec1,
bool accept_IN, bool* ok);
V8_INLINE ExpressionT ParseBinaryExpression(int prec, bool accept_IN,
bool* ok);
ExpressionT ParseUnaryOpExpression(bool* ok); ExpressionT ParseUnaryOpExpression(bool* ok);
ExpressionT ParseAwaitExpression(bool* ok); ExpressionT ParseAwaitExpression(bool* ok);
ExpressionT ParsePrefixExpression(bool* ok); ExpressionT ParsePrefixExpression(bool* ok);
...@@ -1139,6 +1142,7 @@ class ParserBase { ...@@ -1139,6 +1142,7 @@ class ParserBase {
bool* ok); bool* ok);
V8_INLINE ExpressionT ParseMemberWithNewPrefixesExpression(bool* is_async, V8_INLINE ExpressionT ParseMemberWithNewPrefixesExpression(bool* is_async,
bool* ok); bool* ok);
ExpressionT ParseFunctionExpression(bool* ok);
V8_INLINE ExpressionT ParseMemberExpression(bool* is_async, bool* ok); V8_INLINE ExpressionT ParseMemberExpression(bool* is_async, bool* ok);
V8_INLINE ExpressionT ParseMemberExpressionContinuation( V8_INLINE ExpressionT ParseMemberExpressionContinuation(
ExpressionT expression, bool* is_async, bool* ok); ExpressionT expression, bool* is_async, bool* ok);
...@@ -1295,7 +1299,6 @@ class ParserBase { ...@@ -1295,7 +1299,6 @@ class ParserBase {
bool* ok); bool* ok);
bool IsNextLetKeyword(); bool IsNextLetKeyword();
bool IsTrivialExpression();
// Checks if the expression is a valid reference expression (e.g., on the // Checks if the expression is a valid reference expression (e.g., on the
// left-hand side of assignments). Although ruled out by ECMA as early errors, // left-hand side of assignments). Although ruled out by ECMA as early errors,
...@@ -2869,12 +2872,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) { ...@@ -2869,12 +2872,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
// Parse a simple, faster sub-grammar (primary expression) if it's evident // Parse a simple, faster sub-grammar (primary expression) if it's evident
// that we have only a trivial expression to parse. // that we have only a trivial expression to parse.
ExpressionT expression; ExpressionT expression = ParseConditionalExpression(accept_IN, CHECK_OK);
if (IsTrivialExpression()) {
expression = ParsePrimaryExpression(&is_async, CHECK_OK);
} else {
expression = ParseConditionalExpression(accept_IN, CHECK_OK);
}
if (is_async && impl()->IsIdentifier(expression) && peek_any_identifier() && if (is_async && impl()->IsIdentifier(expression) && peek_any_identifier() &&
PeekAhead() == Token::ARROW) { PeekAhead() == Token::ARROW) {
...@@ -3133,12 +3131,11 @@ ParserBase<Impl>::ParseConditionalContinuation(ExpressionT expression, ...@@ -3133,12 +3131,11 @@ ParserBase<Impl>::ParseConditionalContinuation(ExpressionT expression,
// Precedence >= 4 // Precedence >= 4
template <typename Impl> template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression( typename ParserBase<Impl>::ExpressionT
int prec, bool accept_IN, bool* ok) { ParserBase<Impl>::ParseBinaryContinuation(ExpressionT x, int prec, int prec1,
DCHECK_GE(prec, 4); bool accept_IN, bool* ok) {
SourceRange right_range; SourceRange right_range;
ExpressionT x = ParseUnaryExpression(CHECK_OK); do {
for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
// prec1 >= 4 // prec1 >= 4
while (Precedence(peek(), accept_IN) == prec1) { while (Precedence(peek(), accept_IN) == prec1) {
ValidateExpression(CHECK_OK); ValidateExpression(CHECK_OK);
...@@ -3181,6 +3178,21 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression( ...@@ -3181,6 +3178,21 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
} }
} }
} }
--prec1;
} while (prec1 >= prec);
return x;
}
// Precedence >= 4
template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
int prec, bool accept_IN, bool* ok) {
DCHECK_GE(prec, 4);
ExpressionT x = ParseUnaryExpression(CHECK_OK);
int prec1 = Precedence(peek(), accept_IN);
if (prec1 >= prec) {
return ParseBinaryContinuation(x, prec, prec1, accept_IN, CHECK_OK);
} }
return x; return x;
} }
...@@ -3521,6 +3533,47 @@ ParserBase<Impl>::ParseMemberWithNewPrefixesExpression(bool* is_async, ...@@ -3521,6 +3533,47 @@ ParserBase<Impl>::ParseMemberWithNewPrefixesExpression(bool* is_async,
: ParseMemberExpression(is_async, ok); : ParseMemberExpression(is_async, ok);
} }
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseFunctionExpression(bool* ok) {
BindingPatternUnexpectedToken();
ArrowFormalParametersUnexpectedToken();
Consume(Token::FUNCTION);
int function_token_position = position();
FunctionKind function_kind = Check(Token::MUL)
? FunctionKind::kGeneratorFunction
: FunctionKind::kNormalFunction;
IdentifierT name = impl()->NullIdentifier();
bool is_strict_reserved_name = false;
Scanner::Location function_name_location = Scanner::Location::invalid();
FunctionLiteral::FunctionType function_type =
FunctionLiteral::kAnonymousExpression;
if (impl()->ParsingDynamicFunctionDeclaration()) {
// We don't want dynamic functions to actually declare their name
// "anonymous". We just want that name in the toString().
if (stack_overflow()) {
*ok = false;
return impl()->NullExpression();
}
Consume(Token::IDENTIFIER);
DCHECK(scanner()->CurrentMatchesContextual(Token::ANONYMOUS));
} else if (peek_any_identifier()) {
bool is_await = false;
name = ParseIdentifierOrStrictReservedWord(
function_kind, &is_strict_reserved_name, &is_await, CHECK_OK);
function_name_location = scanner()->location();
function_type = FunctionLiteral::kNamedExpression;
}
return impl()->ParseFunctionLiteral(
name, function_name_location,
is_strict_reserved_name ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown,
function_kind, function_token_position, function_type, language_mode(),
nullptr, CHECK_OK);
}
template <typename Impl> template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression( typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression(
bool* is_async, bool* ok) { bool* is_async, bool* ok) {
...@@ -3539,42 +3592,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression( ...@@ -3539,42 +3592,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression(
// Parse the initial primary or function expression. // Parse the initial primary or function expression.
ExpressionT result; ExpressionT result;
if (peek() == Token::FUNCTION) { if (peek() == Token::FUNCTION) {
BindingPatternUnexpectedToken(); result = ParseFunctionExpression(CHECK_OK);
ArrowFormalParametersUnexpectedToken();
Consume(Token::FUNCTION);
int function_token_position = position();
FunctionKind function_kind = Check(Token::MUL)
? FunctionKind::kGeneratorFunction
: FunctionKind::kNormalFunction;
IdentifierT name = impl()->NullIdentifier();
bool is_strict_reserved_name = false;
Scanner::Location function_name_location = Scanner::Location::invalid();
FunctionLiteral::FunctionType function_type =
FunctionLiteral::kAnonymousExpression;
if (impl()->ParsingDynamicFunctionDeclaration()) {
// We don't want dynamic functions to actually declare their name
// "anonymous". We just want that name in the toString().
if (stack_overflow()) {
*ok = false;
return impl()->NullExpression();
}
Consume(Token::IDENTIFIER);
DCHECK(scanner()->CurrentMatchesContextual(Token::ANONYMOUS));
} else if (peek_any_identifier()) {
bool is_await = false;
name = ParseIdentifierOrStrictReservedWord(
function_kind, &is_strict_reserved_name, &is_await, CHECK_OK);
function_name_location = scanner()->location();
function_type = FunctionLiteral::kNamedExpression;
}
result = impl()->ParseFunctionLiteral(
name, function_name_location,
is_strict_reserved_name ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown,
function_kind, function_token_position, function_type, language_mode(),
nullptr, CHECK_OK);
} else if (peek() == Token::SUPER) { } else if (peek() == Token::SUPER) {
const bool is_new = false; const bool is_new = false;
result = ParseSuperExpression(is_new, CHECK_OK); result = ParseSuperExpression(is_new, CHECK_OK);
...@@ -4340,21 +4358,6 @@ bool ParserBase<Impl>::IsNextLetKeyword() { ...@@ -4340,21 +4358,6 @@ bool ParserBase<Impl>::IsNextLetKeyword() {
} }
} }
template <typename Impl>
bool ParserBase<Impl>::IsTrivialExpression() {
if (Token::IsTrivialExpressionToken(peek())) {
// PeekAhead() may not always be called, so we only call it after checking
// peek().
Token::Value peek_ahead = PeekAhead();
if (peek_ahead == Token::COMMA || peek_ahead == Token::RPAREN ||
peek_ahead == Token::SEMICOLON || peek_ahead == Token::RBRACK ||
Token::IsAssignmentOp(peek_ahead)) {
return true;
}
}
return false;
}
template <typename Impl> template <typename Impl>
typename ParserBase<Impl>::ExpressionT typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseArrowFunctionLiteral( ParserBase<Impl>::ParseArrowFunctionLiteral(
......
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