Commit 02b6178c authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[scanner] Push surrogate pair handling down into identifier scanning

Most scanner logic doesn't need to care about surrogate pairs, so we can just
push it down to identifier scanning.

This CL additionally drops some explicit kEndOfInput checks that are subsumed
by predicates seemlessly returning false for kEndOfInput (-1).

Change-Id: If031a9355ab5fbca0c3b647045e3034f42923979
Reviewed-on: https://chromium-review.googlesource.com/1124447Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54172}
parent 9bbb0cd2
...@@ -438,8 +438,8 @@ Token::Value Scanner::SkipWhiteSpace() { ...@@ -438,8 +438,8 @@ Token::Value Scanner::SkipWhiteSpace() {
while (true) { while (true) {
while (true) { while (true) {
// Don't skip behind the end of input. // We won't skip behind the end of input.
if (c0_ == kEndOfInput) break; DCHECK(!unicode_cache_->IsWhiteSpace(kEndOfInput));
// Advance as long as character is a WhiteSpace or LineTerminator. // Advance as long as character is a WhiteSpace or LineTerminator.
// Remember if the latter is the case. // Remember if the latter is the case.
...@@ -521,9 +521,11 @@ Token::Value Scanner::SkipSourceURLComment() { ...@@ -521,9 +521,11 @@ Token::Value Scanner::SkipSourceURLComment() {
void Scanner::TryToParseSourceURLComment() { void Scanner::TryToParseSourceURLComment() {
// Magic comments are of the form: //[#@]\s<name>=\s*<value>\s*.* and this // Magic comments are of the form: //[#@]\s<name>=\s*<value>\s*.* and this
// function will just return if it cannot parse a magic comment. // function will just return if it cannot parse a magic comment.
if (c0_ == kEndOfInput || !unicode_cache_->IsWhiteSpace(c0_)) return; DCHECK(!unicode_cache_->IsWhiteSpaceOrLineTerminator(kEndOfInput));
if (!unicode_cache_->IsWhiteSpace(c0_)) return;
Advance(); Advance();
LiteralBuffer name; LiteralBuffer name;
while (c0_ != kEndOfInput && while (c0_ != kEndOfInput &&
!unicode_cache_->IsWhiteSpaceOrLineTerminator(c0_) && c0_ != '=') { !unicode_cache_->IsWhiteSpaceOrLineTerminator(c0_) && c0_ != '=') {
name.AddChar(c0_); name.AddChar(c0_);
...@@ -543,7 +545,7 @@ void Scanner::TryToParseSourceURLComment() { ...@@ -543,7 +545,7 @@ void Scanner::TryToParseSourceURLComment() {
return; return;
Advance(); Advance();
value->Reset(); value->Reset();
while (c0_ != kEndOfInput && unicode_cache_->IsWhiteSpace(c0_)) { while (unicode_cache_->IsWhiteSpace(c0_)) {
Advance(); Advance();
} }
while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) { while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) {
...@@ -576,7 +578,8 @@ Token::Value Scanner::SkipMultiLineComment() { ...@@ -576,7 +578,8 @@ Token::Value Scanner::SkipMultiLineComment() {
while (c0_ != kEndOfInput) { while (c0_ != kEndOfInput) {
uc32 ch = c0_; uc32 ch = c0_;
Advance(); Advance();
if (c0_ != kEndOfInput && unibrow::IsLineTerminator(ch)) { DCHECK(!unibrow::IsLineTerminator(kEndOfInput));
if (unibrow::IsLineTerminator(ch)) {
// Following ECMA-262, section 7.4, a comment containing // Following ECMA-262, section 7.4, a comment containing
// a newline will make the comment count as a line-terminator. // a newline will make the comment count as a line-terminator.
has_multiline_comment_before_next_ = true; has_multiline_comment_before_next_ = true;
...@@ -866,17 +869,17 @@ void Scanner::Scan() { ...@@ -866,17 +869,17 @@ void Scanner::Scan() {
break; break;
default: default:
if (c0_ == kEndOfInput) { if (unicode_cache_->IsIdentifierStart(c0_) ||
token = Token::EOS; (CombineSurrogatePair() &&
} else if (unicode_cache_->IsIdentifierStart(c0_)) { unicode_cache_->IsIdentifierStart(c0_))) {
token = ScanIdentifierOrKeyword(); token = ScanIdentifierOrKeyword();
} else if (IsDecimalDigit(c0_)) { } else if (IsDecimalDigit(c0_)) {
token = ScanNumber(false); token = ScanNumber(false);
} else if (c0_ == kEndOfInput) {
token = Token::EOS;
} else { } else {
token = SkipWhiteSpace(); token = SkipWhiteSpace();
if (token == Token::ILLEGAL) { if (token == Token::ILLEGAL) Advance();
Advance();
}
} }
break; break;
} }
...@@ -978,8 +981,8 @@ bool Scanner::ScanEscape() { ...@@ -978,8 +981,8 @@ bool Scanner::ScanEscape() {
Advance<capture_raw>(); Advance<capture_raw>();
// Skip escaped newlines. // Skip escaped newlines.
if (!in_template_literal && c0_ != kEndOfInput && DCHECK(!unibrow::IsLineTerminator(kEndOfInput));
unibrow::IsLineTerminator(c)) { if (!in_template_literal && unibrow::IsLineTerminator(c)) {
// Allow escaped CR+LF newlines in multiline string literals. // Allow escaped CR+LF newlines in multiline string literals.
if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>(); if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>();
return true; return true;
...@@ -1053,43 +1056,28 @@ uc32 Scanner::ScanOctalEscape(uc32 c, int length, bool in_template_literal) { ...@@ -1053,43 +1056,28 @@ uc32 Scanner::ScanOctalEscape(uc32 c, int length, bool in_template_literal) {
Token::Value Scanner::ScanString() { Token::Value Scanner::ScanString() {
uc32 quote = c0_; uc32 quote = c0_;
Advance<false, false>(); // consume quote Advance(); // consume quote
LiteralScope literal(this); LiteralScope literal(this);
while (true) { while (true) {
if (c0_ > kMaxAscii) {
HandleLeadSurrogate();
break;
}
if (c0_ == kEndOfInput || c0_ == '\n' || c0_ == '\r') return Token::ILLEGAL;
if (c0_ == quote) { if (c0_ == quote) {
literal.Complete(); literal.Complete();
Advance<false, false>(); Advance();
return Token::STRING; return Token::STRING;
} }
char c = static_cast<char>(c0_); if (c0_ == kEndOfInput || unibrow::IsStringLiteralLineTerminator(c0_)) {
if (c == '\\') break; return Token::ILLEGAL;
Advance<false, false>();
AddLiteralChar(c);
} }
if (c0_ == '\\') {
while (c0_ != quote && c0_ != kEndOfInput &&
!unibrow::IsStringLiteralLineTerminator(c0_)) {
uc32 c = c0_;
Advance(); Advance();
if (c == '\\') { // TODO(verwaest): Check whether we can remove the additional check.
if (c0_ == kEndOfInput || !ScanEscape<false, false>()) { if (c0_ == kEndOfInput || !ScanEscape<false, false>()) {
return Token::ILLEGAL; return Token::ILLEGAL;
} }
} else { continue;
AddLiteralChar(c);
} }
AddLiteralCharAdvance();
} }
if (c0_ != quote) return Token::ILLEGAL;
literal.Complete();
Advance(); // consume quote
return Token::STRING;
} }
Token::Value Scanner::ScanPrivateName() { Token::Value Scanner::ScanPrivateName() {
...@@ -1102,7 +1090,8 @@ Token::Value Scanner::ScanPrivateName() { ...@@ -1102,7 +1090,8 @@ Token::Value Scanner::ScanPrivateName() {
LiteralScope literal(this); LiteralScope literal(this);
DCHECK_EQ(c0_, '#'); DCHECK_EQ(c0_, '#');
AddLiteralCharAdvance(); AddLiteralCharAdvance();
if (c0_ == kEndOfInput || !unicode_cache_->IsIdentifierStart(c0_)) { DCHECK(!unicode_cache_->IsIdentifierStart(kEndOfInput));
if (!unicode_cache_->IsIdentifierStart(c0_)) {
PushBack(c0_); PushBack(c0_);
ReportScannerError(source_pos(), ReportScannerError(source_pos(),
MessageTemplate::kInvalidOrUnexpectedToken); MessageTemplate::kInvalidOrUnexpectedToken);
...@@ -1150,7 +1139,8 @@ Token::Value Scanner::ScanTemplateSpan() { ...@@ -1150,7 +1139,8 @@ Token::Value Scanner::ScanTemplateSpan() {
ReduceRawLiteralLength(2); ReduceRawLiteralLength(2);
break; break;
} else if (c == '\\') { } else if (c == '\\') {
if (c0_ != kEndOfInput && unibrow::IsLineTerminator(c0_)) { DCHECK(!unibrow::IsLineTerminator(kEndOfInput));
if (unibrow::IsLineTerminator(c0_)) {
// The TV of LineContinuation :: \ LineTerminatorSequence is the empty // The TV of LineContinuation :: \ LineTerminatorSequence is the empty
// code unit sequence. // code unit sequence.
uc32 lastChar = c0_; uc32 lastChar = c0_;
...@@ -1230,7 +1220,7 @@ bool Scanner::ScanDigitsWithNumericSeparators(bool (*predicate)(uc32 ch), ...@@ -1230,7 +1220,7 @@ bool Scanner::ScanDigitsWithNumericSeparators(bool (*predicate)(uc32 ch),
bool separator_seen = false; bool separator_seen = false;
while (predicate(c0_) || c0_ == '_') { while (predicate(c0_) || c0_ == '_') {
if (c0_ == '_') { if (c0_ == '_') {
Advance<false, false>(); Advance();
if (c0_ == '_') { if (c0_ == '_') {
ReportScannerError(Location(source_pos(), source_pos() + 1), ReportScannerError(Location(source_pos(), source_pos() + 1),
MessageTemplate::kContinuousNumericSeparator); MessageTemplate::kContinuousNumericSeparator);
...@@ -1266,7 +1256,7 @@ bool Scanner::ScanDecimalAsSmiWithNumericSeparators(uint64_t* value) { ...@@ -1266,7 +1256,7 @@ bool Scanner::ScanDecimalAsSmiWithNumericSeparators(uint64_t* value) {
bool separator_seen = false; bool separator_seen = false;
while (IsDecimalDigit(c0_) || c0_ == '_') { while (IsDecimalDigit(c0_) || c0_ == '_') {
if (c0_ == '_') { if (c0_ == '_') {
Advance<false, false>(); Advance();
if (c0_ == '_') { if (c0_ == '_') {
ReportScannerError(Location(source_pos(), source_pos() + 1), ReportScannerError(Location(source_pos(), source_pos() + 1),
MessageTemplate::kContinuousNumericSeparator); MessageTemplate::kContinuousNumericSeparator);
...@@ -1278,7 +1268,7 @@ bool Scanner::ScanDecimalAsSmiWithNumericSeparators(uint64_t* value) { ...@@ -1278,7 +1268,7 @@ bool Scanner::ScanDecimalAsSmiWithNumericSeparators(uint64_t* value) {
separator_seen = false; separator_seen = false;
*value = 10 * *value + (c0_ - '0'); *value = 10 * *value + (c0_ - '0');
uc32 first_char = c0_; uc32 first_char = c0_;
Advance<false, false>(); Advance();
AddLiteralChar(first_char); AddLiteralChar(first_char);
} }
...@@ -1299,7 +1289,7 @@ bool Scanner::ScanDecimalAsSmi(uint64_t* value) { ...@@ -1299,7 +1289,7 @@ bool Scanner::ScanDecimalAsSmi(uint64_t* value) {
while (IsDecimalDigit(c0_)) { while (IsDecimalDigit(c0_)) {
*value = 10 * *value + (c0_ - '0'); *value = 10 * *value + (c0_ - '0');
uc32 first_char = c0_; uc32 first_char = c0_;
Advance<false, false>(); Advance();
AddLiteralChar(first_char); AddLiteralChar(first_char);
} }
return true; return true;
...@@ -1444,10 +1434,9 @@ Token::Value Scanner::ScanNumber(bool seen_period) { ...@@ -1444,10 +1434,9 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
if (next_.literal_chars->one_byte_literal().length() <= 10 && if (next_.literal_chars->one_byte_literal().length() <= 10 &&
value <= Smi::kMaxValue && c0_ != '.' && value <= Smi::kMaxValue && c0_ != '.' &&
(c0_ == kEndOfInput || !unicode_cache_->IsIdentifierStart(c0_))) { !unicode_cache_->IsIdentifierStart(c0_)) {
next_.smi_value_ = static_cast<uint32_t>(value); next_.smi_value_ = static_cast<uint32_t>(value);
literal.Complete(); literal.Complete();
HandleLeadSurrogate();
if (kind == DECIMAL_WITH_LEADING_ZERO) { if (kind == DECIMAL_WITH_LEADING_ZERO) {
octal_pos_ = Location(start_pos, source_pos()); octal_pos_ = Location(start_pos, source_pos());
...@@ -1455,7 +1444,6 @@ Token::Value Scanner::ScanNumber(bool seen_period) { ...@@ -1455,7 +1444,6 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
} }
return Token::SMI; return Token::SMI;
} }
HandleLeadSurrogate();
} }
if (!ScanDecimalDigits()) return Token::ILLEGAL; if (!ScanDecimalDigits()) return Token::ILLEGAL;
...@@ -1503,9 +1491,9 @@ Token::Value Scanner::ScanNumber(bool seen_period) { ...@@ -1503,9 +1491,9 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
// not be an identifier start or a decimal digit; see ECMA-262 // not be an identifier start or a decimal digit; see ECMA-262
// section 7.8.3, page 17 (note that we read only one decimal digit // section 7.8.3, page 17 (note that we read only one decimal digit
// if the value is 0). // if the value is 0).
if (IsDecimalDigit(c0_) || if (IsDecimalDigit(c0_) || unicode_cache_->IsIdentifierStart(c0_)) {
(c0_ != kEndOfInput && unicode_cache_->IsIdentifierStart(c0_)))
return Token::ILLEGAL; return Token::ILLEGAL;
}
literal.Complete(); literal.Complete();
...@@ -1688,24 +1676,18 @@ Token::Value Scanner::ScanIdentifierOrKeyword() { ...@@ -1688,24 +1676,18 @@ Token::Value Scanner::ScanIdentifierOrKeyword() {
Token::Value Scanner::ScanIdentifierOrKeywordInner(LiteralScope* literal) { Token::Value Scanner::ScanIdentifierOrKeywordInner(LiteralScope* literal) {
DCHECK(unicode_cache_->IsIdentifierStart(c0_)); DCHECK(unicode_cache_->IsIdentifierStart(c0_));
bool escaped = false;
if (IsInRange(c0_, 'a', 'z') || c0_ == '_') { if (IsInRange(c0_, 'a', 'z') || c0_ == '_') {
do { do {
char first_char = static_cast<char>(c0_); AddLiteralCharAdvance();
Advance<false, false>();
AddLiteralChar(first_char);
} while (IsInRange(c0_, 'a', 'z') || c0_ == '_'); } while (IsInRange(c0_, 'a', 'z') || c0_ == '_');
if (IsDecimalDigit(c0_) || IsInRange(c0_, 'A', 'Z') || c0_ == '_' || if (IsDecimalDigit(c0_) || IsInRange(c0_, 'A', 'Z') || c0_ == '$') {
c0_ == '$') { // Identifier starting with lowercase or _.
// Identifier starting with lowercase. do {
char first_char = static_cast<char>(c0_); AddLiteralCharAdvance();
Advance<false, false>(); } while (IsAsciiIdentifier(c0_));
AddLiteralChar(first_char);
while (IsAsciiIdentifier(c0_)) {
char first_char = static_cast<char>(c0_);
Advance<false, false>();
AddLiteralChar(first_char);
}
if (c0_ <= kMaxAscii && c0_ != '\\') { if (c0_ <= kMaxAscii && c0_ != '\\') {
literal->Complete(); literal->Complete();
return Token::IDENTIFIER; return Token::IDENTIFIER;
...@@ -1721,100 +1703,67 @@ Token::Value Scanner::ScanIdentifierOrKeywordInner(LiteralScope* literal) { ...@@ -1721,100 +1703,67 @@ Token::Value Scanner::ScanIdentifierOrKeywordInner(LiteralScope* literal) {
literal->Complete(); literal->Complete();
return token; return token;
} }
} else if (IsInRange(c0_, 'A', 'Z') || c0_ == '$') {
HandleLeadSurrogate();
} else if (IsInRange(c0_, 'A', 'Z') || c0_ == '_' || c0_ == '$') {
do { do {
char first_char = static_cast<char>(c0_); AddLiteralCharAdvance();
Advance<false, false>();
AddLiteralChar(first_char);
} while (IsAsciiIdentifier(c0_)); } while (IsAsciiIdentifier(c0_));
if (c0_ <= kMaxAscii && c0_ != '\\') { if (c0_ <= kMaxAscii && c0_ != '\\') {
literal->Complete(); literal->Complete();
return Token::IDENTIFIER; return Token::IDENTIFIER;
} }
HandleLeadSurrogate();
} else if (c0_ == '\\') { } else if (c0_ == '\\') {
// Scan identifier start character. escaped = true;
uc32 c = ScanIdentifierUnicodeEscape(); uc32 c = ScanIdentifierUnicodeEscape();
// Only allow legal identifier start characters. DCHECK(!unicode_cache_->IsIdentifierStart(-1));
if (c < 0 || if (c == '\\' || !unicode_cache_->IsIdentifierStart(c)) {
c == '\\' || // No recursive escapes.
!unicode_cache_->IsIdentifierStart(c)) {
return Token::ILLEGAL; return Token::ILLEGAL;
} }
AddLiteralChar(c); AddLiteralChar(c);
return ScanIdentifierSuffix(literal, true);
} else {
uc32 first_char = c0_;
Advance();
AddLiteralChar(first_char);
} }
// Scan the rest of the identifier characters. while (true) {
while (c0_ != kEndOfInput && unicode_cache_->IsIdentifierPart(c0_)) {
if (c0_ != '\\') {
uc32 next_char = c0_;
Advance();
AddLiteralChar(next_char);
continue;
}
// Fallthrough if no longer able to complete keyword.
return ScanIdentifierSuffix(literal, false);
}
if (next_.literal_chars->is_one_byte()) {
Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
Token::Value token =
KeywordOrIdentifierToken(chars.start(), chars.length());
if (token == Token::IDENTIFIER ||
token == Token::FUTURE_STRICT_RESERVED_WORD ||
Token::IsContextualKeyword(token))
literal->Complete();
return token;
}
literal->Complete();
return Token::IDENTIFIER;
}
Token::Value Scanner::ScanIdentifierSuffix(LiteralScope* literal,
bool escaped) {
// Scan the rest of the identifier characters.
while (c0_ != kEndOfInput && unicode_cache_->IsIdentifierPart(c0_)) {
if (c0_ == '\\') { if (c0_ == '\\') {
uc32 c = ScanIdentifierUnicodeEscape();
escaped = true; escaped = true;
uc32 c = ScanIdentifierUnicodeEscape();
// Only allow legal identifier part characters. // Only allow legal identifier part characters.
if (c < 0 || // TODO(verwaest): Make this true.
c == '\\' || // DCHECK(!unicode_cache_->IsIdentifierPart('\\'));
!unicode_cache_->IsIdentifierPart(c)) { DCHECK(!unicode_cache_->IsIdentifierPart(-1));
if (c == '\\' || !unicode_cache_->IsIdentifierPart(c)) {
return Token::ILLEGAL; return Token::ILLEGAL;
} }
AddLiteralChar(c); AddLiteralChar(c);
} else if (unicode_cache_->IsIdentifierPart(c0_) ||
(CombineSurrogatePair() &&
unicode_cache_->IsIdentifierPart(c0_))) {
AddLiteralCharAdvance();
} else { } else {
AddLiteralChar(c0_); break;
Advance();
} }
} }
literal->Complete();
if (escaped && next_.literal_chars->is_one_byte()) { if (next_.literal_chars->is_one_byte()) {
Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal(); Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
Token::Value token = Token::Value token =
KeywordOrIdentifierToken(chars.start(), chars.length()); KeywordOrIdentifierToken(chars.start(), chars.length());
/* TODO(adamk): YIELD should be handled specially. */ /* TODO(adamk): YIELD should be handled specially. */
if (token == Token::IDENTIFIER || Token::IsContextualKeyword(token)) { if (token == Token::IDENTIFIER || Token::IsContextualKeyword(token)) {
literal->Complete();
return token; return token;
} else if (token == Token::FUTURE_STRICT_RESERVED_WORD || }
token == Token::LET || token == Token::STATIC) {
if (!escaped) return token;
literal->Complete();
if (token == Token::FUTURE_STRICT_RESERVED_WORD || token == Token::LET ||
token == Token::STATIC) {
return Token::ESCAPED_STRICT_RESERVED_WORD; return Token::ESCAPED_STRICT_RESERVED_WORD;
} else {
return Token::ESCAPED_KEYWORD;
} }
return Token::ESCAPED_KEYWORD;
} }
literal->Complete();
return Token::IDENTIFIER; return Token::IDENTIFIER;
} }
...@@ -1879,7 +1828,7 @@ Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() { ...@@ -1879,7 +1828,7 @@ Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() {
// Scan regular expression flags. // Scan regular expression flags.
int flags = 0; int flags = 0;
while (c0_ != kEndOfInput && unicode_cache_->IsIdentifierPart(c0_)) { while (unicode_cache_->IsIdentifierPart(c0_)) {
RegExp::Flags flag = RegExp::kNone; RegExp::Flags flag = RegExp::kNone;
switch (c0_) { switch (c0_) {
case 'g': case 'g':
......
...@@ -608,26 +608,26 @@ class Scanner { ...@@ -608,26 +608,26 @@ class Scanner {
} }
// Low-level scanning support. // Low-level scanning support.
template <bool capture_raw = false, bool check_surrogate = true> template <bool capture_raw = false>
void Advance() { void Advance() {
if (capture_raw) { if (capture_raw) {
AddRawLiteralChar(c0_); AddRawLiteralChar(c0_);
} }
c0_ = source_->Advance(); c0_ = source_->Advance();
if (check_surrogate) HandleLeadSurrogate();
} }
void HandleLeadSurrogate() { bool CombineSurrogatePair() {
DCHECK(!unibrow::Utf16::IsLeadSurrogate(kEndOfInput)); DCHECK(!unibrow::Utf16::IsLeadSurrogate(kEndOfInput));
if (unibrow::Utf16::IsLeadSurrogate(c0_)) { if (unibrow::Utf16::IsLeadSurrogate(c0_)) {
uc32 c1 = source_->Advance(); uc32 c1 = source_->Advance();
DCHECK(!unibrow::Utf16::IsTrailSurrogate(kEndOfInput)); DCHECK(!unibrow::Utf16::IsTrailSurrogate(kEndOfInput));
if (!unibrow::Utf16::IsTrailSurrogate(c1)) { if (unibrow::Utf16::IsTrailSurrogate(c1)) {
source_->Back();
} else {
c0_ = unibrow::Utf16::CombineSurrogatePair(c0_, c1); c0_ = unibrow::Utf16::CombineSurrogatePair(c0_, c1);
return true;
} }
source_->Back();
} }
return false;
} }
void PushBack(uc32 ch) { void PushBack(uc32 ch) {
...@@ -752,7 +752,6 @@ class Scanner { ...@@ -752,7 +752,6 @@ class Scanner {
Token::Value ScanNumber(bool seen_period); Token::Value ScanNumber(bool seen_period);
Token::Value ScanIdentifierOrKeyword(); Token::Value ScanIdentifierOrKeyword();
Token::Value ScanIdentifierOrKeywordInner(LiteralScope* literal); Token::Value ScanIdentifierOrKeywordInner(LiteralScope* literal);
Token::Value ScanIdentifierSuffix(LiteralScope* literal, bool escaped);
Token::Value ScanString(); Token::Value ScanString();
Token::Value ScanPrivateName(); Token::Value ScanPrivateName();
......
...@@ -39,8 +39,12 @@ class Predicate { ...@@ -39,8 +39,12 @@ class Predicate {
inline CacheEntry() inline CacheEntry()
: bit_field_(CodePointField::encode(0) | ValueField::encode(0)) {} : bit_field_(CodePointField::encode(0) | ValueField::encode(0)) {}
inline CacheEntry(uchar code_point, bool value) inline CacheEntry(uchar code_point, bool value)
: bit_field_(CodePointField::encode(code_point) | : bit_field_(
ValueField::encode(value)) {} CodePointField::encode(CodePointField::kMask & code_point) |
ValueField::encode(value)) {
DCHECK_IMPLIES((CodePointField::kMask & code_point) != code_point,
code_point == static_cast<uchar>(-1));
}
uchar code_point() const { return CodePointField::decode(bit_field_); } uchar code_point() const { return CodePointField::decode(bit_field_); }
bool value() const { return ValueField::decode(bit_field_); } bool value() const { return ValueField::decode(bit_field_); }
......
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