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