Commit 93fea343 authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[parser] Use more range checks to reduce branches

- Introduce Token::IsLiteral helper
- Introduce Token::IsStrictReservedWord helper


Drive-by-fix:
- Use "token" instead of "tok" as variable name
- Keep enum order consistent accross files

Change-Id: Ie3b30a62dfbea761a31c32465c0afa681d326710
Reviewed-on: https://chromium-review.googlesource.com/1203952Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55804}
parent a15ad0d3
......@@ -1727,9 +1727,7 @@ ParserBase<Impl>::ParseAndClassifyIdentifier(bool* ok) {
}
return name;
} else if (is_sloppy(language_mode()) &&
(next == Token::FUTURE_STRICT_RESERVED_WORD ||
next == Token::ESCAPED_STRICT_RESERVED_WORD ||
next == Token::LET || next == Token::STATIC ||
(Token::IsStrictReservedWord(next) ||
(next == Token::YIELD && !is_generator()))) {
classifier()->RecordStrictModeFormalParameterError(
scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
......@@ -1762,9 +1760,7 @@ ParserBase<Impl>::ParseIdentifierOrStrictReservedWord(
next == Token::ASYNC) {
*is_strict_reserved = false;
*is_await = next == Token::AWAIT;
} else if (next == Token::ESCAPED_STRICT_RESERVED_WORD ||
next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
next == Token::STATIC ||
} else if (Token::IsStrictReservedWord(next) ||
(next == Token::YIELD && !IsGeneratorFunction(function_kind))) {
*is_strict_reserved = true;
} else {
......@@ -1780,12 +1776,8 @@ template <typename Impl>
typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifierName(
bool* ok) {
Token::Value next = Next();
if (next != Token::IDENTIFIER && next != Token::ASYNC &&
next != Token::ENUM && next != Token::AWAIT && next != Token::LET &&
next != Token::STATIC && next != Token::YIELD &&
next != Token::FUTURE_STRICT_RESERVED_WORD &&
next != Token::ESCAPED_KEYWORD &&
next != Token::ESCAPED_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
if (!Token::IsAnyIdentifier(next) && next != Token::ESCAPED_KEYWORD &&
!Token::IsKeyword(next)) {
ReportUnexpectedToken(next);
*ok = false;
return impl()->NullIdentifier();
......@@ -1860,7 +1852,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
// AsyncFunctionLiteral
int beg_pos = peek_position();
switch (peek()) {
Token::Value token = peek();
switch (token) {
case Token::THIS: {
BindingPatternUnexpectedToken();
Consume(Token::THIS);
......@@ -1872,9 +1865,18 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::FALSE_LITERAL:
case Token::SMI:
case Token::NUMBER:
case Token::BIGINT:
case Token::BIGINT: {
// Ensure continuous enum range.
DCHECK(Token::IsLiteral(token));
BindingPatternUnexpectedToken();
return impl()->ExpressionFromLiteral(Next(), beg_pos);
}
case Token::STRING: {
DCHECK(Token::IsLiteral(token));
BindingPatternUnexpectedToken();
Consume(Token::STRING);
return impl()->ExpressionFromString(beg_pos);
}
case Token::ASYNC:
if (!scanner()->HasLineTerminatorAfterNext() &&
......@@ -1891,19 +1893,16 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::STATIC:
case Token::YIELD:
case Token::AWAIT:
case Token::ESCAPED_STRICT_RESERVED_WORD:
case Token::FUTURE_STRICT_RESERVED_WORD: {
case Token::FUTURE_STRICT_RESERVED_WORD:
case Token::ESCAPED_STRICT_RESERVED_WORD: {
// Ensure continuous enum range.
DCHECK(IsInRange(token, Token::IDENTIFIER,
Token::ESCAPED_STRICT_RESERVED_WORD));
// Using eval or arguments in this context is OK even in strict mode.
IdentifierT name = ParseAndClassifyIdentifier(CHECK_OK);
return impl()->ExpressionFromIdentifier(name, beg_pos);
}
case Token::STRING: {
BindingPatternUnexpectedToken();
Consume(Token::STRING);
return impl()->ExpressionFromString(beg_pos);
}
case Token::ASSIGN_DIV:
case Token::DIV:
classifier()->RecordBindingPatternError(
......@@ -1919,8 +1918,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::LPAREN: {
// Arrow function formal parameters are either a single identifier or a
// list of BindingPattern productions enclosed in parentheses.
// Parentheses are not valid on the LHS of a BindingPattern, so we use the
// is_valid_binding_pattern() check to detect multiple levels of
// Parentheses are not valid on the LHS of a BindingPattern, so we use
// the is_valid_binding_pattern() check to detect multiple levels of
// parenthesization.
bool pattern_error = !classifier()->is_valid_binding_pattern();
classifier()->RecordPatternError(scanner()->peek_location(),
......
......@@ -146,23 +146,23 @@ namespace internal {
K(FALSE_LITERAL, "false", 0) \
T(NUMBER, nullptr, 0) \
T(SMI, nullptr, 0) \
T(STRING, nullptr, 0) \
T(BIGINT, nullptr, 0) \
T(STRING, nullptr, 0) \
\
/* BEGIN AnyIdentifier. */ \
/* BEGIN AnyIdentifier */ \
/* Identifiers (not keywords or future reserved words). */ \
T(IDENTIFIER, nullptr, 0) \
K(ASYNC, "async", 0) \
/* `await` is a reserved word in module code only */ \
K(AWAIT, "await", 0) \
K(YIELD, "yield", 0) \
K(LET, "let", 0) \
K(STATIC, "static", 0) \
/* Future reserved words (ECMA-262, section 7.6.1.2). */ \
T(FUTURE_STRICT_RESERVED_WORD, nullptr, 0) \
T(ESCAPED_STRICT_RESERVED_WORD, nullptr, 0) \
K(LET, "let", 0) \
K(STATIC, "static", 0) \
K(ENUM, "enum", 0) \
/* `await` is a reserved word in module code only */ \
K(AWAIT, "await", 0) \
K(YIELD, "yield", 0) \
/* END AnyIdentifier. */ \
/* END AnyIdentifier */ \
K(CLASS, "class", 0) \
K(CONST, "const", 0) \
K(EXPORT, "export", 0) \
......@@ -211,38 +211,44 @@ class Token {
// Returns a string corresponding to the C++ token name
// (e.g. "LT" for the token LT).
static const char* Name(Value tok) {
DCHECK_GT(NUM_TOKENS, tok); // tok is unsigned
return name_[tok];
static const char* Name(Value token) {
DCHECK_GT(NUM_TOKENS, token); // token is unsigned
return name_[token];
}
static char TypeForTesting(Value tok) { return token_type[tok]; }
static char TypeForTesting(Value token) { return token_type[token]; }
// Predicates
static bool IsKeyword(Value tok) {
return token_type[tok] == 'K';
}
static bool IsContextualKeyword(Value tok) {
return IsInRange(tok, GET, ANONYMOUS);
static bool IsKeyword(Value token) { return token_type[token] == 'K'; }
static bool IsContextualKeyword(Value token) {
return IsInRange(token, GET, ANONYMOUS);
}
static bool IsIdentifier(Value tok, LanguageMode language_mode,
static bool IsIdentifier(Value token, LanguageMode language_mode,
bool is_generator, bool disallow_await) {
if (IsInRange(tok, IDENTIFIER, ASYNC)) return true;
if (IsInRange(tok, FUTURE_STRICT_RESERVED_WORD, STATIC)) {
if (IsInRange(token, IDENTIFIER, ASYNC)) return true;
if (IsInRange(token, LET, ESCAPED_STRICT_RESERVED_WORD)) {
return is_sloppy(language_mode);
}
if (tok == AWAIT) return !disallow_await;
if (tok == YIELD) return !is_generator && is_sloppy(language_mode);
if (token == AWAIT) return !disallow_await;
if (token == YIELD) return !is_generator && is_sloppy(language_mode);
return false;
}
static bool IsAnyIdentifier(Value tok) {
return IsInRange(tok, IDENTIFIER, YIELD);
static bool IsAnyIdentifier(Value token) {
return IsInRange(token, IDENTIFIER, ENUM);
}
static bool IsStrictReservedWord(Value token) {
return IsInRange(token, LET, ESCAPED_STRICT_RESERVED_WORD);
}
static bool IsLiteral(Value token) {
return IsInRange(token, NULL_LITERAL, STRING);
}
static bool IsAssignmentOp(Value tok) {
return IsInRange(tok, INIT, ASSIGN_EXP);
static bool IsAssignmentOp(Value token) {
return IsInRange(token, INIT, ASSIGN_EXP);
}
static bool IsGetOrSet(Value op) { return IsInRange(op, GET, SET); }
......@@ -282,21 +288,21 @@ class Token {
// 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).
static const char* String(Value tok) {
DCHECK_GT(NUM_TOKENS, tok); // tok is unsigned
return string_[tok];
static const char* String(Value token) {
DCHECK_GT(NUM_TOKENS, token); // token is unsigned
return string_[token];
}
static uint8_t StringLength(Value tok) {
DCHECK_GT(NUM_TOKENS, tok); // tok is unsigned
return string_length_[tok];
static uint8_t StringLength(Value token) {
DCHECK_GT(NUM_TOKENS, token); // token is unsigned
return string_length_[token];
}
// Returns the precedence > 0 for binary and compare
// operators; returns 0 otherwise.
static int Precedence(Value tok) {
DCHECK_GT(NUM_TOKENS, tok); // tok is unsigned
return precedence_[tok];
static int Precedence(Value token) {
DCHECK_GT(NUM_TOKENS, token); // token is unsigned
return precedence_[token];
}
private:
......
This diff is collapsed.
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