[parser] Restructure identifier classifying
- Rely more heavily on Token::IsValidIdentifier. - Deal with IsLet() when it's possibly a lexical declaration. - Remove ENUM from the default IsAnyIdentifier range. - Always pre-check whether IsAnyIdentifier before classifying identifiers. Change-Id: I55eae6ff65dc306b466fa29d233c715e85bc3854 Reviewed-on: https://chromium-review.googlesource.com/c/1356514 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/master@{#57977}
This commit is contained in:
parent
8fd93c827d
commit
298aefa600
@ -1039,13 +1039,12 @@ class ParserBase {
|
||||
// for the case of parsing the identifier in a function expression, where the
|
||||
// relevant "function_kind" bit is of the function being parsed, not the
|
||||
// containing function.
|
||||
IdentifierT ParseIdentifierOrStrictReservedWord(FunctionKind function_kind,
|
||||
bool* is_strict_reserved,
|
||||
bool* is_await);
|
||||
IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
|
||||
bool* is_await) {
|
||||
V8_INLINE IdentifierT ParseIdentifierOrStrictReservedWord(
|
||||
FunctionKind function_kind, bool* is_strict_reserved);
|
||||
V8_INLINE IdentifierT
|
||||
ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved) {
|
||||
return ParseIdentifierOrStrictReservedWord(function_state_->kind(),
|
||||
is_strict_reserved, is_await);
|
||||
is_strict_reserved);
|
||||
}
|
||||
|
||||
V8_INLINE IdentifierT ParseIdentifierName();
|
||||
@ -1540,52 +1539,47 @@ template <typename Impl>
|
||||
typename ParserBase<Impl>::IdentifierT
|
||||
ParserBase<Impl>::ParseAndClassifyIdentifier() {
|
||||
Token::Value next = Next();
|
||||
STATIC_ASSERT(Token::IDENTIFIER + 1 == Token::ASYNC);
|
||||
if (IsInRange(next, Token::IDENTIFIER, Token::ASYNC)) {
|
||||
IdentifierT name = impl()->GetSymbol();
|
||||
|
||||
STATIC_ASSERT(Token::IDENTIFIER + 1 == Token::ASYNC);
|
||||
if (V8_LIKELY(IsInRange(next, Token::IDENTIFIER, Token::ASYNC))) {
|
||||
IdentifierT name = impl()->GetSymbol();
|
||||
if (V8_UNLIKELY(impl()->IsArguments(name) &&
|
||||
scope()->ShouldBanArguments())) {
|
||||
ReportMessage(MessageTemplate::kArgumentsDisallowedInInitializer);
|
||||
return impl()->EmptyIdentifierString();
|
||||
}
|
||||
|
||||
return name;
|
||||
} else if (next == Token::AWAIT && !parsing_module_ && !is_async_function()) {
|
||||
classifier()->RecordAsyncArrowFormalParametersError(
|
||||
scanner()->location(), MessageTemplate::kAwaitBindingIdentifier);
|
||||
return impl()->GetSymbol();
|
||||
} else if (is_sloppy(language_mode()) &&
|
||||
(Token::IsStrictReservedWord(next) ||
|
||||
(next == Token::YIELD && !is_generator()))) {
|
||||
IdentifierT name = impl()->GetSymbol();
|
||||
classifier()->RecordStrictModeFormalParameterError(
|
||||
scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
|
||||
if (impl()->IdentifierEquals(name, ast_value_factory()->let_string())) {
|
||||
classifier()->RecordLetPatternError(
|
||||
scanner()->location(), MessageTemplate::kLetInLexicalBinding);
|
||||
}
|
||||
return name;
|
||||
} else {
|
||||
|
||||
if (!Token::IsValidIdentifier(next, language_mode(), this->is_generator(),
|
||||
parsing_module_ || is_async_function())) {
|
||||
ReportUnexpectedToken(next);
|
||||
return impl()->EmptyIdentifierString();
|
||||
}
|
||||
|
||||
if (next == Token::AWAIT) {
|
||||
classifier()->RecordAsyncArrowFormalParametersError(
|
||||
scanner()->location(), MessageTemplate::kAwaitBindingIdentifier);
|
||||
return impl()->GetSymbol();
|
||||
}
|
||||
|
||||
DCHECK(Token::IsStrictReservedWord(next));
|
||||
classifier()->RecordStrictModeFormalParameterError(
|
||||
scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
|
||||
return impl()->GetSymbol();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
typename ParserBase<Impl>::IdentifierT
|
||||
ParserBase<Impl>::ParseIdentifierOrStrictReservedWord(
|
||||
FunctionKind function_kind, bool* is_strict_reserved, bool* is_await) {
|
||||
FunctionKind function_kind, bool* is_strict_reserved) {
|
||||
Token::Value next = Next();
|
||||
if (next == Token::IDENTIFIER || (next == Token::AWAIT && !parsing_module_ &&
|
||||
!IsAsyncFunction(function_kind)) ||
|
||||
next == Token::ASYNC) {
|
||||
*is_strict_reserved = false;
|
||||
*is_await = next == Token::AWAIT;
|
||||
} else if (Token::IsStrictReservedWord(next) ||
|
||||
(next == Token::YIELD && !IsGeneratorFunction(function_kind))) {
|
||||
*is_strict_reserved = true;
|
||||
} else {
|
||||
|
||||
*is_strict_reserved = Token::IsStrictReservedWord(next);
|
||||
|
||||
if (!Token::IsValidIdentifier(
|
||||
next, language_mode(), IsGeneratorFunction(function_kind),
|
||||
parsing_module_ || IsAsyncFunction(function_kind))) {
|
||||
ReportUnexpectedToken(next);
|
||||
return impl()->EmptyIdentifierString();
|
||||
}
|
||||
@ -1596,7 +1590,7 @@ ParserBase<Impl>::ParseIdentifierOrStrictReservedWord(
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifierName() {
|
||||
Token::Value next = Next();
|
||||
if (!Token::IsAnyIdentifier(next) && next != Token::ESCAPED_KEYWORD &&
|
||||
if (!Token::IsAnyIdentifierOrEnum(next) && next != Token::ESCAPED_KEYWORD &&
|
||||
!Token::IsKeyword(next)) {
|
||||
ReportUnexpectedToken(next);
|
||||
return impl()->EmptyIdentifierString();
|
||||
@ -1709,8 +1703,7 @@ ParserBase<Impl>::ParsePrimaryExpression() {
|
||||
int beg_pos = peek_position();
|
||||
Token::Value token = peek();
|
||||
|
||||
if (IsInRange(token, Token::IDENTIFIER,
|
||||
Token::ESCAPED_STRICT_RESERVED_WORD)) {
|
||||
if (Token::IsAnyIdentifier(token)) {
|
||||
// Using eval or arguments in this context is OK even in strict mode.
|
||||
IdentifierT name = ParseAndClassifyIdentifier();
|
||||
InferName infer = InferName::kYes;
|
||||
@ -1743,7 +1736,6 @@ ParserBase<Impl>::ParsePrimaryExpression() {
|
||||
}
|
||||
return impl()->ExpressionFromIdentifier(name, beg_pos, infer);
|
||||
}
|
||||
DCHECK_IMPLIES(Token::IsAnyIdentifier(token), token == Token::ENUM);
|
||||
|
||||
if (Token::IsLiteral(token)) {
|
||||
return impl()->ExpressionFromLiteral(Next(), beg_pos);
|
||||
@ -1804,14 +1796,10 @@ ParserBase<Impl>::ParsePrimaryExpression() {
|
||||
bool is_strict_reserved_name = false;
|
||||
Scanner::Location class_name_location = Scanner::Location::invalid();
|
||||
if (peek_any_identifier()) {
|
||||
bool is_await = false;
|
||||
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
|
||||
&is_await);
|
||||
name = ParseAndClassifyIdentifier();
|
||||
class_name_location = scanner()->location();
|
||||
if (is_await) {
|
||||
classifier()->RecordAsyncArrowFormalParametersError(
|
||||
scanner()->location(), MessageTemplate::kAwaitBindingIdentifier);
|
||||
}
|
||||
is_strict_reserved_name =
|
||||
Token::IsStrictReservedWord(scanner()->current_token());
|
||||
}
|
||||
return ParseClassLiteral(name, class_name_location,
|
||||
is_strict_reserved_name, class_token_pos);
|
||||
@ -2397,7 +2385,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
|
||||
// IdentifierReference Initializer?
|
||||
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
|
||||
|
||||
if (!Token::IsIdentifier(name_token, language_mode(),
|
||||
if (!Token::IsValidIdentifier(name_token, language_mode(),
|
||||
this->is_generator(),
|
||||
parsing_module_ || is_async_function())) {
|
||||
ReportUnexpectedToken(Next());
|
||||
@ -3282,9 +3270,8 @@ ParserBase<Impl>::ParseFunctionExpression() {
|
||||
scanner()->CurrentSymbol(ast_value_factory()) ==
|
||||
ast_value_factory()->anonymous_string());
|
||||
} else if (peek_any_identifier()) {
|
||||
bool is_await = false;
|
||||
name = ParseIdentifierOrStrictReservedWord(
|
||||
function_kind, &is_strict_reserved_name, &is_await);
|
||||
name = ParseIdentifierOrStrictReservedWord(function_kind,
|
||||
&is_strict_reserved_name);
|
||||
function_name_location = scanner()->location();
|
||||
function_type = FunctionLiteral::kNamedExpression;
|
||||
}
|
||||
@ -3600,9 +3587,17 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
|
||||
pattern = ParseBindingPattern();
|
||||
|
||||
if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
|
||||
if (impl()->IsIdentifier(pattern)) {
|
||||
if (impl()->IsLet(impl()->AsIdentifier(pattern))) {
|
||||
impl()->ReportMessageAt(
|
||||
Scanner::Location(bindings_start, end_position()),
|
||||
MessageTemplate::kLetInLexicalBinding);
|
||||
}
|
||||
} else {
|
||||
ValidateLetPattern();
|
||||
}
|
||||
}
|
||||
}
|
||||
Scanner::Location variable_loc = scanner()->location();
|
||||
|
||||
bool single_name = impl()->IsIdentifier(pattern);
|
||||
@ -3746,8 +3741,7 @@ ParserBase<Impl>::ParseHoistableDeclaration(
|
||||
name_validity = kSkipFunctionNameCheck;
|
||||
} else {
|
||||
bool is_strict_reserved = false;
|
||||
bool is_await = false;
|
||||
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, &is_await);
|
||||
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved);
|
||||
name_validity = is_strict_reserved ? kFunctionNameIsStrictReserved
|
||||
: kFunctionNameValidityUnknown;
|
||||
variable_name = name;
|
||||
@ -3809,8 +3803,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseClassDeclaration(
|
||||
if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) {
|
||||
impl()->GetDefaultStrings(&name, &variable_name);
|
||||
} else {
|
||||
bool is_await = false;
|
||||
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, &is_await);
|
||||
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved);
|
||||
variable_name = name;
|
||||
}
|
||||
|
||||
@ -4305,12 +4298,7 @@ ParserBase<Impl>::ParseAsyncFunctionLiteral() {
|
||||
ast_value_factory()->anonymous_string());
|
||||
} else if (peek_any_identifier()) {
|
||||
type = FunctionLiteral::kNamedExpression;
|
||||
bool is_await = false;
|
||||
name = ParseIdentifierOrStrictReservedWord(kind, &is_strict_reserved,
|
||||
&is_await);
|
||||
// If the function name is "await", ParseIdentifierOrStrictReservedWord
|
||||
// recognized the error.
|
||||
DCHECK(!is_await);
|
||||
name = ParseIdentifierOrStrictReservedWord(kind, &is_strict_reserved);
|
||||
}
|
||||
FunctionLiteralT result = impl()->ParseFunctionLiteral(
|
||||
name, scanner()->location(),
|
||||
@ -4478,10 +4466,14 @@ void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression,
|
||||
classifier()->RecordBindingPatternError(
|
||||
Scanner::Location(begin, end),
|
||||
MessageTemplate::kInvalidPropertyBindingPattern);
|
||||
} else if (is_strict(language_mode()) && impl()->IsIdentifier(expression)) {
|
||||
// Only classify if we are already in strict mode since the language mode
|
||||
// cannot change in the presence of non-simple parameters.
|
||||
ClassifyFormalParameter(impl()->AsIdentifier(expression), begin, end);
|
||||
} else if (impl()->IsIdentifier(expression)) {
|
||||
IdentifierT identifier = impl()->AsIdentifier(expression);
|
||||
ClassifyFormalParameter(identifier, begin, end);
|
||||
if (impl()->IsLet(identifier)) {
|
||||
classifier()->RecordLetPatternError(
|
||||
Scanner::Location(begin, end),
|
||||
MessageTemplate::kLetInLexicalBinding);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -916,7 +916,7 @@ ZoneChunkList<Parser::ExportClauseData>* Parser::ParseExportClause(
|
||||
// Keep track of the first reserved word encountered in case our
|
||||
// caller needs to report an error.
|
||||
if (!reserved_loc->IsValid() &&
|
||||
!Token::IsIdentifier(name_tok, LanguageMode::kStrict, false,
|
||||
!Token::IsValidIdentifier(name_tok, LanguageMode::kStrict, false,
|
||||
parsing_module_)) {
|
||||
*reserved_loc = scanner()->location();
|
||||
}
|
||||
@ -971,8 +971,9 @@ ZonePtrList<const Parser::NamedImport>* Parser::ParseNamedImports(int pos) {
|
||||
if (CheckContextualKeyword(ast_value_factory()->as_string())) {
|
||||
local_name = ParseIdentifierName();
|
||||
}
|
||||
if (!Token::IsIdentifier(scanner()->current_token(), LanguageMode::kStrict,
|
||||
false, parsing_module_)) {
|
||||
if (!Token::IsValidIdentifier(scanner()->current_token(),
|
||||
LanguageMode::kStrict, false,
|
||||
parsing_module_)) {
|
||||
ReportMessage(MessageTemplate::kUnexpectedReserved);
|
||||
return nullptr;
|
||||
} else if (IsEvalOrArguments(local_name)) {
|
||||
|
@ -595,6 +595,10 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
return identifier == ast_value_factory()->arguments_string();
|
||||
}
|
||||
|
||||
V8_INLINE bool IsLet(const AstRawString* identifier) const {
|
||||
return identifier == ast_value_factory()->let_string();
|
||||
}
|
||||
|
||||
V8_INLINE bool IsEvalOrArguments(const AstRawString* identifier) const {
|
||||
return IsEval(identifier) || IsArguments(identifier);
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ PreParserIdentifier GetSymbolHelper(Scanner* scanner,
|
||||
// - 'contextual' keywords (and may contain escaped; treated in 2nd switch.)
|
||||
// - 'contextual' keywords, but may not be escaped (3rd switch).
|
||||
switch (scanner->current_token()) {
|
||||
case Token::LET:
|
||||
return PreParserIdentifier::Let();
|
||||
case Token::AWAIT:
|
||||
return PreParserIdentifier::Await();
|
||||
case Token::ASYNC:
|
||||
@ -44,6 +46,9 @@ PreParserIdentifier GetSymbolHelper(Scanner* scanner,
|
||||
return PreParserIdentifier::Name();
|
||||
}
|
||||
if (scanner->literal_contains_escapes()) {
|
||||
if (string == avf->let_string()) {
|
||||
return PreParserIdentifier::Let();
|
||||
}
|
||||
return PreParserIdentifier::Default();
|
||||
}
|
||||
if (string == avf->eval_string()) {
|
||||
|
@ -45,6 +45,9 @@ class PreParserIdentifier {
|
||||
static PreParserIdentifier Await() {
|
||||
return PreParserIdentifier(kAwaitIdentifier);
|
||||
}
|
||||
static PreParserIdentifier Let() {
|
||||
return PreParserIdentifier(kLetIdentifier);
|
||||
}
|
||||
static PreParserIdentifier Async() {
|
||||
return PreParserIdentifier(kAsyncIdentifier);
|
||||
}
|
||||
@ -64,6 +67,7 @@ class PreParserIdentifier {
|
||||
}
|
||||
bool IsConstructor() const { return type_ == kConstructorIdentifier; }
|
||||
bool IsAwait() const { return type_ == kAwaitIdentifier; }
|
||||
bool IsLet() const { return type_ == kLetIdentifier; }
|
||||
bool IsName() const { return type_ == kNameIdentifier; }
|
||||
bool IsPrivateName() const { return type_ == kPrivateNameIdentifier; }
|
||||
|
||||
@ -75,6 +79,7 @@ class PreParserIdentifier {
|
||||
kArgumentsIdentifier,
|
||||
kConstructorIdentifier,
|
||||
kAwaitIdentifier,
|
||||
kLetIdentifier,
|
||||
kAsyncIdentifier,
|
||||
kNameIdentifier,
|
||||
kPrivateNameIdentifier
|
||||
@ -1301,6 +1306,10 @@ class PreParser : public ParserBase<PreParser> {
|
||||
return identifier.IsAwait();
|
||||
}
|
||||
|
||||
V8_INLINE bool IsLet(const PreParserIdentifier& identifier) const {
|
||||
return identifier.IsLet();
|
||||
}
|
||||
|
||||
// Returns true if the expression is of type "this.foo".
|
||||
V8_INLINE static bool IsThisProperty(const PreParserExpression& expression) {
|
||||
return expression.IsThisProperty();
|
||||
|
@ -518,7 +518,8 @@ class Scanner {
|
||||
token == Token::UNINITIALIZED || token == Token::REGEXP_LITERAL ||
|
||||
token == Token::ESCAPED_KEYWORD ||
|
||||
IsInRange(token, Token::NUMBER, Token::STRING) ||
|
||||
(Token::IsAnyIdentifier(token) && !Token::IsKeyword(token)) ||
|
||||
(Token::IsAnyIdentifierOrEnum(token) &&
|
||||
!Token::IsKeyword(token)) ||
|
||||
IsInRange(token, Token::TEMPLATE_SPAN, Token::TEMPLATE_TAIL);
|
||||
}
|
||||
bool CanAccessRawLiteral() const {
|
||||
|
@ -173,8 +173,10 @@ namespace internal {
|
||||
T(IDENTIFIER, nullptr, 0) \
|
||||
K(ASYNC, "async", 0) \
|
||||
/* `await` is a reserved word in module code only */ \
|
||||
/* BEGIN AwaitOrYield */ \
|
||||
K(AWAIT, "await", 0) \
|
||||
K(YIELD, "yield", 0) \
|
||||
/* END AwaitOrYield */ \
|
||||
K(LET, "let", 0) \
|
||||
K(STATIC, "static", 0) \
|
||||
/* Future reserved words (ECMA-262, section 7.6.1.2). */ \
|
||||
@ -218,15 +220,14 @@ class Token {
|
||||
// Predicates
|
||||
static bool IsKeyword(Value token) { return token_type[token] == 'K'; }
|
||||
|
||||
static bool IsIdentifier(Value token, LanguageMode language_mode,
|
||||
bool is_generator, bool disallow_await) {
|
||||
if (IsInRange(token, IDENTIFIER, ASYNC)) return true;
|
||||
if (IsInRange(token, LET, ESCAPED_STRICT_RESERVED_WORD)) {
|
||||
return is_sloppy(language_mode);
|
||||
}
|
||||
V8_INLINE static bool IsValidIdentifier(Value token,
|
||||
LanguageMode language_mode,
|
||||
bool is_generator,
|
||||
bool disallow_await) {
|
||||
if (V8_LIKELY(IsInRange(token, IDENTIFIER, ASYNC))) return true;
|
||||
if (token == AWAIT) return !disallow_await;
|
||||
if (token == YIELD) return !is_generator && is_sloppy(language_mode);
|
||||
return false;
|
||||
return IsStrictReservedWord(token) && is_sloppy(language_mode);
|
||||
}
|
||||
|
||||
static bool IsCallable(Value token) { return IsInRange(token, SUPER, ENUM); }
|
||||
@ -236,11 +237,19 @@ class Token {
|
||||
}
|
||||
|
||||
static bool IsAnyIdentifier(Value token) {
|
||||
return IsInRange(token, IDENTIFIER, ESCAPED_STRICT_RESERVED_WORD);
|
||||
}
|
||||
|
||||
static bool IsAnyIdentifierOrEnum(Value token) {
|
||||
return IsInRange(token, IDENTIFIER, ENUM);
|
||||
}
|
||||
|
||||
static bool IsAwaitOrYield(Value token) {
|
||||
return IsInRange(token, AWAIT, YIELD);
|
||||
}
|
||||
|
||||
static bool IsStrictReservedWord(Value token) {
|
||||
return IsInRange(token, LET, ESCAPED_STRICT_RESERVED_WORD);
|
||||
return IsInRange(token, YIELD, ESCAPED_STRICT_RESERVED_WORD);
|
||||
}
|
||||
|
||||
static bool IsLiteral(Value token) {
|
||||
|
@ -98,7 +98,6 @@ bool TokenIsAnyIdentifier(Token::Value token) {
|
||||
case Token::STATIC:
|
||||
case Token::FUTURE_STRICT_RESERVED_WORD:
|
||||
case Token::ESCAPED_STRICT_RESERVED_WORD:
|
||||
case Token::ENUM:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@ -112,6 +111,31 @@ TEST(AnyIdentifierToken) {
|
||||
}
|
||||
}
|
||||
|
||||
bool TokenIsAnyIdentifierOrEnum(Token::Value token) {
|
||||
switch (token) {
|
||||
case Token::IDENTIFIER:
|
||||
case Token::ASYNC:
|
||||
case Token::AWAIT:
|
||||
case Token::YIELD:
|
||||
case Token::LET:
|
||||
case Token::STATIC:
|
||||
case Token::FUTURE_STRICT_RESERVED_WORD:
|
||||
case Token::ESCAPED_STRICT_RESERVED_WORD:
|
||||
case Token::ENUM:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AnyIdentifierOrEnumToken) {
|
||||
for (int i = 0; i < Token::NUM_TOKENS; i++) {
|
||||
Token::Value token = static_cast<Token::Value>(i);
|
||||
CHECK_EQ(TokenIsAnyIdentifierOrEnum(token),
|
||||
Token::IsAnyIdentifierOrEnum(token));
|
||||
}
|
||||
}
|
||||
|
||||
bool TokenIsCallable(Token::Value token) {
|
||||
switch (token) {
|
||||
case Token::SUPER:
|
||||
@ -137,7 +161,7 @@ TEST(CallableToken) {
|
||||
}
|
||||
}
|
||||
|
||||
bool TokenIsIdentifier(Token::Value token, LanguageMode language_mode,
|
||||
bool TokenIsValidIdentifier(Token::Value token, LanguageMode language_mode,
|
||||
bool is_generator, bool disallow_await) {
|
||||
switch (token) {
|
||||
case Token::IDENTIFIER:
|
||||
@ -158,7 +182,7 @@ bool TokenIsIdentifier(Token::Value token, LanguageMode language_mode,
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
TEST(IsIdentifierToken) {
|
||||
TEST(IsValidIdentifierToken) {
|
||||
for (int i = 0; i < Token::NUM_TOKENS; i++) {
|
||||
Token::Value token = static_cast<Token::Value>(i);
|
||||
for (size_t raw_language_mode = 0; raw_language_mode < LanguageModeSize;
|
||||
@ -167,17 +191,30 @@ TEST(IsIdentifierToken) {
|
||||
for (int is_generator = 0; is_generator < 2; is_generator++) {
|
||||
for (int disallow_await = 0; disallow_await < 2; disallow_await++) {
|
||||
CHECK_EQ(
|
||||
TokenIsIdentifier(token, mode, is_generator, disallow_await),
|
||||
Token::IsIdentifier(token, mode, is_generator, disallow_await));
|
||||
TokenIsValidIdentifier(token, mode, is_generator, disallow_await),
|
||||
Token::IsValidIdentifier(token, mode, is_generator,
|
||||
disallow_await));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TokenIsAwaitOrYield(Token::Value token) {
|
||||
return token == Token::AWAIT || token == Token::YIELD;
|
||||
}
|
||||
|
||||
TEST(IsAwaitOrYield) {
|
||||
for (int i = 0; i < Token::NUM_TOKENS; i++) {
|
||||
Token::Value token = static_cast<Token::Value>(i);
|
||||
CHECK_EQ(TokenIsAwaitOrYield(token), Token::IsAwaitOrYield(token));
|
||||
}
|
||||
}
|
||||
|
||||
bool TokenIsStrictReservedWord(Token::Value token) {
|
||||
switch (token) {
|
||||
case Token::LET:
|
||||
case Token::YIELD:
|
||||
case Token::STATIC:
|
||||
case Token::FUTURE_STRICT_RESERVED_WORD:
|
||||
case Token::ESCAPED_STRICT_RESERVED_WORD:
|
||||
|
Loading…
Reference in New Issue
Block a user