Commit 33c6f120 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[parser] Cleanup property name parsing, introduce token flags

- Rename methods,
- Introduce flags for tokens to lookup IsKeyword and IsPropertyName
- Remove "contextual keyword" leftover code.
- Inline ParsePropertyName into ParsePropertyNameOrPrivatePropertyName
  since public is more likely than private.

Change-Id: Ib7633ef3c46889ecafc7a6c929029845bb8ef15c
Reviewed-on: https://chromium-review.googlesource.com/c/1357052
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57993}
parent dac7aa0f
......@@ -1047,9 +1047,9 @@ class ParserBase {
is_strict_reserved);
}
V8_INLINE IdentifierT ParseIdentifierName();
V8_INLINE IdentifierT ParsePropertyName();
ExpressionT ParseIdentifierNameOrPrivateName();
ExpressionT ParsePropertyOrPrivatePropertyName();
ExpressionT ParseRegExpLiteral();
......@@ -1077,7 +1077,7 @@ class ParserBase {
ParsePropertyKind::kAccessorSetter);
}
ExpressionT ParsePropertyName(ParsePropertyInfo* prop_info);
ExpressionT ParseProperty(ParsePropertyInfo* prop_info);
ExpressionT ParseObjectLiteral();
ClassLiteralPropertyT ParseClassPropertyDefinition(
ClassInfo* class_info, ParsePropertyInfo* prop_info, bool has_extends);
......@@ -1588,32 +1588,33 @@ ParserBase<Impl>::ParseIdentifierOrStrictReservedWord(
}
template <typename Impl>
typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifierName() {
typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParsePropertyName() {
Token::Value next = Next();
if (!Token::IsAnyIdentifier(next) && next != Token::ESCAPED_KEYWORD &&
!Token::IsKeyword(next)) {
if (V8_LIKELY(Token::IsPropertyName(next))) return impl()->GetSymbol();
ReportUnexpectedToken(next);
return impl()->EmptyIdentifierString();
}
return impl()->GetSymbol();
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseIdentifierNameOrPrivateName() {
ParserBase<Impl>::ParsePropertyOrPrivatePropertyName() {
int pos = position();
IdentifierT name;
ExpressionT key;
if (allow_harmony_private_fields() && Check(Token::PRIVATE_NAME)) {
Token::Value next = Next();
if (V8_LIKELY(Token::IsPropertyName(next))) {
name = impl()->GetSymbol();
key = factory()->NewStringLiteral(name, pos);
} else if (allow_harmony_private_fields() && next == Token::PRIVATE_NAME) {
name = impl()->GetSymbol();
auto key_proxy =
impl()->ExpressionFromIdentifier(name, pos, InferName::kNo);
key_proxy->set_is_private_name();
key = key_proxy;
} else {
name = ParseIdentifierName();
key = factory()->NewStringLiteral(name, pos);
ReportUnexpectedToken(next);
return impl()->FailureExpression();
}
impl()->PushLiteralName(name);
return key;
......@@ -1963,7 +1964,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() {
}
template <class Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseProperty(
ParsePropertyInfo* prop_info) {
DCHECK_EQ(prop_info->kind, ParsePropertyKind::kNotSet);
DCHECK_EQ(prop_info->function_flags, ParseFunctionFlag::kIsNormal);
......@@ -2100,7 +2101,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
V8_FALLTHROUGH;
default:
prop_info->name = ParseIdentifierName();
prop_info->name = ParsePropertyName();
is_array_index = false;
break;
}
......@@ -2149,10 +2150,10 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassInfo* class_info,
return impl()->NullLiteralProperty();
} else {
prop_info->is_static = true;
name_expression = ParsePropertyName(prop_info);
name_expression = ParseProperty(prop_info);
}
} else {
name_expression = ParsePropertyName(prop_info);
name_expression = ParseProperty(prop_info);
}
if (!class_info->has_name_static_property && prop_info->is_static &&
......@@ -2333,7 +2334,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
Token::Value name_token = peek();
Scanner::Location next_loc = scanner()->peek_location();
ExpressionT name_expression = ParsePropertyName(prop_info);
ExpressionT name_expression = ParseProperty(prop_info);
IdentifierT name = prop_info->name;
ParseFunctionFlags function_flags = prop_info->function_flags;
ParsePropertyKind kind = prop_info->kind;
......@@ -3116,7 +3117,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
case Token::PERIOD: {
Consume(Token::PERIOD);
int pos = position();
ExpressionT key = ParseIdentifierNameOrPrivateName();
ExpressionT key = ParsePropertyOrPrivatePropertyName();
result = factory()->NewProperty(result, key, pos);
break;
}
......@@ -3422,7 +3423,7 @@ ParserBase<Impl>::DoParseMemberExpressionContinuation(ExpressionT expression) {
case Token::PERIOD: {
Consume(Token::PERIOD);
int pos = peek_position();
ExpressionT key = ParseIdentifierNameOrPrivateName();
ExpressionT key = ParsePropertyOrPrivatePropertyName();
expression = factory()->NewProperty(expression, key, pos);
break;
}
......
......@@ -918,11 +918,11 @@ ZoneChunkList<Parser::ExportClauseData>* Parser::ParseExportClause(
parsing_module_)) {
*reserved_loc = scanner()->location();
}
const AstRawString* local_name = ParseIdentifierName();
const AstRawString* local_name = ParsePropertyName();
const AstRawString* export_name = nullptr;
Scanner::Location location = scanner()->location();
if (CheckContextualKeyword(ast_value_factory()->as_string())) {
export_name = ParseIdentifierName();
export_name = ParsePropertyName();
// Set the location to the whole "a as b" string, so that it makes sense
// both for errors due to "a" and for errors due to "b".
location.end_pos = scanner()->location().end_pos;
......@@ -960,14 +960,14 @@ ZonePtrList<const Parser::NamedImport>* Parser::ParseNamedImports(int pos) {
auto result = new (zone()) ZonePtrList<const NamedImport>(1, zone());
while (peek() != Token::RBRACE) {
const AstRawString* import_name = ParseIdentifierName();
const AstRawString* import_name = ParsePropertyName();
const AstRawString* local_name = import_name;
Scanner::Location location = scanner()->location();
// In the presence of 'as', the left-side of the 'as' can
// be any IdentifierName. But without 'as', it must be a valid
// BindingIdentifier.
if (CheckContextualKeyword(ast_value_factory()->as_string())) {
local_name = ParseIdentifierName();
local_name = ParsePropertyName();
}
if (!Token::IsValidIdentifier(scanner()->current_token(),
LanguageMode::kStrict, false,
......@@ -1199,7 +1199,7 @@ void Parser::ParseExportStar() {
// import * as .x from "..."; export {.x as x};
ExpectContextualKeyword(ast_value_factory()->as_string());
const AstRawString* export_name = ParseIdentifierName();
const AstRawString* export_name = ParsePropertyName();
Scanner::Location export_name_loc = scanner()->location();
const AstRawString* local_name = NextInternalNamespaceExportName();
Scanner::Location local_name_loc = Scanner::Location::invalid();
......
......@@ -10,37 +10,37 @@ namespace v8 {
namespace internal {
#define T(name, string, precedence) #name,
const char* const Token::name_[NUM_TOKENS] = {TOKEN_LIST(T, T, T)};
const char* const Token::name_[NUM_TOKENS] = {TOKEN_LIST(T, T)};
#undef T
#define T(name, string, precedence) string,
const char* const Token::string_[NUM_TOKENS] = {TOKEN_LIST(T, T, T)};
const char* const Token::string_[NUM_TOKENS] = {TOKEN_LIST(T, T)};
#undef T
constexpr uint8_t length(const char* str) {
return str ? static_cast<uint8_t>(strlen(str)) : 0;
}
#define T(name, string, precedence) length(string),
const uint8_t Token::string_length_[NUM_TOKENS] = {TOKEN_LIST(T, T, T)};
const uint8_t Token::string_length_[NUM_TOKENS] = {TOKEN_LIST(T, T)};
#undef T
#define T1(name, string, precedence) \
((Token::name == Token::IN) ? 0 : precedence),
#define T2(name, string, precedence) precedence,
// precedence_[0] for accept_IN == false, precedence_[1] for accept_IN = true.
const int8_t Token::precedence_[2][NUM_TOKENS] = {{TOKEN_LIST(T1, T1, T1)},
{TOKEN_LIST(T2, T2, T2)}};
const int8_t Token::precedence_[2][NUM_TOKENS] = {{TOKEN_LIST(T1, T1)},
{TOKEN_LIST(T2, T2)}};
#undef T2
#undef T1
#define KT(a, b, c) 'T',
#define KK(a, b, c) 'K',
#define KC(a, b, c) 'C',
const char Token::token_type[] = {TOKEN_LIST(KT, KK, KC)};
#define KT(a, b, c) \
IsPropertyNameBits::encode(Token::IsAnyIdentifier(a) || a == ESCAPED_KEYWORD),
#define KK(a, b, c) \
IsKeywordBits::encode(true) | IsPropertyNameBits::encode(true),
const uint8_t Token::token_flags[] = {TOKEN_LIST(KT, KK)};
#undef KT
#undef KK
#undef KC
} // namespace internal
} // namespace v8
......@@ -49,7 +49,7 @@ namespace internal {
#define EXPAND_BINOP_TOKEN(T, name, string, precedence) \
T(name, string, precedence)
#define TOKEN_LIST(T, K, C) \
#define TOKEN_LIST(T, K) \
\
/* BEGIN PropertyOrCall */ \
/* BEGIN Member */ \
......@@ -203,7 +203,7 @@ class Token {
public:
// All token values.
#define T(name, string, precedence) name,
enum Value : uint8_t { TOKEN_LIST(T, T, T) NUM_TOKENS };
enum Value : uint8_t { TOKEN_LIST(T, T) NUM_TOKENS };
#undef T
// Returns a string corresponding to the C++ token name
......@@ -213,10 +213,17 @@ class Token {
return name_[token];
}
static char TypeForTesting(Value token) { return token_type[token]; }
class IsKeywordBits : public BitField8<bool, 0, 1> {};
class IsPropertyNameBits : public BitField8<bool, IsKeywordBits::kNext, 1> {};
// Predicates
static bool IsKeyword(Value token) { return token_type[token] == 'K'; }
static bool IsKeyword(Value token) {
return IsKeywordBits::decode(token_flags[token]);
}
static bool IsPropertyName(Value token) {
return IsPropertyNameBits::decode(token_flags[token]);
}
V8_INLINE static bool IsValidIdentifier(Value token,
LanguageMode language_mode,
......@@ -323,7 +330,7 @@ class Token {
static const char* const string_[NUM_TOKENS];
static const uint8_t string_length_[NUM_TOKENS];
static const int8_t precedence_[2][NUM_TOKENS];
static const char token_type[NUM_TOKENS];
static const uint8_t token_flags[NUM_TOKENS];
};
} // namespace internal
......
......@@ -342,18 +342,20 @@ class BitFieldBase {
}
// Returns a type U with the bit field value encoded.
static U encode(T value) {
static constexpr U encode(T value) {
#if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
DCHECK(is_valid(value));
#endif
return static_cast<U>(value) << shift;
}
// Returns a type U with the bit field value updated.
static U update(U previous, T value) {
static constexpr U update(U previous, T value) {
return (previous & ~kMask) | encode(value);
}
// Extracts the bit field from the value.
static T decode(U value) {
static constexpr T decode(U value) {
return static_cast<T>((value & kMask) >> shift);
}
......
......@@ -502,7 +502,7 @@ TEST(ScanKeywords) {
static const KeywordToken keywords[] = {
#define KEYWORD(t, s, d) { s, i::Token::t },
TOKEN_LIST(IGNORE_TOKEN, KEYWORD, IGNORE_TOKEN)
TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
#undef KEYWORD
{nullptr, i::Token::IDENTIFIER}};
......
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