Commit 0851de10 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[parser] Combine UnaryExpression and CountExpression behind single range-check

Change-Id: I8704003f05e74d55e724d669f5bbcef5c2214bf4
Reviewed-on: https://chromium-review.googlesource.com/c/1351018Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57867}
parent 7a3cb59f
......@@ -1035,9 +1035,8 @@ class ParserBase {
ExpressionT ParseConditionalContinuation(ExpressionT expression, int pos);
ExpressionT ParseBinaryContinuation(ExpressionT x, int prec, int prec1);
V8_INLINE ExpressionT ParseBinaryExpression(int prec);
ExpressionT ParseUnaryOpExpression();
ExpressionT ParseUnaryOrPrefixExpression();
ExpressionT ParseAwaitExpression();
ExpressionT ParsePrefixExpression();
V8_INLINE ExpressionT ParseUnaryExpression();
V8_INLINE ExpressionT ParsePostfixExpression();
V8_INLINE ExpressionT ParseLeftHandSideExpression();
......@@ -2896,7 +2895,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseUnaryOpExpression() {
ParserBase<Impl>::ParseUnaryOrPrefixExpression() {
Token::Value op = Next();
int pos = position();
......@@ -2909,40 +2908,34 @@ ParserBase<Impl>::ParseUnaryOpExpression() {
ExpressionT expression = ParseUnaryExpression();
if (op == Token::DELETE) {
if (impl()->IsIdentifier(expression) && is_strict(language_mode())) {
// "delete identifier" is a syntax error in strict mode.
ReportMessage(MessageTemplate::kStrictDelete);
return impl()->FailureExpression();
if (Token::IsUnaryOp(op)) {
if (op == Token::DELETE) {
if (impl()->IsIdentifier(expression) && is_strict(language_mode())) {
// "delete identifier" is a syntax error in strict mode.
ReportMessage(MessageTemplate::kStrictDelete);
return impl()->FailureExpression();
}
if (impl()->IsPropertyWithPrivateFieldKey(expression)) {
ReportMessage(MessageTemplate::kDeletePrivateField);
return impl()->FailureExpression();
}
}
if (impl()->IsPropertyWithPrivateFieldKey(expression)) {
ReportMessage(MessageTemplate::kDeletePrivateField);
if (peek() == Token::EXP) {
ReportUnexpectedToken(Next());
return impl()->FailureExpression();
}
}
if (peek() == Token::EXP) {
ReportUnexpectedToken(Next());
return impl()->FailureExpression();
// Allow the parser's implementation to rewrite the expression.
return impl()->BuildUnaryExpression(expression, op, pos);
}
// Allow the parser's implementation to rewrite the expression.
return impl()->BuildUnaryExpression(expression, op, pos);
}
DCHECK(Token::IsCountOp(op));
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParsePrefixExpression() {
Token::Value op = Next();
int beg_pos = peek_position();
CheckStackOverflow();
ExpressionT expression = ParseUnaryExpression();
if (V8_UNLIKELY(!IsValidReferenceExpression(expression))) {
expression = RewriteInvalidReferenceExpression(
expression, beg_pos, end_position(),
expression, expression->position(), end_position(),
MessageTemplate::kInvalidLhsInPrefixOp);
}
impl()->MarkExpressionAsAssigned(expression);
......@@ -2987,8 +2980,7 @@ ParserBase<Impl>::ParseUnaryExpression() {
// [+Await] AwaitExpression[?Yield]
Token::Value op = peek();
if (Token::IsUnaryOp(op)) return ParseUnaryOpExpression();
if (Token::IsCountOp(op)) return ParsePrefixExpression();
if (Token::IsUnaryOrCountOp(op)) return ParseUnaryOrPrefixExpression();
if (is_async_function() && op == Token::AWAIT) {
return ParseAwaitExpression();
}
......
......@@ -27,7 +27,8 @@ namespace internal {
#define IGNORE_TOKEN(name, string, precedence)
/* Binary operators sorted by precedence */
/* Binary operators */
/* ADD and SUB are at the end since they are UnaryOp */
#define BINARY_OP_TOKEN_LIST(T, E) \
E(T, BIT_OR, "|", 6) \
E(T, BIT_XOR, "^", 7) \
......@@ -35,12 +36,12 @@ namespace internal {
E(T, SHL, "<<", 11) \
E(T, SAR, ">>", 11) \
E(T, SHR, ">>>", 11) \
E(T, ADD, "+", 12) \
E(T, SUB, "-", 12) \
E(T, MUL, "*", 13) \
E(T, DIV, "/", 13) \
E(T, MOD, "%", 13) \
E(T, EXP, "**", 14)
E(T, EXP, "**", 14) \
E(T, ADD, "+", 12) \
E(T, SUB, "-", 12)
#define EXPAND_BINOP_ASSIGN_TOKEN(T, name, string, precedence) \
T(ASSIGN_##name, string "=", 2)
......@@ -68,8 +69,6 @@ namespace internal {
T(COLON, ":", 0) \
T(ELLIPSIS, "...", 0) \
T(CONDITIONAL, "?", 3) \
T(INC, "++", 0) \
T(DEC, "--", 0) \
/* BEGIN AutoSemicolon */ \
T(SEMICOLON, ";", 0) \
T(RBRACE, "}", 0) \
......@@ -94,8 +93,24 @@ namespace internal {
T(COMMA, ",", 1) \
T(OR, "||", 4) \
T(AND, "&&", 5) \
\
/* Unary operators, starting at ADD in BINARY_OP_TOKEN_LIST */ \
/* IsUnaryOp() relies on this block of enum values */ \
/* being contiguous and sorted in the same order! */ \
BINARY_OP_TOKEN_LIST(T, EXPAND_BINOP_TOKEN) \
\
T(NOT, "!", 0) \
T(BIT_NOT, "~", 0) \
K(DELETE, "delete", 0) \
K(TYPEOF, "typeof", 0) \
K(VOID, "void", 0) \
\
/* BEGIN IsCountOp */ \
T(INC, "++", 0) \
T(DEC, "--", 0) \
/* END IsCountOp */ \
/* END IsUnaryOrCountOp */ \
\
/* Compare operators sorted by precedence. */ \
/* IsCompareOp() relies on this block of enum values */ \
/* being contiguous and sorted in the same order! */ \
......@@ -110,15 +125,6 @@ namespace internal {
K(INSTANCEOF, "instanceof", 10) \
K(IN, "in", 10) \
\
/* Unary operators. */ \
/* IsUnaryOp() relies on this block of enum values */ \
/* being contiguous and sorted in the same order! */ \
T(NOT, "!", 0) \
T(BIT_NOT, "~", 0) \
K(DELETE, "delete", 0) \
K(TYPEOF, "typeof", 0) \
K(VOID, "void", 0) \
\
/* Keywords (ECMA-262, section 7.5.2, page 13). */ \
K(BREAK, "break", 0) \
K(CASE, "case", 0) \
......@@ -246,14 +252,14 @@ class Token {
}
static bool IsArrowOrAssignmentOp(Value token) {
return IsInRange(token, ARROW, ASSIGN_EXP);
return IsInRange(token, ARROW, ASSIGN_SUB);
}
static bool IsAssignmentOp(Value token) {
return IsInRange(token, INIT, ASSIGN_EXP);
return IsInRange(token, INIT, ASSIGN_SUB);
}
static bool IsBinaryOp(Value op) { return IsInRange(op, COMMA, EXP); }
static bool IsBinaryOp(Value op) { return IsInRange(op, COMMA, SUB); }
static bool IsCompareOp(Value op) { return IsInRange(op, EQ, IN); }
......@@ -264,7 +270,7 @@ class Token {
static bool IsEqualityOp(Value op) { return IsInRange(op, EQ, EQ_STRICT); }
static Value BinaryOpForAssignment(Value op) {
DCHECK(IsInRange(op, ASSIGN_BIT_OR, ASSIGN_EXP));
DCHECK(IsInRange(op, ASSIGN_BIT_OR, ASSIGN_SUB));
Value result = static_cast<Value>(op - ASSIGN_BIT_OR + BIT_OR);
DCHECK(IsBinaryOp(result));
return result;
......@@ -274,12 +280,9 @@ class Token {
return IsInRange(op, BIT_OR, SHR) || op == BIT_NOT;
}
static bool IsUnaryOp(Value op) {
return IsInRange(op, NOT, VOID) || IsInRange(op, ADD, SUB);
}
static bool IsUnaryOp(Value op) { return IsInRange(op, ADD, VOID); }
static bool IsCountOp(Value op) { return IsInRange(op, INC, DEC); }
static bool IsUnaryOrCountOp(Value op) { return IsInRange(op, ADD, DEC); }
static bool IsShiftOp(Value op) { return IsInRange(op, SHL, SHR); }
// Returns a string corresponding to the JS token string
......
......@@ -434,6 +434,14 @@ TEST(IsCountOp) {
}
}
TEST(IsUnaryOrCountOp) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsUnaryOp(token) || TokenIsCountOp(token),
Token::IsUnaryOrCountOp(token));
}
}
bool TokenIsShiftOp(Token::Value token) {
switch (token) {
case Token::SHL:
......
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