Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(824)

Unified Diff: src/preparser.h

Issue 997823003: [es6] support rest parameters in arrow functions (alternative) (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/preparser.h
diff --git a/src/preparser.h b/src/preparser.h
index a17296349b362df6afefbb5b8538d7c030915270..78f58d60072626a608a9cca31f16133ad2fa8815 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -563,7 +563,7 @@ class ParserBase : public Traits {
ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok);
- ExpressionT ParsePrimaryExpression(bool* ok);
+ ExpressionT ParsePrimaryExpression(bool maybeArrow, bool* ok);
ExpressionT ParseExpression(bool accept_IN, bool* ok);
ExpressionT ParseArrayLiteral(bool* ok);
ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set,
@@ -577,13 +577,15 @@ class ParserBase : public Traits {
typename Traits::Type::ExpressionList ParseArguments(bool* ok);
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
ExpressionT ParseYieldExpression(bool* ok);
- ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
- ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
- ExpressionT ParseUnaryExpression(bool* ok);
- ExpressionT ParsePostfixExpression(bool* ok);
- ExpressionT ParseLeftHandSideExpression(bool* ok);
- ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok);
- ExpressionT ParseMemberExpression(bool* ok);
+ ExpressionT ParseConditionalExpression(bool accept_IN, bool maybeArrow,
+ bool* ok);
+ ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool maybeArrow,
+ bool* ok);
+ ExpressionT ParseUnaryExpression(bool maybeArrow, bool* ok);
+ ExpressionT ParsePostfixExpression(bool maybeArrow, bool* ok);
+ ExpressionT ParseLeftHandSideExpression(bool maybeArrow, bool* ok);
+ ExpressionT ParseMemberWithNewPrefixesExpression(bool maybeArrow, bool* ok);
+ ExpressionT ParseMemberExpression(bool maybeArrow, bool* ok);
ExpressionT ParseMemberExpressionContinuation(ExpressionT expression,
bool* ok);
ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast,
@@ -778,6 +780,11 @@ class PreParserExpression {
return PreParserExpression(TypeField::encode(kExpression));
}
+ static PreParserExpression Spread(PreParserExpression expression) {
+ return PreParserExpression(
+ expression.code_ | TypeField::encode(kSpreadExpression));
+ }
+
static PreParserExpression FromIdentifier(PreParserIdentifier id) {
return PreParserExpression(TypeField::encode(kIdentifierExpression) |
IdentifierTypeField::encode(id.type_));
@@ -789,7 +796,7 @@ class PreParserExpression {
bool valid_arrow_param_list =
op == Token::COMMA && !left.is_parenthesized() &&
!right.is_parenthesized() && left.IsValidArrowParams() &&
- right.IsValidArrowParams();
+ right.IsValidArrowParams() && !left.IsSpread();
return PreParserExpression(
TypeField::encode(kBinaryOperationExpression) |
IsValidArrowParamListField::encode(valid_arrow_param_list));
@@ -922,6 +929,15 @@ class PreParserExpression {
: kParanthesizedExpression);
}
+ bool IsSpread() const {
+ // Is<NodeType> queries other than IsSpread() should always fail
+ return TypeField::decode(code_) & kSpreadExpression;
+ }
+
+ PreParserExpression SpreadExpression() const {
+ return PreParserExpression(code_ & ~TypeField::encode(kSpreadExpression));
+ }
+
// Dummy implementation for making expression->somefunc() work in both Parser
// and PreParser.
PreParserExpression* operator->() { return this; }
@@ -938,7 +954,8 @@ class PreParserExpression {
kExpression,
kIdentifierExpression,
kStringLiteralExpression,
- kBinaryOperationExpression
+ kBinaryOperationExpression,
+ kSpreadExpression
};
enum Parenthesization {
@@ -959,13 +976,14 @@ class PreParserExpression {
: code_(expression_code) {}
V8_INLINE bool IsValidArrowParams() const {
- return IsBinaryOperation()
- ? IsValidArrowParamListField::decode(code_)
- : (IsIdentifier() && AsIdentifier().IsValidArrowParam());
+ PreParserExpression e = IsSpread() ? SpreadExpression() : *this;
+ return e.IsBinaryOperation()
+ ? IsValidArrowParamListField::decode(e.code_)
+ : (e.IsIdentifier() && e.AsIdentifier().IsValidArrowParam());
}
// The first four bits are for the Type and Parenthesization.
- typedef BitField<Type, 0, 2> TypeField;
+ typedef BitField<Type, 0, 3> TypeField;
typedef BitField<Parenthesization, TypeField::kNext, 2> ParenthesizationField;
// The rest of the bits are interpreted depending on the value
@@ -1150,6 +1168,9 @@ class PreParserFactory {
int pos) {
return PreParserExpression::Default();
}
+ PreParserExpression NewSpread(PreParserExpression expression, int pos) {
+ return PreParserExpression::Spread(expression);
+ }
PreParserExpression NewCountOperation(Token::Value op,
bool is_prefix,
PreParserExpression expression,
@@ -1494,6 +1515,10 @@ class PreParserTraits {
bool name_is_strict_reserved, int pos,
bool* ok);
+ PreParserExpression SpreadExpression(PreParserExpression spread) const {
+ return spread.SpreadExpression();
+ }
+
private:
PreParser* pre_parser_;
};
@@ -1601,7 +1626,8 @@ class PreParser : public ParserBase<PreParserTraits> {
Statement ParseThrowStatement(bool* ok);
Statement ParseTryStatement(bool* ok);
Statement ParseDebuggerStatement(bool* ok);
- Expression ParseConditionalExpression(bool accept_IN, bool* ok);
+ Expression ParseConditionalExpression(bool accept_IN, bool maybeArrow,
+ bool* ok);
Expression ParseObjectLiteral(bool* ok);
Expression ParseV8Intrinsic(bool* ok);
@@ -1850,7 +1876,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
template <class Traits>
typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
+ParserBase<Traits>::ParsePrimaryExpression(bool maybeArrow, bool* ok) {
// PrimaryExpression ::
// 'this'
// 'null'
@@ -1976,6 +2002,30 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
// If we're not allowing special syntax we fall-through to the
// default case.
+ case Token::ELLIPSIS:
arv (Not doing code reviews) 2015/03/11 18:59:13 Beware of fall through here.
+ if (maybeArrow && allow_harmony_arrow_functions() &&
+ allow_harmony_rest_params()) {
+ Consume(Token::ELLIPSIS);
+ if (!peek_any_identifier()) {
+ ReportUnexpectedToken(token);
+ *ok = false;
+ break;
+ }
+ bool is_strict_reserved_name = false;
+ IdentifierT name = ParseIdentifierOrStrictReservedWord(
+ &is_strict_reserved_name, CHECK_OK);
+ if (peek() != Token::RPAREN) {
+ ReportUnexpectedTokenAt(Scanner::Location(beg_pos, beg_pos + 3),
+ Token::ELLIPSIS);
+ *ok = false;
+ break;
+ }
+ result = this->ExpressionFromIdentifier(name, position(),
+ peek_position(), scope_,
+ factory());
+ return factory()->NewSpread(result, beg_pos);
+ }
+
default: {
Next();
ReportUnexpectedToken(token);
@@ -2345,14 +2395,25 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
if (fni_ != NULL) fni_->Enter();
ParserBase<Traits>::Checkpoint checkpoint(this);
+ const bool maybeArrow =
+ allow_harmony_arrow_functions() && allow_harmony_rest_params();
ExpressionT expression =
- this->ParseConditionalExpression(accept_IN, CHECK_OK);
+ this->ParseConditionalExpression(accept_IN, maybeArrow, CHECK_OK);
if (allow_harmony_arrow_functions() && peek() == Token::ARROW) {
checkpoint.Restore();
+ if (expression->IsSpread() && !expression->is_parenthesized()) {
+ // TODO(caitp): the error is an unexpected `...`, it would be nice if we
arv (Not doing code reviews) 2015/03/11 18:59:12 Can you store the position before calling ParseCon
+ // knew where the `...` occurred.
+ ReportUnexpectedToken(peek());
+ *ok = false;
+ return this->EmptyExpression();
+ }
expression = this->ParseArrowFunctionLiteral(lhs_location.beg_pos,
expression, CHECK_OK);
return expression;
+ } else if (maybeArrow) {
+ // TODO(caitp): report an error if an unexpected `...` occurred.
arv (Not doing code reviews) 2015/03/11 18:59:13 Here it would be good to have an ast ;-) I'm not
}
if (!Token::IsAssignmentOp(peek())) {
@@ -2448,14 +2509,16 @@ ParserBase<Traits>::ParseYieldExpression(bool* ok) {
// Precedence = 3
template <class Traits>
typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) {
+ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool maybeArrow,
+ bool* ok) {
// ConditionalExpression ::
// LogicalOrExpression
// LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
int pos = peek_position();
// We start using the binary expression parser for prec >= 4 only!
- ExpressionT expression = this->ParseBinaryExpression(4, accept_IN, CHECK_OK);
+ ExpressionT expression = this->ParseBinaryExpression(4, accept_IN, maybeArrow,
+ CHECK_OK);
if (peek() != Token::CONDITIONAL) return expression;
Consume(Token::CONDITIONAL);
// In parsing the first assignment expression in conditional
@@ -2471,16 +2534,20 @@ ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) {
// Precedence >= 4
template <class Traits>
typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
+ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN,
+ bool maybeArrow, bool* ok) {
DCHECK(prec >= 4);
- ExpressionT x = this->ParseUnaryExpression(CHECK_OK);
+ ExpressionT x = this->ParseUnaryExpression(maybeArrow, CHECK_OK);
for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
// prec1 >= 4
while (Precedence(peek(), accept_IN) == prec1) {
Token::Value op = Next();
Scanner::Location op_location = scanner()->location();
int pos = position();
- ExpressionT y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
+ // Only allow arrow extensions in binary expressions if op is comma
+ ExpressionT y = ParseBinaryExpression(prec1 + 1, accept_IN,
+ maybeArrow && op == Token::COMMA,
+ CHECK_OK);
if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos,
factory())) {
@@ -2521,7 +2588,7 @@ ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
template <class Traits>
typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseUnaryExpression(bool* ok) {
+ParserBase<Traits>::ParseUnaryExpression(bool maybeArrow, bool* ok) {
// UnaryExpression ::
// PostfixExpression
// 'delete' UnaryExpression
@@ -2538,7 +2605,7 @@ ParserBase<Traits>::ParseUnaryExpression(bool* ok) {
if (Token::IsUnaryOp(op)) {
op = Next();
int pos = position();
- ExpressionT expression = ParseUnaryExpression(CHECK_OK);
+ ExpressionT expression = ParseUnaryExpression(false, CHECK_OK);
if (op == Token::DELETE && is_strict(language_mode())) {
if (is_strong(language_mode())) {
@@ -2558,7 +2625,7 @@ ParserBase<Traits>::ParseUnaryExpression(bool* ok) {
} else if (Token::IsCountOp(op)) {
op = Next();
Scanner::Location lhs_location = scanner()->peek_location();
- ExpressionT expression = this->ParseUnaryExpression(CHECK_OK);
+ ExpressionT expression = this->ParseUnaryExpression(false, CHECK_OK);
expression = this->CheckAndRewriteReferenceExpression(
expression, lhs_location, "invalid_lhs_in_prefix_op", CHECK_OK);
this->MarkExpressionAsAssigned(expression);
@@ -2569,19 +2636,20 @@ ParserBase<Traits>::ParseUnaryExpression(bool* ok) {
position());
} else {
- return this->ParsePostfixExpression(ok);
+ return this->ParsePostfixExpression(maybeArrow, ok);
}
}
template <class Traits>
typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParsePostfixExpression(bool* ok) {
+ParserBase<Traits>::ParsePostfixExpression(bool maybeArrow, bool* ok) {
// PostfixExpression ::
// LeftHandSideExpression ('++' | '--')?
Scanner::Location lhs_location = scanner()->peek_location();
- ExpressionT expression = this->ParseLeftHandSideExpression(CHECK_OK);
+ ExpressionT expression = this->ParseLeftHandSideExpression(maybeArrow,
+ CHECK_OK);
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
Token::IsCountOp(peek())) {
expression = this->CheckAndRewriteReferenceExpression(
@@ -2601,11 +2669,12 @@ ParserBase<Traits>::ParsePostfixExpression(bool* ok) {
template <class Traits>
typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
+ParserBase<Traits>::ParseLeftHandSideExpression(bool maybeArrow, bool* ok) {
// LeftHandSideExpression ::
// (NewExpression | MemberExpression) ...
- ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
+ ExpressionT result = this->ParseMemberWithNewPrefixesExpression(
+ maybeArrow, CHECK_OK);
while (true) {
switch (peek()) {
@@ -2689,7 +2758,8 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
template <class Traits>
typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
+ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(
+ bool maybeArrow, bool* ok) {
// NewExpression ::
// ('new')+ MemberExpression
@@ -2715,7 +2785,7 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
const bool is_new = true;
result = ParseSuperExpression(is_new, CHECK_OK);
} else {
- result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
+ result = this->ParseMemberWithNewPrefixesExpression(maybeArrow, CHECK_OK);
}
if (peek() == Token::LPAREN) {
// NewExpression with arguments.
@@ -2731,13 +2801,13 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
new_pos);
}
// No 'new' or 'super' keyword.
- return this->ParseMemberExpression(ok);
+ return this->ParseMemberExpression(maybeArrow, ok);
}
template <class Traits>
typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseMemberExpression(bool* ok) {
+ParserBase<Traits>::ParseMemberExpression(bool maybeArrow, bool* ok) {
// MemberExpression ::
// (PrimaryExpression | FunctionLiteral | ClassLiteral)
// ('[' Expression ']' | '.' Identifier | Arguments)*
@@ -2773,7 +2843,7 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) {
const bool is_new = false;
result = ParseSuperExpression(is_new, CHECK_OK);
} else {
- result = ParsePrimaryExpression(CHECK_OK);
+ result = ParsePrimaryExpression(maybeArrow, CHECK_OK);
}
result = ParseMemberExpressionContinuation(result, CHECK_OK);
« no previous file with comments | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698