Commit 32838756 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[parser] Restore trivial expression grammar shortcuts with range-based condition

Change-Id: I04385d44f6175f7b391fb07ec4f1beb9abd4d22f
Reviewed-on: https://chromium-review.googlesource.com/1194033Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55500}
parent 9a0f2546
......@@ -1297,6 +1297,7 @@ class ParserBase {
bool* ok);
bool IsNextLetKeyword();
bool IsTrivialExpression();
// Checks if the expression is a valid reference expression (e.g., on the
// left-hand side of assignments). Although ruled out by ECMA as early errors,
......@@ -2882,7 +2883,14 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
ArrowFormalParametersUnexpectedToken();
}
ExpressionT expression = ParseConditionalExpression(accept_IN, CHECK_OK);
// Parse a simple, faster sub-grammar (primary expression) if it's evident
// that we have only a trivial expression to parse.
ExpressionT expression;
if (IsTrivialExpression()) {
expression = ParsePrimaryExpression(&is_async, CHECK_OK);
} else {
expression = ParseConditionalExpression(accept_IN, CHECK_OK);
}
if (is_async && impl()->IsIdentifier(expression) && peek_any_identifier() &&
PeekAhead() == Token::ARROW) {
......@@ -4313,6 +4321,20 @@ bool ParserBase<Impl>::IsNextLetKeyword() {
}
}
template <typename Impl>
bool ParserBase<Impl>::IsTrivialExpression() {
if (Token::IsTrivialExpressionToken(peek())) {
// PeekAhead() may not always be called, so we only call it after checking
// peek().
Token::Value peek_ahead = PeekAhead();
if (peek_ahead == Token::COMMA || peek_ahead == Token::RPAREN ||
peek_ahead == Token::SEMICOLON || peek_ahead == Token::RBRACK) {
return true;
}
}
return false;
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseArrowFunctionLiteral(
......
......@@ -131,7 +131,6 @@ namespace internal {
K(NEW, "new", 0) \
K(RETURN, "return", 0) \
K(SWITCH, "switch", 0) \
K(THIS, "this", 0) \
K(THROW, "throw", 0) \
K(TRY, "try", 0) \
/* TYPEOF */ \
......@@ -139,6 +138,7 @@ namespace internal {
/* VOID */ \
K(WHILE, "while", 0) \
K(WITH, "with", 0) \
K(THIS, "this", 0) \
\
/* Literals (ECMA-262, section 7.8, page 16). */ \
K(NULL_LITERAL, "null", 0) \
......@@ -278,6 +278,10 @@ class Token {
static bool IsShiftOp(Value op) { return IsInRange(op, SHL, SHR); }
static bool IsTrivialExpressionToken(Value op) {
return IsInRange(op, THIS, IDENTIFIER);
}
// Returns a string corresponding to the JS token string
// (.e., "<" for the token LT) or nullptr if the token doesn't
// have a (unique) string (e.g. an IDENTIFIER).
......
......@@ -277,6 +277,31 @@ TEST(IsShiftOp) {
}
}
bool TokenIsTrivialExpressionToken(Token::Value tok) {
switch (tok) {
case Token::SMI:
case Token::NUMBER:
case Token::BIGINT:
case Token::NULL_LITERAL:
case Token::TRUE_LITERAL:
case Token::FALSE_LITERAL:
case Token::STRING:
case Token::IDENTIFIER:
case Token::THIS:
return true;
default:
return false;
}
}
TEST(IsTrivialExpressionToken) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsTrivialExpressionToken(tok),
Token::IsTrivialExpressionToken(tok));
}
}
TEST(ScanKeywords) {
struct KeywordToken {
const char* keyword;
......
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