[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: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57362}
This commit is contained in:
Toon Verwaest 2018-11-08 17:14:54 +01:00 committed by Commit Bot
parent 7537b0016f
commit 701136f9ae
5 changed files with 53 additions and 32 deletions

View File

@ -1000,6 +1000,7 @@ class ParserBase {
// "CoverParenthesizedExpressionAndArrowParameterList" in the ES 2017
// specification).
ExpressionT ParseExpressionCoverGrammar(bool accept_IN);
ExpressionT ParseArrowFormalsWithRest(ExpressionListT* list);
ExpressionT ParseArrayLiteral();
@ -1833,40 +1834,23 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN) {
// Expression ',' AssignmentExpression
ExpressionListT list(pointer_buffer());
ExpressionT right;
ExpressionT expression;
while (true) {
ExpressionClassifier binding_classifier(this);
if (Check(Token::ELLIPSIS)) {
// 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only
// 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);
if (V8_UNLIKELY(peek() == Token::ELLIPSIS)) {
return ParseArrowFormalsWithRest(&list);
}
expression = ParseAssignmentExpression(accept_IN);
// No need to accumulate binding pattern-related errors, since
// an Expression can't be a binding pattern anyway.
AccumulateNonBindingPatternErrors();
if (!impl()->IsIdentifier(right)) classifier()->RecordNonSimpleParameter();
list.Add(right);
if (!impl()->IsIdentifier(expression)) {
classifier()->RecordNonSimpleParameter();
}
list.Add(expression);
if (!Check(Token::COMMA)) break;
if (right->IsSpread()) {
classifier()->RecordArrowFormalParametersError(
scanner()->location(), MessageTemplate::kParamAfterRest);
}
if (peek() == Token::RPAREN && PeekAhead() == Token::ARROW) {
// a trailing comma is allowed at the end of an arrow parameter list
break;
@ -1884,10 +1868,47 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN) {
// callers of this function care about the type of the result if there was
// only a single assignment expression. The preparser would lose this
// information otherwise.
if (list.length() == 1) return right;
if (list.length() == 1) return expression;
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>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() {
// ArrayLiteral ::

View File

@ -1,4 +1,4 @@
*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
(w, ...x, y) => 10
^
^
SyntaxError: Rest parameter must be last formal parameter

View File

@ -1,4 +1,4 @@
*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
(...x, y) => 10
^
^
SyntaxError: Rest parameter must be last formal parameter

View File

@ -1,4 +1,4 @@
*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
(w, ...x, ...y) => 10
^
^
SyntaxError: Rest parameter must be last formal parameter

View File

@ -1,4 +1,4 @@
*%(basename)s:7: SyntaxError: Unexpected token ...
*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter
(x, ...y, z)
^^^
SyntaxError: Unexpected token ...
^
SyntaxError: Rest parameter must be last formal parameter