[parser] Track accept_IN with scopes and a different precendece table
Change-Id: I6da7a3cbf681a5ae691fe0aee2e69536a84f0df0 Reviewed-on: https://chromium-review.googlesource.com/c/1329174 Commit-Queue: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#57400}
This commit is contained in:
parent
1e9ead8ac6
commit
d0049fb7ac
@ -997,7 +997,7 @@ class ParserBase {
|
||||
// corresponds to what's inside the parentheses generated by the symbol
|
||||
// "CoverParenthesizedExpressionAndArrowParameterList" in the ES 2017
|
||||
// specification).
|
||||
ExpressionT ParseExpressionCoverGrammar(bool accept_IN);
|
||||
ExpressionT ParseExpressionCoverGrammar();
|
||||
ExpressionT ParseArrowFormalsWithRest(ExpressionListT* list);
|
||||
|
||||
ExpressionT ParseArrayLiteral();
|
||||
@ -1027,14 +1027,12 @@ class ParserBase {
|
||||
ParseArguments(args, has_spread, false);
|
||||
}
|
||||
|
||||
ExpressionT ParseAssignmentExpression(bool accept_IN);
|
||||
ExpressionT ParseYieldExpression(bool accept_IN);
|
||||
V8_INLINE ExpressionT ParseConditionalExpression(bool accept_IN);
|
||||
ExpressionT ParseConditionalContinuation(ExpressionT expression,
|
||||
bool accept_IN, int pos);
|
||||
ExpressionT ParseBinaryContinuation(ExpressionT x, int prec, int prec1,
|
||||
bool accept_IN);
|
||||
V8_INLINE ExpressionT ParseBinaryExpression(int prec, bool accept_IN);
|
||||
ExpressionT ParseAssignmentExpression();
|
||||
ExpressionT ParseYieldExpression();
|
||||
V8_INLINE ExpressionT ParseConditionalExpression();
|
||||
ExpressionT ParseConditionalContinuation(ExpressionT expression, int pos);
|
||||
ExpressionT ParseBinaryContinuation(ExpressionT x, int prec, int prec1);
|
||||
V8_INLINE ExpressionT ParseBinaryExpression(int prec);
|
||||
ExpressionT ParseUnaryOpExpression();
|
||||
ExpressionT ParseAwaitExpression();
|
||||
ExpressionT ParsePrefixExpression();
|
||||
@ -1057,8 +1055,7 @@ class ParserBase {
|
||||
// queue in the parent function state, prior to parsing of formal parameters.
|
||||
// If the arrow function is lazy, any items added during formal parameter
|
||||
// parsing are removed from the queue.
|
||||
ExpressionT ParseArrowFunctionLiteral(bool accept_IN,
|
||||
const FormalParametersT& parameters,
|
||||
ExpressionT ParseArrowFunctionLiteral(const FormalParametersT& parameters,
|
||||
int rewritable_length);
|
||||
void ParseAsyncFunctionBody(Scope* scope, StatementListT* body);
|
||||
ExpressionT ParseAsyncFunctionLiteral();
|
||||
@ -1099,7 +1096,7 @@ class ParserBase {
|
||||
int pos, const FormalParametersT& parameters,
|
||||
FunctionKind kind,
|
||||
FunctionLiteral::FunctionType function_type,
|
||||
FunctionBodyType body_type, bool accept_IN);
|
||||
FunctionBodyType body_type);
|
||||
|
||||
// Under some circumstances, we allow preparsing to abort if the preparsed
|
||||
// function is "long and trivial", and fully parse instead. Our current
|
||||
@ -1389,6 +1386,20 @@ class ParserBase {
|
||||
classifier_ = previous;
|
||||
}
|
||||
|
||||
class AcceptINScope final {
|
||||
public:
|
||||
AcceptINScope(ParserBase* parser, bool accept_IN)
|
||||
: parser_(parser), previous_accept_IN_(parser->accept_IN_) {
|
||||
parser_->accept_IN_ = accept_IN;
|
||||
}
|
||||
|
||||
~AcceptINScope() { parser_->accept_IN_ = previous_accept_IN_; }
|
||||
|
||||
private:
|
||||
ParserBase* parser_;
|
||||
bool previous_accept_IN_;
|
||||
};
|
||||
|
||||
V8_INLINE void AccumulateNonBindingPatternErrors() {
|
||||
this->Accumulate(ExpressionClassifier::AllProductions &
|
||||
~(ExpressionClassifier::BindingPatternProduction |
|
||||
@ -1441,6 +1452,8 @@ class ParserBase {
|
||||
int function_literal_id_;
|
||||
int script_id_;
|
||||
|
||||
bool accept_IN_ = true;
|
||||
|
||||
bool allow_natives_;
|
||||
bool allow_harmony_public_fields_;
|
||||
bool allow_harmony_static_fields_;
|
||||
@ -1757,7 +1770,8 @@ ParserBase<Impl>::ParsePrimaryExpression() {
|
||||
(peek() == Token::ASYNC && PeekAhead() == Token::FUNCTION)) {
|
||||
function_state_->set_next_function_is_likely_called();
|
||||
}
|
||||
ExpressionT expr = ParseExpressionCoverGrammar(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT expr = ParseExpressionCoverGrammar();
|
||||
Expect(Token::RPAREN);
|
||||
// Parenthesized parameters have to be followed immediately by an arrow to
|
||||
// be valid.
|
||||
@ -1809,14 +1823,15 @@ ParserBase<Impl>::ParsePrimaryExpression() {
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseExpression() {
|
||||
ExpressionClassifier classifier(this);
|
||||
ExpressionT result = ParseExpressionCoverGrammar(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT result = ParseExpressionCoverGrammar();
|
||||
ValidateExpression();
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::ExpressionT
|
||||
ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN) {
|
||||
ParserBase<Impl>::ParseExpressionCoverGrammar() {
|
||||
// Expression ::
|
||||
// AssignmentExpression
|
||||
// Expression ',' AssignmentExpression
|
||||
@ -1828,7 +1843,7 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN) {
|
||||
if (V8_UNLIKELY(peek() == Token::ELLIPSIS)) {
|
||||
return ParseArrowFormalsWithRest(&list);
|
||||
}
|
||||
expression = ParseAssignmentExpression(accept_IN);
|
||||
expression = ParseAssignmentExpression();
|
||||
// No need to accumulate binding pattern-related errors, since
|
||||
// an Expression can't be a binding pattern anyway.
|
||||
AccumulateNonBindingPatternErrors();
|
||||
@ -1913,7 +1928,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() {
|
||||
} else if (Check(Token::ELLIPSIS)) {
|
||||
int start_pos = position();
|
||||
int expr_pos = peek_position();
|
||||
ExpressionT argument = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT argument = ParseAssignmentExpression();
|
||||
elem = factory()->NewSpread(argument, start_pos, expr_pos);
|
||||
|
||||
if (first_spread_index < 0) {
|
||||
@ -1935,7 +1951,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() {
|
||||
}
|
||||
} else {
|
||||
int beg_pos = peek_position();
|
||||
elem = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
elem = ParseAssignmentExpression();
|
||||
CheckDestructuringElement(elem, beg_pos, end_position());
|
||||
}
|
||||
values.Add(elem);
|
||||
@ -2064,7 +2081,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
|
||||
*is_computed_name = true;
|
||||
Consume(Token::LBRACK);
|
||||
ExpressionClassifier computed_name_classifier(this);
|
||||
ExpressionT expression = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT expression = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
AccumulateFormalParameterContainmentErrors();
|
||||
Expect(Token::RBRACK);
|
||||
@ -2078,7 +2096,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
|
||||
if (*kind == ParsePropertyKind::kNotSet) {
|
||||
*name = impl()->NullIdentifier();
|
||||
Consume(Token::ELLIPSIS);
|
||||
ExpressionT expression = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT expression = ParseAssignmentExpression();
|
||||
*kind = ParsePropertyKind::kSpread;
|
||||
|
||||
if (!impl()->IsIdentifier(expression)) {
|
||||
@ -2307,7 +2326,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberInitializer(
|
||||
initializer_scope);
|
||||
ExpressionClassifier expression_classifier(this);
|
||||
|
||||
initializer = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
initializer = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
|
||||
// TODO(gsathya): In the future, this could be changed to be
|
||||
@ -2373,7 +2393,8 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
|
||||
}
|
||||
Consume(Token::COLON);
|
||||
int beg_pos = peek_position();
|
||||
ExpressionT value = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT value = ParseAssignmentExpression();
|
||||
CheckDestructuringElement(value, beg_pos, end_position());
|
||||
|
||||
ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
|
||||
@ -2422,7 +2443,8 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
|
||||
if (peek() == Token::ASSIGN) {
|
||||
Consume(Token::ASSIGN);
|
||||
ExpressionClassifier rhs_classifier(this);
|
||||
ExpressionT rhs = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT rhs = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
AccumulateFormalParameterContainmentErrors();
|
||||
value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs,
|
||||
@ -2586,7 +2608,8 @@ void ParserBase<Impl>::ParseArguments(
|
||||
bool is_spread = Check(Token::ELLIPSIS);
|
||||
int expr_pos = peek_position();
|
||||
|
||||
ExpressionT argument = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT argument = ParseAssignmentExpression();
|
||||
if (maybe_arrow) {
|
||||
if (!impl()->IsIdentifier(argument)) {
|
||||
classifier()->previous()->RecordNonSimpleParameter();
|
||||
@ -2625,7 +2648,7 @@ void ParserBase<Impl>::ParseArguments(
|
||||
// Precedence = 2
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::ExpressionT
|
||||
ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN) {
|
||||
ParserBase<Impl>::ParseAssignmentExpression() {
|
||||
// AssignmentExpression ::
|
||||
// ConditionalExpression
|
||||
// ArrowFunction
|
||||
@ -2634,7 +2657,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN) {
|
||||
int lhs_beg_pos = peek_position();
|
||||
|
||||
if (peek() == Token::YIELD && is_generator()) {
|
||||
return ParseYieldExpression(accept_IN);
|
||||
return ParseYieldExpression();
|
||||
}
|
||||
|
||||
FuncNameInferrerState fni_state(&fni_);
|
||||
@ -2647,7 +2670,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN) {
|
||||
bool parenthesized_formals =
|
||||
(is_async ? PeekAhead() : peek()) == Token::LPAREN;
|
||||
|
||||
ExpressionT expression = ParseConditionalExpression(accept_IN);
|
||||
ExpressionT expression = ParseConditionalExpression();
|
||||
|
||||
Token::Value op = peek();
|
||||
|
||||
@ -2694,8 +2717,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN) {
|
||||
scope->set_start_position(lhs_beg_pos);
|
||||
impl()->DeclareArrowFunctionFormalParameters(¶meters, expression, loc);
|
||||
|
||||
expression =
|
||||
ParseArrowFunctionLiteral(accept_IN, parameters, rewritable_length);
|
||||
expression = ParseArrowFunctionLiteral(parameters, rewritable_length);
|
||||
Accumulate(ExpressionClassifier::AsyncArrowFormalParametersProduction);
|
||||
classifier()->RecordPatternError(arrow_loc,
|
||||
MessageTemplate::kUnexpectedToken,
|
||||
@ -2720,7 +2742,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN) {
|
||||
|
||||
ExpressionClassifier rhs_classifier(this);
|
||||
|
||||
ExpressionT right = ParseAssignmentExpression(accept_IN);
|
||||
ExpressionT right = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
AccumulateFormalParameterContainmentErrors();
|
||||
|
||||
@ -2745,7 +2767,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN) {
|
||||
|
||||
ExpressionClassifier rhs_classifier(this);
|
||||
|
||||
ExpressionT right = ParseAssignmentExpression(accept_IN);
|
||||
ExpressionT right = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
AccumulateFormalParameterContainmentErrors();
|
||||
|
||||
@ -2778,8 +2800,8 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN) {
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
|
||||
bool accept_IN) {
|
||||
typename ParserBase<Impl>::ExpressionT
|
||||
ParserBase<Impl>::ParseYieldExpression() {
|
||||
// YieldExpression ::
|
||||
// 'yield' ([no line terminator] '*'? AssignmentExpression)?
|
||||
int pos = peek_position();
|
||||
@ -2813,7 +2835,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
|
||||
// Delegating yields require an RHS; fall through.
|
||||
V8_FALLTHROUGH;
|
||||
default:
|
||||
expression = ParseAssignmentExpression(accept_IN);
|
||||
expression = ParseAssignmentExpression();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2842,23 +2864,23 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
|
||||
// Precedence = 3
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::ExpressionT
|
||||
ParserBase<Impl>::ParseConditionalExpression(bool accept_IN) {
|
||||
ParserBase<Impl>::ParseConditionalExpression() {
|
||||
// ConditionalExpression ::
|
||||
// LogicalOrExpression
|
||||
// LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
|
||||
|
||||
int pos = peek_position();
|
||||
// We start using the binary expression parser for prec >= 4 only!
|
||||
ExpressionT expression = ParseBinaryExpression(4, accept_IN);
|
||||
ExpressionT expression = ParseBinaryExpression(4);
|
||||
return peek() == Token::CONDITIONAL
|
||||
? ParseConditionalContinuation(expression, accept_IN, pos)
|
||||
? ParseConditionalContinuation(expression, pos)
|
||||
: expression;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::ExpressionT
|
||||
ParserBase<Impl>::ParseConditionalContinuation(ExpressionT expression,
|
||||
bool accept_IN, int pos) {
|
||||
int pos) {
|
||||
SourceRange then_range, else_range;
|
||||
BindingPatternUnexpectedToken();
|
||||
|
||||
@ -2871,13 +2893,14 @@ ParserBase<Impl>::ParseConditionalContinuation(ExpressionT expression,
|
||||
// In parsing the first assignment expression in conditional
|
||||
// expressions we always accept the 'in' keyword; see ECMA-262,
|
||||
// section 11.12, page 58.
|
||||
left = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
left = ParseAssignmentExpression();
|
||||
}
|
||||
ExpressionT right;
|
||||
{
|
||||
SourceRangeScope range_scope(scanner(), &else_range);
|
||||
Expect(Token::COLON);
|
||||
right = ParseAssignmentExpression(accept_IN);
|
||||
right = ParseAssignmentExpression();
|
||||
}
|
||||
ExpressionT expr = factory()->NewConditional(expression, left, right, pos);
|
||||
impl()->RecordConditionalSourceRange(expr, then_range, else_range);
|
||||
@ -2888,13 +2911,11 @@ ParserBase<Impl>::ParseConditionalContinuation(ExpressionT expression,
|
||||
// Precedence >= 4
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::ExpressionT
|
||||
ParserBase<Impl>::ParseBinaryContinuation(ExpressionT x, int prec, int prec1,
|
||||
bool accept_IN) {
|
||||
if (!accept_IN && peek() == Token::IN) return x;
|
||||
ParserBase<Impl>::ParseBinaryContinuation(ExpressionT x, int prec, int prec1) {
|
||||
BindingPatternUnexpectedToken();
|
||||
do {
|
||||
// prec1 >= 4
|
||||
while (Token::Precedence(peek()) == prec1) {
|
||||
while (Token::Precedence(peek(), accept_IN_) == prec1) {
|
||||
SourceRange right_range;
|
||||
int pos = peek_position();
|
||||
ExpressionT y;
|
||||
@ -2905,7 +2926,7 @@ ParserBase<Impl>::ParseBinaryContinuation(ExpressionT x, int prec, int prec1,
|
||||
|
||||
const bool is_right_associative = op == Token::EXP;
|
||||
const int next_prec = is_right_associative ? prec1 : prec1 + 1;
|
||||
y = ParseBinaryExpression(next_prec, accept_IN);
|
||||
y = ParseBinaryExpression(next_prec);
|
||||
}
|
||||
|
||||
// For now we distinguish between comparisons and other binary
|
||||
@ -2933,7 +2954,6 @@ ParserBase<Impl>::ParseBinaryContinuation(ExpressionT x, int prec, int prec1,
|
||||
impl()->RecordBinaryOperationSourceRange(x, right_range);
|
||||
}
|
||||
}
|
||||
if (!accept_IN && peek() == Token::IN) return x;
|
||||
}
|
||||
--prec1;
|
||||
} while (prec1 >= prec);
|
||||
@ -2944,12 +2964,12 @@ ParserBase<Impl>::ParseBinaryContinuation(ExpressionT x, int prec, int prec1,
|
||||
// Precedence >= 4
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
|
||||
int prec, bool accept_IN) {
|
||||
int prec) {
|
||||
DCHECK_GE(prec, 4);
|
||||
ExpressionT x = ParseUnaryExpression();
|
||||
int prec1 = Token::Precedence(peek());
|
||||
int prec1 = Token::Precedence(peek(), accept_IN_);
|
||||
if (prec1 >= prec) {
|
||||
return ParseBinaryContinuation(x, prec, prec1, accept_IN);
|
||||
return ParseBinaryContinuation(x, prec, prec1);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@ -3108,7 +3128,8 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
|
||||
case Token::LBRACK: {
|
||||
Consume(Token::LBRACK);
|
||||
int pos = position();
|
||||
ExpressionT index = ParseExpressionCoverGrammar(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT index = ParseExpressionCoverGrammar();
|
||||
result = factory()->NewProperty(result, index, pos);
|
||||
Expect(Token::RBRACK);
|
||||
break;
|
||||
@ -3376,7 +3397,8 @@ ParserBase<Impl>::ParseImportExpressions() {
|
||||
MessageTemplate::kImportMissingSpecifier);
|
||||
return impl()->FailureExpression();
|
||||
}
|
||||
ExpressionT arg = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT arg = ParseAssignmentExpression();
|
||||
Expect(Token::RPAREN);
|
||||
return factory()->NewImportCallExpression(arg, pos);
|
||||
}
|
||||
@ -3452,7 +3474,8 @@ ParserBase<Impl>::DoParseMemberExpressionContinuation(ExpressionT expression) {
|
||||
case Token::LBRACK: {
|
||||
Consume(Token::LBRACK);
|
||||
int pos = position();
|
||||
ExpressionT index = ParseExpressionCoverGrammar(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT index = ParseExpressionCoverGrammar();
|
||||
expression = factory()->NewProperty(expression, index, pos);
|
||||
impl()->PushPropertyName(index);
|
||||
Expect(Token::RBRACK);
|
||||
@ -3508,7 +3531,8 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters) {
|
||||
}
|
||||
{
|
||||
ExpressionClassifier init_classifier(this);
|
||||
initializer = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
initializer = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
ValidateFormalParameterInitializer();
|
||||
parameters->is_simple = false;
|
||||
@ -3640,7 +3664,8 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
|
||||
value_beg_position = peek_position();
|
||||
|
||||
ExpressionClassifier classifier(this);
|
||||
value = ParseAssignmentExpression(var_context != kForStatement);
|
||||
AcceptINScope scope(this, var_context != kForStatement);
|
||||
value = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
variable_loc.end_pos = end_position();
|
||||
|
||||
@ -3887,8 +3912,7 @@ template <typename Impl>
|
||||
void ParserBase<Impl>::ParseFunctionBody(
|
||||
typename ParserBase<Impl>::StatementListT* body, IdentifierT function_name,
|
||||
int pos, const FormalParametersT& parameters, FunctionKind kind,
|
||||
FunctionLiteral::FunctionType function_type, FunctionBodyType body_type,
|
||||
bool accept_IN) {
|
||||
FunctionLiteral::FunctionType function_type, FunctionBodyType body_type) {
|
||||
DeclarationScope* function_scope = scope()->AsDeclarationScope();
|
||||
DeclarationScope* inner_scope = function_scope;
|
||||
|
||||
@ -3904,7 +3928,7 @@ void ParserBase<Impl>::ParseFunctionBody(
|
||||
|
||||
if (body_type == FunctionBodyType::kExpression) {
|
||||
ExpressionClassifier classifier(this);
|
||||
ExpressionT expression = ParseAssignmentExpression(accept_IN);
|
||||
ExpressionT expression = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
|
||||
if (IsAsyncFunction(kind)) {
|
||||
@ -3914,7 +3938,7 @@ void ParserBase<Impl>::ParseFunctionBody(
|
||||
body->Add(BuildReturnStatement(expression, expression->position()));
|
||||
}
|
||||
} else {
|
||||
DCHECK(accept_IN);
|
||||
DCHECK(accept_IN_);
|
||||
DCHECK_EQ(FunctionBodyType::kBlock, body_type);
|
||||
// If we are parsing the source as if it is wrapped in a function, the
|
||||
// source ends without a closing brace.
|
||||
@ -4052,8 +4076,7 @@ bool ParserBase<Impl>::IsNextLetKeyword() {
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::ExpressionT
|
||||
ParserBase<Impl>::ParseArrowFunctionLiteral(
|
||||
bool accept_IN, const FormalParametersT& formal_parameters,
|
||||
int rewritable_length) {
|
||||
const FormalParametersT& formal_parameters, int rewritable_length) {
|
||||
const RuntimeCallCounterId counters[2][2] = {
|
||||
{RuntimeCallCounterId::kParseBackgroundArrowFunctionLiteral,
|
||||
RuntimeCallCounterId::kParseArrowFunctionLiteral},
|
||||
@ -4134,19 +4157,21 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
|
||||
// In case we did not sucessfully preparse the function because of an
|
||||
// unidentified error we do a full reparse to return the error.
|
||||
Consume(Token::LBRACE);
|
||||
AcceptINScope scope(this, true);
|
||||
ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition,
|
||||
formal_parameters, kind,
|
||||
FunctionLiteral::kAnonymousExpression,
|
||||
FunctionBodyType::kBlock, true);
|
||||
FunctionBodyType::kBlock);
|
||||
CHECK(has_error());
|
||||
return impl()->FailureExpression();
|
||||
}
|
||||
} else {
|
||||
Consume(Token::LBRACE);
|
||||
AcceptINScope scope(this, true);
|
||||
ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition,
|
||||
formal_parameters, kind,
|
||||
FunctionLiteral::kAnonymousExpression,
|
||||
FunctionBodyType::kBlock, true);
|
||||
FunctionBodyType::kBlock);
|
||||
expected_property_count = function_state.expected_property_count();
|
||||
}
|
||||
} else {
|
||||
@ -4155,7 +4180,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
|
||||
ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition,
|
||||
formal_parameters, kind,
|
||||
FunctionLiteral::kAnonymousExpression,
|
||||
FunctionBodyType::kExpression, accept_IN);
|
||||
FunctionBodyType::kExpression);
|
||||
expected_property_count = function_state.expected_property_count();
|
||||
}
|
||||
|
||||
@ -4395,7 +4420,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral(
|
||||
next = peek();
|
||||
|
||||
int expr_pos = peek_position();
|
||||
ExpressionT expression = ParseExpressionCoverGrammar(true);
|
||||
AcceptINScope scope(this, true);
|
||||
ExpressionT expression = ParseExpressionCoverGrammar();
|
||||
impl()->AddTemplateExpression(&ts, expression);
|
||||
|
||||
if (peek() != Token::RBRACE) {
|
||||
@ -5410,7 +5436,11 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
|
||||
// The initializer does not contain declarations.
|
||||
int lhs_beg_pos = peek_position();
|
||||
ExpressionClassifier classifier(this);
|
||||
ExpressionT expression = ParseExpressionCoverGrammar(false);
|
||||
ExpressionT expression;
|
||||
{
|
||||
AcceptINScope scope(this, false);
|
||||
expression = ParseExpressionCoverGrammar();
|
||||
}
|
||||
int lhs_end_pos = end_position();
|
||||
|
||||
bool is_for_each = CheckInOrOf(&for_info.mode);
|
||||
@ -5482,7 +5512,8 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
|
||||
ExpressionT enumerable = impl()->NullExpression();
|
||||
if (for_info->mode == ForEachStatement::ITERATE) {
|
||||
ExpressionClassifier classifier(this);
|
||||
enumerable = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
enumerable = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
} else {
|
||||
enumerable = ParseExpression();
|
||||
@ -5562,7 +5593,8 @@ ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
|
||||
ExpressionT enumerable = impl()->NullExpression();
|
||||
if (for_info->mode == ForEachStatement::ITERATE) {
|
||||
ExpressionClassifier classifier(this);
|
||||
enumerable = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
enumerable = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
} else {
|
||||
enumerable = ParseExpression();
|
||||
@ -5767,7 +5799,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
|
||||
|
||||
{
|
||||
ExpressionClassifier classifier(this);
|
||||
iterable = ParseAssignmentExpression(kAllowIn);
|
||||
AcceptINScope scope(this, kAllowIn);
|
||||
iterable = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
}
|
||||
|
||||
|
@ -812,14 +812,11 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info,
|
||||
SkipFunctionLiterals(info->function_literal_id() - 1);
|
||||
}
|
||||
|
||||
// Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should
|
||||
// not be observable, or else the preparser would have failed.
|
||||
const bool accept_IN = true;
|
||||
// Any destructuring assignments in the current FunctionState
|
||||
// actually belong to the arrow function itself.
|
||||
const int rewritable_length = 0;
|
||||
Expression* expression =
|
||||
ParseArrowFunctionLiteral(accept_IN, formals, rewritable_length);
|
||||
ParseArrowFunctionLiteral(formals, rewritable_length);
|
||||
// Scanning must end at the same position that was recorded
|
||||
// previously. If not, parsing has been interrupted due to a stack
|
||||
// overflow, at which point the partially parsed arrow function
|
||||
@ -1153,7 +1150,8 @@ Statement* Parser::ParseExportDefault() {
|
||||
default: {
|
||||
int pos = position();
|
||||
ExpressionClassifier classifier(this);
|
||||
Expression* value = ParseAssignmentExpression(true);
|
||||
AcceptINScope scope(this, true);
|
||||
Expression* value = ParseAssignmentExpression();
|
||||
ValidateExpression();
|
||||
SetFunctionName(value, ast_value_factory()->default_string());
|
||||
|
||||
@ -3012,8 +3010,9 @@ void Parser::ParseFunction(
|
||||
*num_parameters = formals.num_parameters();
|
||||
*function_length = formals.function_length;
|
||||
|
||||
AcceptINScope scope(this, true);
|
||||
ParseFunctionBody(body, function_name, pos, formals, kind, function_type,
|
||||
FunctionBodyType::kBlock, true);
|
||||
FunctionBodyType::kBlock);
|
||||
|
||||
RewriteDestructuringAssignments();
|
||||
|
||||
|
@ -302,8 +302,9 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
|
||||
PreParserScopedStatementList body(pointer_buffer());
|
||||
int pos = function_token_pos == kNoSourcePosition ? peek_position()
|
||||
: function_token_pos;
|
||||
AcceptINScope scope(this, true);
|
||||
ParseFunctionBody(&body, function_name, pos, formals, kind, function_type,
|
||||
FunctionBodyType::kBlock, true);
|
||||
FunctionBodyType::kBlock);
|
||||
|
||||
// Parsing the body may change the language mode in our scope.
|
||||
language_mode = function_scope->language_mode();
|
||||
|
@ -25,9 +25,14 @@ constexpr uint8_t length(const char* str) {
|
||||
const uint8_t Token::string_length_[NUM_TOKENS] = {TOKEN_LIST(T, T, T)};
|
||||
#undef T
|
||||
|
||||
#define T(name, string, precedence) precedence,
|
||||
const int8_t Token::precedence_[NUM_TOKENS] = {TOKEN_LIST(T, T, T)};
|
||||
#undef T
|
||||
#define T1(name, string, precedence) \
|
||||
((Token::name == Token::IN) ? 0 : precedence),
|
||||
#define T2(name, string, precedence) precedence,
|
||||
// precedence_[0] for accept_IN == false, precedence_[1] for accept_IN = true.
|
||||
const int8_t Token::precedence_[2][NUM_TOKENS] = {{TOKEN_LIST(T1, T1, T1)},
|
||||
{TOKEN_LIST(T2, T2, T2)}};
|
||||
#undef T2
|
||||
#undef T1
|
||||
|
||||
#define KT(a, b, c) 'T',
|
||||
#define KK(a, b, c) 'K',
|
||||
|
@ -326,16 +326,16 @@ class Token {
|
||||
|
||||
// Returns the precedence > 0 for binary and compare
|
||||
// operators; returns 0 otherwise.
|
||||
static int Precedence(Value token) {
|
||||
static int Precedence(Value token, bool accept_IN) {
|
||||
DCHECK_GT(NUM_TOKENS, token); // token is unsigned
|
||||
return precedence_[token];
|
||||
return precedence_[accept_IN][token];
|
||||
}
|
||||
|
||||
private:
|
||||
static const char* const name_[NUM_TOKENS];
|
||||
static const char* const string_[NUM_TOKENS];
|
||||
static const uint8_t string_length_[NUM_TOKENS];
|
||||
static const int8_t precedence_[NUM_TOKENS];
|
||||
static const int8_t precedence_[2][NUM_TOKENS];
|
||||
static const char token_type[NUM_TOKENS];
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user