5#ifndef V8_PARSING_SCANNER_H_
6#define V8_PARSING_SCANNER_H_
30class ExternalOneByteString;
31class ExternalTwoByteString;
33class RuntimeCallStats;
57 return static_cast<base::uc32>(*buffer_cursor_);
59 return static_cast<base::uc32>(*buffer_cursor_);
76 template <
typename FunctionType>
79 auto next_cursor_pos =
93 return static_cast<base::uc32>(*next_cursor_pos);
111 inline size_t pos()
const {
135 virtual std::unique_ptr<Utf16CharacterStream>
Clone()
const = 0;
147 const uint16_t* buffer_cursor,
148 const uint16_t* buffer_end,
size_t buffer_pos)
222 bookmark_(kNoBookmark),
223 had_parser_error_(scanner->has_parser_error()) {
230 void Set(
size_t bookmark);
232 bool HasBeenSet()
const;
233 bool HasBeenApplied()
const;
247 if (!has_parser_error()) {
251 if (desc.token != Token::kUninitialized) desc.token = Token::kIllegal;
256 source_->reset_parser_error_flag();
259 return source_->has_parser_error();
264 Location(
int b,
int e) : beg_pos(b), end_pos(e) { }
267 int length()
const {
return end_pos - beg_pos; }
268 bool IsValid()
const {
return base::IsInRange(beg_pos, 0, end_pos); }
277 static constexpr base::uc32 kEndOfInput = Utf16CharacterStream::kEndOfInput;
301 bool has_error()
const {
return scanner_error_ != MessageTemplate::kNone; }
306 return current().invalid_template_escape_message != MessageTemplate::kNone;
309 DCHECK(has_invalid_template_escape());
310 return current().invalid_template_escape_message;
314 DCHECK(has_invalid_template_escape());
315 current_->invalid_template_escape_message = MessageTemplate::kNone;
319 DCHECK(has_invalid_template_escape());
320 return current().invalid_template_escape_location;
331 return LiteralContainsEscapes(
current());
335 return LiteralContainsEscapes(next());
344 double DoubleValue();
346 return literal_one_byte_string();
349 const char* CurrentLiteralAsCString(
Zone* zone)
const;
352 DCHECK(Token::IsKeyword(token));
353 return current().token == token;
358 DCHECK(next().CanAccessLiteral());
362 if (!is_next_literal_one_byte())
return false;
363 if (peek_location().
length() !=
N + 1)
return false;
366 const char* chars =
reinterpret_cast<const char*
>(next.
begin());
367 return next.
length() ==
N - 1 && strncmp(s, chars,
N - 1) == 0;
373 if (!is_literal_one_byte())
return false;
376 const char* chars =
reinterpret_cast<const char*
>(current.begin());
377 return current.length() ==
N - 1 && strncmp(s, chars,
N - 1) == 0;
383 octal_pos_ = Location::invalid();
384 octal_message_ = MessageTemplate::kNone;
395 void SeekForward(
int pos);
400 return next().after_line_terminator;
405 USE(ensure_next_next);
406 return next_next().after_line_terminator;
411 USE(ensure_next_next_next);
412 return next_next_next().after_line_terminator;
417 bool ScanRegExpPattern();
419 std::optional<RegExpFlags> ScanRegExpFlags();
423 DCHECK_EQ(next().token, Token::kRightBrace);
424 DCHECK_EQ(source_pos() - 1, next().location.beg_pos);
425 return ScanTemplateSpan();
428 template <
typename IsolateT>
430 template <
typename IsolateT>
434 return saw_source_mapping_url_magic_comment_at_sign_;
438 return saw_magic_comment_compile_hints_all_;
441 bool HasPerFunctionCompileHint(
int position);
459 DECIMAL_WITH_LEADING_ZERO
471 uint32_t smi_value = 0;
472 bool after_line_terminator =
false;
475 bool CanAccessLiteral()
const {
476 return token == Token::kPrivateName || token == Token::kIllegal ||
477 token == Token::kEscapedKeyword ||
478 token == Token::kUninitialized || token == Token::kRegExpLiteral ||
479 base::IsInRange(token, Token::kNumber, Token::kString) ||
480 Token::IsAnyIdentifier(token) || Token::IsKeyword(token) ||
481 base::IsInRange(token, Token::kTemplateSpan, Token::kTemplateTail);
483 bool CanAccessRawLiteral()
const {
484 return token == Token::kIllegal || token == Token::kUninitialized ||
485 base::IsInRange(token, Token::kTemplateSpan, Token::kTemplateTail);
491 return base::IsInRange(
kind, BINARY, DECIMAL);
495 return base::IsInRange(
kind, DECIMAL, DECIMAL_WITH_LEADING_ZERO);
498 static const int kCharacterLookaheadBufferSize = 1;
499 static const int kMaxAscii = 127;
502 template <
bool capture_raw>
508 static_assert(kCharacterLookaheadBufferSize == 1);
512 next_ = &token_storage_[1];
513 next_next_ = &token_storage_[2];
514 next_next_next_ = &token_storage_[3];
516 found_html_comment_ =
false;
517 scanner_error_ = MessageTemplate::kNone;
521 if (has_error())
return;
522 scanner_error_ = error;
523 scanner_error_location_ = location;
527 if (has_error())
return;
528 scanner_error_ = error;
536 next().literal_chars.AddChar(c);
542 next().raw_literal_chars.AddChar(c);
551 template <
bool capture_raw = false>
554 AddRawLiteralChar(c0_);
559 template <
typename FunctionType>
561 c0_ =
source_->AdvanceUntil(check);
617 current().token == Token::kEscapedKeyword);
618 return current().literal_chars.one_byte_literal();
622 current().token == Token::kEscapedKeyword);
623 return current().literal_chars.two_byte_literal();
627 current().token == Token::kEscapedKeyword);
628 return current().literal_chars.is_one_byte();
633 DCHECK(next().CanAccessLiteral());
634 return next().literal_chars.one_byte_literal();
637 DCHECK(next().CanAccessLiteral());
638 return next().literal_chars.two_byte_literal();
641 DCHECK(next().CanAccessLiteral());
642 return next().literal_chars.is_one_byte();
646 return current().raw_literal_chars.one_byte_literal();
650 return current().raw_literal_chars.two_byte_literal();
654 return current().raw_literal_chars.is_one_byte();
657 template <
bool capture_raw,
bool unicode = false>
658 base::uc32 ScanHexNumber(
int expected_length);
662 template <
bool capture_raw>
672 V8_INLINE void Scan(TokenDesc* next_desc);
678 void TryToParseMagicComment(
base::uc32 hash_or_at_sign);
683 bool ScanDigitsWithNumericSeparators(
bool (*predicate)(
base::uc32 ch),
684 bool is_check_first_digit);
685 bool ScanDecimalDigits(
bool allow_numeric_separator);
687 bool ScanDecimalAsSmi(uint64_t* value,
bool allow_numeric_separator);
688 bool ScanDecimalAsSmiWithNumericSeparators(uint64_t* value);
689 bool ScanHexDigits();
690 bool ScanBinaryDigits();
691 bool ScanSignedInteger();
692 bool ScanOctalDigits();
693 bool ScanImplicitOctalDigits(
int start_pos, NumberKind*
kind);
698 Token::Value ScanIdentifierOrKeywordInnerSlow(
bool escaped,
699 bool can_be_keyword);
707 template <
bool capture_raw>
714 template <
bool capture_raw>
721 return static_cast<int>(
source_->pos()) - kCharacterLookaheadBufferSize;
727 if (token.
token == Token::kString) {
735 void SanityCheckTokenDesc(
const TokenDesc&)
const;
767 bool saw_source_mapping_url_magic_comment_at_sign_ =
false;
768 bool saw_magic_comment_compile_hints_all_ =
false;
769 bool saw_non_comment_ =
false;
771 size_t per_function_compile_hint_positions_idx_ = 0;
static const uchar kMaxNonSurrogateCharCode
static int CombineSurrogatePair(uchar lead, uchar trail)
static bool IsTrailSurrogate(int code)
static bool IsLeadSurrogate(int code)
constexpr T * begin() const
BookmarkScope & operator=(const BookmarkScope &)=delete
static const size_t kNoBookmark
static const size_t kBookmarkWasApplied
BookmarkScope(Scanner *scanner)
BookmarkScope(const BookmarkScope &)=delete
V8_INLINE void AddLiteralCharAdvance()
MessageTemplate error() const
MessageTemplate octal_message_
base::Vector< const uint16_t > literal_two_byte_string() const
bool IsValidBigIntKind(NumberKind kind)
Token::Value peek() const
const TokenDesc & next() const
base::Vector< const uint16_t > raw_literal_two_byte_string() const
TokenDesc * next_next_next_
void clear_invalid_template_escape_message()
base::Vector< const uint8_t > BigIntLiteral() const
Location invalid_template_escape_location() const
static bool LiteralContainsEscapes(const TokenDesc &token)
const TokenDesc & next_next() const
void PushBack(base::uc32 ch)
V8_INLINE void AddLiteralChar(base::uc32 c)
bool has_invalid_template_escape() const
bool IsDecimalNumberKind(NumberKind kind)
bool FoundHtmlComment() const
bool SawMagicCommentCompileHintsAll() const
const Utf16CharacterStream * stream() const
bool next_literal_contains_escapes() const
void ReportScannerError(int pos, MessageTemplate error)
bool CombineSurrogatePair()
uint32_t smi_value() const
bool literal_contains_escapes() const
base::Vector< const uint8_t > literal_one_byte_string() const
bool SawSourceMappingUrlMagicCommentAtSign() const
LiteralBuffer source_mapping_url_
const Location & location() const
Token::Value current_token() const
V8_INLINE bool has_parser_error() const
Token::Value ScanTemplateContinuation()
bool CurrentMatches(Token::Value token) const
bool HasLineTerminatorBeforeNext() const
base::Vector< const uint8_t > next_literal_one_byte_string() const
V8_INLINE void AddLiteralChar(char c)
V8_INLINE void AddRawLiteralChar(base::uc32 c)
Utf16CharacterStream *const source_
bool HasLineTerminatorAfterNextNext()
base::Vector< const uint16_t > next_literal_two_byte_string() const
base::Vector< const uint8_t > raw_literal_one_byte_string() const
V8_INLINE void AdvanceUntil(FunctionType check)
bool NextLiteralExactlyEquals(const char(&s)[N])
bool is_next_literal_one_byte() const
UnoptimizedCompileFlags flags_
V8_INLINE void reset_parser_error_flag()
V8_INLINE void set_parser_error()
LiteralBuffer source_url_
bool CurrentLiteralEquals(const char(&s)[N])
MessageTemplate scanner_error_
bool is_raw_literal_one_byte() const
MessageTemplate octal_message() const
Token::Value Select(base::uc32 next, Token::Value then, Token::Value else_)
const TokenDesc & next_next_next() const
std::vector< int > per_function_compile_hint_positions_
const Location & error_location() const
void clear_octal_position()
Location scanner_error_location_
const Location & peek_location() const
MessageTemplate invalid_template_escape_message() const
bool is_literal_one_byte() const
static constexpr base::uc32 Invalid()
Location octal_position() const
bool HasLineTerminatorAfterNext()
Token::Value Select(Token::Value tok)
void ReportScannerError(const Location &location, MessageTemplate error)
const TokenDesc & current() const
bool can_be_cloned_for_parallel_access() const
const uint16_t * buffer_end_
RuntimeCallStats * runtime_call_stats_
const uint16_t * buffer_start_
V8_INLINE bool has_parser_error() const
V8_INLINE void set_parser_error()
virtual ~Utf16CharacterStream()=default
V8_INLINE void reset_parser_error_flag()
RuntimeCallStats * runtime_call_stats() const
Utf16CharacterStream(const uint16_t *buffer_start, const uint16_t *buffer_cursor, const uint16_t *buffer_end, size_t buffer_pos)
void set_runtime_call_stats(RuntimeCallStats *runtime_call_stats)
virtual bool can_be_cloned() const =0
bool ReadBlockChecked(size_t position)
static constexpr base::uc32 kEndOfInput
const uint16_t * buffer_cursor_
virtual bool ReadBlock(size_t position)=0
virtual bool can_access_heap() const =0
V8_INLINE base::uc32 AdvanceUntil(FunctionType check)
virtual std::unique_ptr< Utf16CharacterStream > Clone() const =0
ZoneVector< RpoNumber > & result
bool(* FunctionType)(const Operation &op, Zone *zone)
#define DCHECK_LE(v1, v2)
#define DCHECK_NOT_NULL(val)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define V8_EXPORT_PRIVATE
static Location invalid()
Location invalid_template_escape_location
LiteralBuffer literal_chars
LiteralBuffer raw_literal_chars
#define V8_LIKELY(condition)