Commit 701136f9 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[parser] Move rest parameter handling out of ExpressionCoverGrammar

This allows the main ExpressionCoverGrammar parsing to be a little tighter.

Change-Id: I45e3d1a9a647a98ffe1ad9969cb1ffbe47f67f1c
Reviewed-on: https://chromium-review.googlesource.com/c/1326468
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57362}
parent 7537b001
...@@ -1000,6 +1000,7 @@ class ParserBase { ...@@ -1000,6 +1000,7 @@ class ParserBase {
// "CoverParenthesizedExpressionAndArrowParameterList" in the ES 2017 // "CoverParenthesizedExpressionAndArrowParameterList" in the ES 2017
// specification). // specification).
ExpressionT ParseExpressionCoverGrammar(bool accept_IN); ExpressionT ParseExpressionCoverGrammar(bool accept_IN);
ExpressionT ParseArrowFormalsWithRest(ExpressionListT* list);
ExpressionT ParseArrayLiteral(); ExpressionT ParseArrayLiteral();
...@@ -1833,40 +1834,23 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN) { ...@@ -1833,40 +1834,23 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN) {
// Expression ',' AssignmentExpression // Expression ',' AssignmentExpression
ExpressionListT list(pointer_buffer()); ExpressionListT list(pointer_buffer());
ExpressionT right; ExpressionT expression;
while (true) { while (true) {
ExpressionClassifier binding_classifier(this); ExpressionClassifier binding_classifier(this);
if (Check(Token::ELLIPSIS)) { if (V8_UNLIKELY(peek() == Token::ELLIPSIS)) {
// 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only return ParseArrowFormalsWithRest(&list);
// as the formal parameters of'(x, y, ...z) => foo', and is not itself a
// valid expression.
classifier()->RecordExpressionError(scanner()->location(),
MessageTemplate::kUnexpectedToken,
Token::String(Token::ELLIPSIS));
int ellipsis_pos = position();
int pattern_pos = peek_position();
ExpressionT pattern = ParseBindingPattern();
if (peek() == Token::ASSIGN) {
ReportMessage(MessageTemplate::kRestDefaultInitializer);
return impl()->FailureExpression();
}
right = factory()->NewSpread(pattern, ellipsis_pos, pattern_pos);
} else {
right = ParseAssignmentExpression(accept_IN);
} }
expression = ParseAssignmentExpression(accept_IN);
// No need to accumulate binding pattern-related errors, since // No need to accumulate binding pattern-related errors, since
// an Expression can't be a binding pattern anyway. // an Expression can't be a binding pattern anyway.
AccumulateNonBindingPatternErrors(); AccumulateNonBindingPatternErrors();
if (!impl()->IsIdentifier(right)) classifier()->RecordNonSimpleParameter(); if (!impl()->IsIdentifier(expression)) {
list.Add(right); classifier()->RecordNonSimpleParameter();
}
list.Add(expression);
if (!Check(Token::COMMA)) break; if (!Check(Token::COMMA)) break;
if (right->IsSpread()) {
classifier()->RecordArrowFormalParametersError(
scanner()->location(), MessageTemplate::kParamAfterRest);
}
if (peek() == Token::RPAREN && PeekAhead() == Token::ARROW) { if (peek() == Token::RPAREN && PeekAhead() == Token::ARROW) {
// a trailing comma is allowed at the end of an arrow parameter list // a trailing comma is allowed at the end of an arrow parameter list
break; break;
...@@ -1884,10 +1868,47 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN) { ...@@ -1884,10 +1868,47 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN) {
// callers of this function care about the type of the result if there was // callers of this function care about the type of the result if there was
// only a single assignment expression. The preparser would lose this // only a single assignment expression. The preparser would lose this
// information otherwise. // information otherwise.
if (list.length() == 1) return right; if (list.length() == 1) return expression;
return impl()->ExpressionListToExpression(list); return impl()->ExpressionListToExpression(list);
} }
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseArrowFormalsWithRest(
typename ParserBase<Impl>::ExpressionListT* list) {
Consume(Token::ELLIPSIS);
Scanner::Location ellipsis = scanner()->location();
int pattern_pos = peek_position();
ExpressionT pattern = ParseBindingPattern();
AccumulateNonBindingPatternErrors();
classifier()->RecordNonSimpleParameter();
if (V8_UNLIKELY(peek() == Token::ASSIGN)) {
ReportMessage(MessageTemplate::kRestDefaultInitializer);
return impl()->FailureExpression();
}
ExpressionT spread =
factory()->NewSpread(pattern, ellipsis.beg_pos, pattern_pos);
if (V8_UNLIKELY(peek() == Token::COMMA)) {
ReportMessage(MessageTemplate::kParamAfterRest);
return impl()->FailureExpression();
}
// 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only
// as the formal parameters of'(x, y, ...z) => foo', and is not itself a
// valid expression.
if (peek() != Token::RPAREN || PeekAhead() != Token::ARROW) {
ReportUnexpectedTokenAt(ellipsis, Token::ELLIPSIS);
return impl()->FailureExpression();
}
list->Add(spread);
return impl()->ExpressionListToExpression(*list);
}
template <typename Impl> template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() { typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() {
// ArrayLiteral :: // ArrayLiteral ::
......
*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter *%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
(w, ...x, y) => 10 (w, ...x, y) => 10
^ ^
SyntaxError: Rest parameter must be last formal parameter SyntaxError: Rest parameter must be last formal parameter
*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter *%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
(...x, y) => 10 (...x, y) => 10
^ ^
SyntaxError: Rest parameter must be last formal parameter SyntaxError: Rest parameter must be last formal parameter
*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter *%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
(w, ...x, ...y) => 10 (w, ...x, ...y) => 10
^ ^
SyntaxError: Rest parameter must be last formal parameter SyntaxError: Rest parameter must be last formal parameter
*%(basename)s:7: SyntaxError: Unexpected token ... *%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
(x, ...y, z) (x, ...y, z)
^^^ ^
SyntaxError: Unexpected token ... SyntaxError: Rest parameter must be last formal parameter
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