1use tsz_common::diagnostics::diagnostic_codes;
15use tsz_common::limits::MAX_PARSER_RECURSION_DEPTH;
16
17use crate::parser::{
18 NodeIndex, NodeList,
19 node::{IdentifierData, NodeArena},
20 syntax_kind_ext,
21};
22use rustc_hash::FxHashMap;
23use tracing::trace;
24use tsz_common::interner::Atom;
25use tsz_scanner::scanner_impl::{ScannerState, TokenFlags};
26use tsz_scanner::{SyntaxKind, token_is_keyword};
27pub const CONTEXT_FLAG_ASYNC: u32 = 1;
33pub const CONTEXT_FLAG_GENERATOR: u32 = 2;
35pub const CONTEXT_FLAG_STATIC_BLOCK: u32 = 4;
37pub const CONTEXT_FLAG_PARAMETER_DEFAULT: u32 = 8;
39pub const CONTEXT_FLAG_DISALLOW_IN: u32 = 16;
41pub const CONTEXT_FLAG_IN_CONDITIONAL_TRUE: u32 = 64;
45pub const CONTEXT_FLAG_CLASS_MEMBER_NAME: u32 = 2048;
47pub const CONTEXT_FLAG_AMBIENT: u32 = 32;
49pub const CONTEXT_FLAG_IN_CLASS: u32 = 4096;
51pub const CONTEXT_FLAG_IN_DECORATOR: u32 = 128;
54pub const CONTEXT_FLAG_CONSTRUCTOR_PARAMETERS: u32 = 256;
56pub const CONTEXT_FLAG_ARROW_PARAMETERS: u32 = 512;
58pub const CONTEXT_FLAG_DISALLOW_CONDITIONAL_TYPES: u32 = 1024;
61pub const CONTEXT_FLAG_IN_BLOCK: u32 = 8192;
64pub const CONTEXT_FLAG_IN_PARENTHESIZED_EXPRESSION: u32 = 16384;
67
68#[derive(Clone, Debug)]
74pub struct ParseDiagnostic {
75 pub start: u32,
76 pub length: u32,
77 pub message: String,
78 pub code: u32,
79}
80
81pub struct IncrementalParseResult {
82 pub statements: NodeList,
83 pub end_pos: u32,
84 pub end_of_file_token: NodeIndex,
85 pub reparse_start: u32,
86}
87
88const ERROR_SUPPRESSION_DISTANCE: u32 = 3;
103
104pub struct ParserState {
107 pub(crate) scanner: ScannerState,
109 pub arena: NodeArena,
111 pub(crate) file_name: String,
113 pub context_flags: u32,
115 pub(crate) current_token: SyntaxKind,
117 pub(crate) parse_diagnostics: Vec<ParseDiagnostic>,
119 pub(crate) node_count: u32,
121 pub(crate) recursion_depth: u32,
123 pub(crate) last_error_pos: u32,
125 pub(crate) label_scopes: Vec<FxHashMap<String, u32>>,
128}
129
130impl ParserState {
131 #[inline]
132 #[must_use]
133 pub(crate) fn u32_from_usize(&self, value: usize) -> u32 {
134 let _ = self;
135 u32::try_from(value).expect("parser offsets must fit in u32")
136 }
137
138 #[inline]
139 #[must_use]
140 pub(crate) fn u16_from_node_flags(&self, value: u32) -> u16 {
141 let _ = self;
142 u16::try_from(value).expect("parser node flags must fit in u16")
143 }
144
145 #[must_use]
147 pub fn new(file_name: String, source_text: String) -> Self {
148 let estimated_nodes = source_text.len() / 20; let scanner = ScannerState::new(source_text, true);
152 Self {
153 scanner,
154 arena: NodeArena::with_capacity(estimated_nodes),
155 file_name,
156 context_flags: 0,
157 current_token: SyntaxKind::Unknown,
158 parse_diagnostics: Vec::new(),
159 node_count: 0,
160 recursion_depth: 0,
161 last_error_pos: 0,
162 label_scopes: vec![FxHashMap::default()],
163 }
164 }
165
166 pub fn reset(&mut self, file_name: String, source_text: String) {
167 self.file_name = file_name;
168 self.scanner.set_text(source_text, None, None);
169 self.arena.clear();
170 self.context_flags = 0;
171 self.current_token = SyntaxKind::Unknown;
172 self.parse_diagnostics.clear();
173 self.node_count = 0;
174 self.recursion_depth = 0;
175 self.last_error_pos = 0;
176 self.label_scopes.clear();
177 self.label_scopes.push(FxHashMap::default());
178 }
179
180 pub(crate) fn enter_recursion(&mut self) -> bool {
182 if self.recursion_depth >= MAX_PARSER_RECURSION_DEPTH {
183 self.parse_error_at_current_token(
184 "Maximum recursion depth exceeded",
185 diagnostic_codes::UNEXPECTED_TOKEN,
186 );
187 false
188 } else {
189 self.recursion_depth += 1;
190 true
191 }
192 }
193
194 fn should_report_error(&self) -> bool {
205 if self.last_error_pos == 0 {
207 return true;
208 }
209 let current = self.token_pos();
210 current.abs_diff(self.last_error_pos) > ERROR_SUPPRESSION_DISTANCE
214 }
215
216 pub(crate) const fn exit_recursion(&mut self) {
218 self.recursion_depth = self.recursion_depth.saturating_sub(1);
219 }
220
221 pub(crate) fn is_jsx_file(&self) -> bool {
229 std::path::Path::new(&self.file_name)
230 .extension()
231 .and_then(|ext| ext.to_str())
232 .is_some_and(|ext| {
233 ext.eq_ignore_ascii_case("tsx")
234 || ext.eq_ignore_ascii_case("jsx")
235 || ext.eq_ignore_ascii_case("js")
236 || ext.eq_ignore_ascii_case("cjs")
237 || ext.eq_ignore_ascii_case("mjs")
238 })
239 }
240
241 #[inline]
243 pub(crate) const fn token(&self) -> SyntaxKind {
244 self.current_token
245 }
246
247 #[inline]
249 pub(crate) fn token_pos(&self) -> u32 {
250 self.u32_from_usize(self.scanner.get_token_start())
251 }
252
253 #[inline]
255 pub(crate) fn token_end(&self) -> u32 {
256 self.u32_from_usize(self.scanner.get_token_end())
257 }
258
259 pub(crate) fn next_token(&mut self) -> SyntaxKind {
261 self.current_token = self.scanner.scan();
262 self.current_token
263 }
264
265 pub(crate) fn consume_keyword(&mut self) {
268 self.check_keyword_with_escape();
269 self.next_token();
270 }
271
272 fn check_keyword_with_escape(&mut self) {
275 if !token_is_keyword(self.current_token) {
277 return;
278 }
279 let flags = self.scanner.get_token_flags();
281 if (flags & TokenFlags::UnicodeEscape as u32) != 0 {
282 use tsz_common::diagnostics::diagnostic_codes;
283 self.parse_error_at(
284 self.u32_from_usize(self.scanner.get_token_start()),
285 self.u32_from_usize(self.scanner.get_token_end() - self.scanner.get_token_start()),
286 "Keywords cannot contain escape characters.",
287 diagnostic_codes::KEYWORDS_CANNOT_CONTAIN_ESCAPE_CHARACTERS,
288 );
289 }
290 }
291
292 #[inline]
294 pub(crate) fn is_token(&self, kind: SyntaxKind) -> bool {
295 self.current_token == kind
296 }
297
298 #[inline]
301 pub(crate) const fn is_identifier_or_keyword(&self) -> bool {
302 self.current_token as u16 >= SyntaxKind::Identifier as u16
303 }
304
305 #[inline]
307 pub(crate) const fn is_type_member_start(&self) -> bool {
308 match self.current_token {
309 SyntaxKind::OpenParenToken | SyntaxKind::LessThanToken | SyntaxKind::NewKeyword => true,
310 _ => self.is_property_name(),
311 }
312 }
313
314 #[inline]
317 pub(crate) const fn is_property_name(&self) -> bool {
318 match self.current_token {
319 SyntaxKind::Identifier
320 | SyntaxKind::StringLiteral
321 | SyntaxKind::NumericLiteral
322 | SyntaxKind::PrivateIdentifier
323 | SyntaxKind::OpenBracketToken | SyntaxKind::GetKeyword
325 | SyntaxKind::SetKeyword => true,
326 _ => self.is_identifier_or_keyword()
328 }
329 }
330
331 #[inline]
334 pub(crate) const fn can_token_start_type(&self) -> bool {
335 match self.current_token {
336 SyntaxKind::CloseParenToken | SyntaxKind::CloseBraceToken | SyntaxKind::CloseBracketToken | SyntaxKind::CommaToken | SyntaxKind::SemicolonToken | SyntaxKind::ColonToken | SyntaxKind::EqualsToken | SyntaxKind::EqualsGreaterThanToken | SyntaxKind::GreaterThanToken | SyntaxKind::BarToken | SyntaxKind::AmpersandToken | SyntaxKind::QuestionToken | SyntaxKind::EndOfFileToken => false,
350 _ => true
353 }
354 }
355
356 pub(crate) const fn is_type_terminator_token(&self) -> bool {
360 matches!(
361 self.current_token,
362 SyntaxKind::CloseParenToken | SyntaxKind::CloseBracketToken | SyntaxKind::CloseBraceToken | SyntaxKind::CommaToken | SyntaxKind::SemicolonToken | SyntaxKind::EqualsGreaterThanToken | SyntaxKind::EndOfFileToken )
370 }
371
372 pub(crate) fn parse_type_member_separator_with_asi(&mut self) {
381 if self.parse_optional(SyntaxKind::SemicolonToken)
382 || self.parse_optional(SyntaxKind::CommaToken)
383 {
384 return;
385 }
386
387 if self.scanner.has_preceding_line_break() || self.is_token(SyntaxKind::CloseBraceToken) {
389 return;
390 }
391
392 if self.is_type_member_start() {
393 self.error_token_expected(";");
394 }
395 }
396
397 #[inline]
399 pub(crate) const fn in_async_context(&self) -> bool {
400 (self.context_flags & CONTEXT_FLAG_ASYNC) != 0
401 }
402
403 #[inline]
405 pub(crate) const fn in_generator_context(&self) -> bool {
406 (self.context_flags & CONTEXT_FLAG_GENERATOR) != 0
407 }
408
409 #[inline]
411 pub(crate) const fn in_class_member_name(&self) -> bool {
412 (self.context_flags & CONTEXT_FLAG_CLASS_MEMBER_NAME) != 0
413 }
414
415 #[inline]
417 pub(crate) const fn in_class_body(&self) -> bool {
418 (self.context_flags & CONTEXT_FLAG_IN_CLASS) != 0
419 }
420
421 #[inline]
423 pub(crate) const fn in_static_block_context(&self) -> bool {
424 (self.context_flags & CONTEXT_FLAG_STATIC_BLOCK) != 0
425 }
426
427 #[inline]
429 pub(crate) const fn in_parameter_default_context(&self) -> bool {
430 (self.context_flags & CONTEXT_FLAG_PARAMETER_DEFAULT) != 0
431 }
432
433 #[inline]
435 pub(crate) const fn in_disallow_in_context(&self) -> bool {
436 (self.context_flags & CONTEXT_FLAG_DISALLOW_IN) != 0
437 }
438
439 #[inline]
442 pub(crate) const fn in_block_context(&self) -> bool {
443 (self.context_flags & CONTEXT_FLAG_IN_BLOCK) != 0
444 }
445
446 #[inline]
448 pub(crate) const fn in_parenthesized_expression_context(&self) -> bool {
449 (self.context_flags & CONTEXT_FLAG_IN_PARENTHESIZED_EXPRESSION) != 0
450 }
451
452 pub(crate) fn check_illegal_binding_identifier(&mut self) -> bool {
455 use tsz_common::diagnostics::diagnostic_codes;
456
457 let is_await = self.is_token(SyntaxKind::AwaitKeyword)
459 || (self.is_token(SyntaxKind::Identifier)
460 && self.scanner.get_token_value_ref() == "await");
461
462 if self.in_class_member_name()
465 && matches!(
466 self.token(),
467 SyntaxKind::PublicKeyword
468 | SyntaxKind::PrivateKeyword
469 | SyntaxKind::ProtectedKeyword
470 | SyntaxKind::ReadonlyKeyword
471 | SyntaxKind::StaticKeyword
472 | SyntaxKind::AbstractKeyword
473 | SyntaxKind::OverrideKeyword
474 | SyntaxKind::AsyncKeyword
475 | SyntaxKind::AwaitKeyword
476 | SyntaxKind::YieldKeyword
477 )
478 {
479 let token_text = self.scanner.get_token_value_ref();
480 self.parse_error_at_current_token(
481 &format!(
482 "Identifier expected. '{token_text}' is a reserved word in strict mode. Class definitions are automatically in strict mode."
483 ),
484 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_IN_STRICT_MODE_CLASS_DEFINITIONS_ARE_AUTO,
485 );
486 return true;
487 }
488
489 if is_await {
490 if self.in_static_block_context() {
492 self.parse_error_at_current_token(
493 "Identifier expected. 'await' is a reserved word that cannot be used here.",
494 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_THAT_CANNOT_BE_USED_HERE,
495 );
496 return true;
497 }
498
499 if self.in_async_context() {
501 self.parse_error_at_current_token(
502 "Identifier expected. 'await' is a reserved word that cannot be used here.",
503 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_THAT_CANNOT_BE_USED_HERE,
504 );
505 return true;
506 }
507 }
508
509 let is_yield = self.is_token(SyntaxKind::YieldKeyword)
512 || (self.is_token(SyntaxKind::Identifier)
513 && self.scanner.get_token_value_ref() == "yield");
514
515 if is_yield && self.in_generator_context() {
516 let is_class_context = self.in_class_body() || self.in_class_member_name();
517 if is_class_context {
518 self.parse_error_at_current_token(
519 "Identifier expected. 'yield' is a reserved word in strict mode. Class definitions are automatically in strict mode.",
520 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_IN_STRICT_MODE_CLASS_DEFINITIONS_ARE_AUTO,
521 );
522 } else {
523 self.parse_error_at_current_token(
524 "Identifier expected. 'yield' is a reserved word in strict mode.",
525 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_IN_STRICT_MODE,
526 );
527 }
528 return true;
529 }
530
531 false
532 }
533
534 pub(crate) fn recover_from_missing_method_open_paren(&mut self) {
538 while !(self.is_token(SyntaxKind::OpenBraceToken)
539 || self.is_token(SyntaxKind::SemicolonToken)
540 || self.is_token(SyntaxKind::CommaToken)
541 || self.is_token(SyntaxKind::CloseBraceToken))
542 {
543 self.next_token();
544 }
545
546 if self.is_token(SyntaxKind::OpenBraceToken) {
547 let body = self.parse_block();
548 let _ = body;
549 return;
550 }
551
552 if self.is_token(SyntaxKind::SemicolonToken) || self.is_token(SyntaxKind::CommaToken) {
553 self.next_token();
554 }
555 }
556
557 pub fn parse_optional(&mut self, kind: SyntaxKind) -> bool {
559 if self.is_token(kind) {
560 if token_is_keyword(kind) {
562 self.check_keyword_with_escape();
563 }
564 self.next_token();
565 true
566 } else {
567 false
568 }
569 }
570
571 pub fn parse_expected(&mut self, kind: SyntaxKind) -> bool {
575 if self.is_token(kind) {
576 if token_is_keyword(kind) {
578 self.check_keyword_with_escape();
579 }
580 self.next_token();
581 true
582 } else if self.is_token(SyntaxKind::Unknown) {
583 {
588 use tsz_common::diagnostics::diagnostic_codes;
589 self.parse_error_at_current_token(
590 "Invalid character.",
591 diagnostic_codes::INVALID_CHARACTER,
592 );
593 }
594 self.next_token();
595 if self.is_token(kind) {
597 self.next_token();
598 return true;
599 }
600 {
605 use tsz_common::diagnostics::diagnostic_codes;
606 self.parse_error_at_current_token(
607 &format!("'{}' expected.", Self::token_to_string(kind)),
608 diagnostic_codes::EXPECTED,
609 );
610 }
611 false
612 } else {
613 let force_emit = kind == SyntaxKind::CloseParenToken
616 && (self.is_token(SyntaxKind::OpenBraceToken)
617 || self.is_token(SyntaxKind::CloseBraceToken)
618 || self.is_token(SyntaxKind::EndOfFileToken));
619
620 if force_emit || self.should_report_error() {
625 let should_suppress = if force_emit {
628 false } else {
630 match kind {
631 SyntaxKind::CloseBraceToken | SyntaxKind::CloseBracketToken => {
632 if self.is_token(SyntaxKind::EndOfFileToken) {
635 false
636 }
637 else if self.is_statement_start() {
640 true
641 }
642 else {
644 self.scanner.has_preceding_line_break()
645 }
646 }
647 SyntaxKind::CloseParenToken => {
648 if self.is_token(SyntaxKind::EndOfFileToken) {
652 false
653 } else if self.scanner.has_preceding_line_break() {
654 !self.is_statement_start()
656 && !self.is_token(SyntaxKind::CloseBraceToken)
657 } else {
658 false
659 }
660 }
661 _ => false,
662 }
663 };
664
665 if !should_suppress {
666 if force_emit {
668 use tsz_common::diagnostics::diagnostic_codes;
669 self.parse_error_at_current_token(
670 &format!("'{}' expected.", Self::token_to_string(kind)),
671 diagnostic_codes::EXPECTED,
672 );
673 } else {
674 self.error_token_expected(Self::token_to_string(kind));
675 }
676 }
677 }
678 false
679 }
680 }
681
682 pub(crate) const fn token_to_string(kind: SyntaxKind) -> &'static str {
684 match kind {
685 SyntaxKind::OpenBraceToken => "{",
686 SyntaxKind::CloseBraceToken => "}",
687 SyntaxKind::OpenParenToken => "(",
688 SyntaxKind::CloseParenToken => ")",
689 SyntaxKind::OpenBracketToken => "[",
690 SyntaxKind::CloseBracketToken => "]",
691 SyntaxKind::SemicolonToken => ";",
692 SyntaxKind::CommaToken => ",",
693 SyntaxKind::ColonToken => ":",
694 SyntaxKind::DotToken => ".",
695 SyntaxKind::EqualsToken => "=",
696 SyntaxKind::GreaterThanToken => ">",
697 SyntaxKind::LessThanToken => "<",
698 SyntaxKind::QuestionToken => "?",
699 SyntaxKind::ExclamationToken => "!",
700 SyntaxKind::AtToken => "@",
701 SyntaxKind::AmpersandToken => "&",
702 SyntaxKind::BarToken => "|",
703 SyntaxKind::PlusToken => "+",
704 SyntaxKind::MinusToken => "-",
705 SyntaxKind::AsteriskToken => "*",
706 SyntaxKind::SlashToken => "/",
707 SyntaxKind::EqualsGreaterThanToken => "=>",
708 SyntaxKind::DotDotDotToken => "...",
709 SyntaxKind::Identifier => "identifier",
710 SyntaxKind::TryKeyword => "try",
711 _ => "token",
712 }
713 }
714
715 pub(crate) fn parse_error_at(&mut self, start: u32, length: u32, message: &str, code: u32) {
716 if let Some(last) = self.parse_diagnostics.last()
720 && last.start == start
721 {
722 return;
723 }
724 self.last_error_pos = start;
726 self.parse_diagnostics.push(ParseDiagnostic {
727 start,
728 length,
729 message: message.to_string(),
730 code,
731 });
732 }
733
734 pub fn parse_error_at_current_token(&mut self, message: &str, code: u32) {
736 let start = self.u32_from_usize(self.scanner.get_token_start());
737 let end = self.u32_from_usize(self.scanner.get_token_end());
738 self.parse_error_at(start, end - start, message, code);
739 }
740
741 pub(crate) fn report_invalid_string_or_template_escape_errors(&mut self) {
743 let token_text = self.scanner.get_token_text_ref().to_string();
744 if token_text.is_empty()
745 || (self.scanner.get_token_flags() & TokenFlags::ContainsInvalidEscape as u32) == 0
746 {
747 return;
748 }
749
750 let bytes = token_text.as_bytes();
751 let token_len = bytes.len();
752 let token_start = self.token_pos() as usize;
753
754 let Some((content_start_offset, content_end_offset)) =
755 self.string_template_escape_content_span(token_len, bytes)
756 else {
757 return;
758 };
759
760 if content_end_offset <= content_start_offset || content_end_offset > token_len {
761 return;
762 }
763
764 let raw = &bytes[content_start_offset..content_end_offset];
765 let content_start = token_start + content_start_offset;
766
767 let mut i = 0usize;
768
769 while i < raw.len() {
770 if raw[i] != b'\\' {
771 i += 1;
772 continue;
773 }
774 if i + 1 >= raw.len() {
775 break;
776 }
777 i = match raw[i + 1] {
778 b'x' => self.report_invalid_string_or_template_hex_escape(raw, content_start, i),
779 b'u' => {
780 self.report_invalid_string_or_template_unicode_escape(raw, content_start, i)
781 }
782 _ => i + 1,
783 };
784 }
785 }
786
787 fn string_template_escape_content_span(
788 &self,
789 token_len: usize,
790 bytes: &[u8],
791 ) -> Option<(usize, usize)> {
792 match self.current_token {
793 SyntaxKind::StringLiteral => {
794 if token_len < 2
795 || (bytes[0] != b'"' && bytes[0] != b'\'')
796 || bytes[token_len - 1] != bytes[0]
797 {
798 return None;
799 }
800 Some((1, token_len - 1))
801 }
802 SyntaxKind::NoSubstitutionTemplateLiteral => {
803 if bytes[0] != b'`' || bytes[token_len - 1] != b'`' {
804 return None;
805 }
806 Some((1, token_len - 1))
807 }
808 SyntaxKind::TemplateHead => {
809 if bytes[0] != b'`' || !bytes.ends_with(b"${") {
810 return None;
811 }
812 Some((1, token_len - 2))
813 }
814 SyntaxKind::TemplateMiddle | SyntaxKind::TemplateTail => {
815 if bytes[0] != b'}' {
816 return None;
817 }
818 if bytes.ends_with(b"${") {
819 Some((1, token_len - 2))
820 } else if bytes.ends_with(b"`") {
821 Some((1, token_len - 1))
822 } else {
823 Some((1, token_len))
824 }
825 }
826 _ => None,
827 }
828 }
829
830 fn report_invalid_string_or_template_hex_escape(
831 &mut self,
832 raw: &[u8],
833 content_start: usize,
834 i: usize,
835 ) -> usize {
836 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
837
838 let first = i + 2;
839 let second = i + 3;
840 let err_len = |offset: usize| u32::from(offset < raw.len());
841
842 if first >= raw.len() || !Self::is_hex_digit(raw[first]) {
843 self.parse_error_at(
844 self.u32_from_usize(content_start + first),
845 err_len(first),
846 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
847 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
848 );
849 } else if second >= raw.len() || !Self::is_hex_digit(raw[second]) {
850 self.parse_error_at(
851 self.u32_from_usize(content_start + second),
852 err_len(second),
853 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
854 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
855 );
856 }
857 i + 2
858 }
859
860 fn report_invalid_string_or_template_unicode_escape(
861 &mut self,
862 raw: &[u8],
863 content_start: usize,
864 i: usize,
865 ) -> usize {
866 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
867
868 if i + 2 >= raw.len() {
869 self.parse_error_at(
870 self.u32_from_usize(content_start + i + 2),
871 u32::from(i + 2 < raw.len()),
872 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
873 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
874 );
875 return i + 2;
876 }
877
878 if raw[i + 2] == b'{' {
879 let mut close = i + 3;
880 let mut has_digit = false;
881 while close < raw.len() && Self::is_hex_digit(raw[close]) {
882 has_digit = true;
883 close += 1;
884 }
885 if close >= raw.len() {
886 if !has_digit {
887 self.parse_error_at(
889 self.u32_from_usize(content_start + i + 3),
890 0,
891 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
892 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
893 );
894 } else {
895 self.parse_error_at(
897 self.u32_from_usize(content_start + close),
898 0,
899 diagnostic_messages::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
900 diagnostic_codes::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
901 );
902 }
903 } else if raw[close] == b'}' {
904 if !has_digit {
905 self.parse_error_at(
906 self.u32_from_usize(content_start + close),
907 1,
908 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
909 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
910 );
911 } else {
912 let hex_str = std::str::from_utf8(&raw[i + 3..close]).unwrap_or("");
914 if let Ok(value) = u32::from_str_radix(hex_str, 16)
915 && value > 0x10FFFF
916 {
917 self.parse_error_at(
918 self.u32_from_usize(content_start + i),
919 (close + 1 - i) as u32,
920 diagnostic_messages::AN_EXTENDED_UNICODE_ESCAPE_VALUE_MUST_BE_BETWEEN_0X0_AND_0X10FFFF_INCLUSIVE,
921 diagnostic_codes::AN_EXTENDED_UNICODE_ESCAPE_VALUE_MUST_BE_BETWEEN_0X0_AND_0X10FFFF_INCLUSIVE,
922 );
923 }
924 }
925 } else if !has_digit {
926 self.parse_error_at(
927 self.u32_from_usize(content_start + i + 3),
928 1,
929 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
930 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
931 );
932 } else {
933 self.parse_error_at(
934 self.u32_from_usize(content_start + close),
935 1,
936 diagnostic_messages::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
937 diagnostic_codes::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
938 );
939 }
940 close + 1
941 } else {
942 let first = i + 2;
943 let second = i + 3;
944 let third = i + 4;
945 let fourth = i + 5;
946 let err_len = |offset: usize| u32::from(offset < raw.len());
947
948 if first >= raw.len() || !Self::is_hex_digit(raw[first]) {
949 self.parse_error_at(
950 self.u32_from_usize(content_start + first),
951 err_len(first),
952 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
953 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
954 );
955 } else if second >= raw.len() || !Self::is_hex_digit(raw[second]) {
956 self.parse_error_at(
957 self.u32_from_usize(content_start + second),
958 err_len(second),
959 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
960 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
961 );
962 } else if third >= raw.len() || !Self::is_hex_digit(raw[third]) {
963 self.parse_error_at(
964 self.u32_from_usize(content_start + third),
965 err_len(third),
966 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
967 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
968 );
969 } else if fourth >= raw.len() || !Self::is_hex_digit(raw[fourth]) {
970 self.parse_error_at(
971 self.u32_from_usize(content_start + fourth),
972 err_len(fourth),
973 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
974 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
975 );
976 }
977 i + 2
978 }
979 }
980
981 #[inline]
982 const fn is_hex_digit(byte: u8) -> bool {
983 byte.is_ascii_hexdigit()
984 }
985
986 pub(crate) fn report_invalid_regular_expression_escape_errors(&mut self) {
988 let token_text = self.scanner.get_token_text_ref().to_string();
989 if !token_text.starts_with('/') || token_text.len() < 2 {
990 return;
991 }
992
993 let bytes = token_text.as_bytes();
994 let mut i = 1usize;
995 let mut in_escape = false;
996 let mut in_character_class = false;
997 while i < bytes.len() {
998 let ch = bytes[i];
999 if in_escape {
1000 in_escape = false;
1001 i += 1;
1002 continue;
1003 }
1004 if ch == b'\\' {
1005 in_escape = true;
1006 i += 1;
1007 continue;
1008 }
1009 if ch == b'[' {
1010 in_character_class = true;
1011 i += 1;
1012 continue;
1013 }
1014 if ch == b']' {
1015 in_character_class = false;
1016 i += 1;
1017 continue;
1018 }
1019 if ch == b'/' && !in_character_class {
1020 break;
1021 }
1022 i += 1;
1023 }
1024 if i >= bytes.len() {
1025 return;
1026 }
1027
1028 let body = &token_text[1..i];
1029 let flags = if i + 1 < token_text.len() {
1030 &token_text[i + 1..]
1031 } else {
1032 ""
1033 };
1034 let has_unicode_flag = flags.as_bytes().iter().any(|&b| b == b'u' || b == b'v');
1035 if !has_unicode_flag {
1036 return;
1037 }
1038
1039 let body_start = self.token_pos() as usize + 1;
1040 let raw = body.as_bytes();
1041 let mut j = 0usize;
1042
1043 while j < raw.len() {
1044 if raw[j] != b'\\' {
1045 j += 1;
1046 continue;
1047 }
1048 if j + 1 >= raw.len() {
1049 break;
1050 }
1051 match raw[j + 1] {
1052 b'x' => {
1053 j = self.report_invalid_regular_expression_hex_escape(raw, body_start, j);
1054 }
1055 b'u' => {
1056 if let Some(next) =
1057 self.report_invalid_regular_expression_unicode_escape(raw, body_start, j)
1058 {
1059 j = next;
1060 } else {
1061 break;
1062 }
1063 }
1064 _ => {
1065 j += 1;
1066 }
1067 }
1068 }
1069 }
1070
1071 fn report_invalid_regular_expression_hex_escape(
1072 &mut self,
1073 raw: &[u8],
1074 body_start: usize,
1075 j: usize,
1076 ) -> usize {
1077 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
1078
1079 let first = j + 2;
1080 let second = j + 3;
1081 if first >= raw.len() || !Self::is_hex_digit(raw[first]) {
1082 self.parse_error_at(
1083 self.u32_from_usize(body_start + first),
1084 u32::from(first < raw.len()),
1085 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1086 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1087 );
1088 } else if second >= raw.len() || !Self::is_hex_digit(raw[second]) {
1089 self.parse_error_at(
1090 self.u32_from_usize(body_start + second),
1091 u32::from(second < raw.len()),
1092 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1093 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1094 );
1095 }
1096 j + 2
1097 }
1098
1099 fn report_invalid_regular_expression_unicode_escape(
1100 &mut self,
1101 raw: &[u8],
1102 body_start: usize,
1103 j: usize,
1104 ) -> Option<usize> {
1105 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
1106
1107 if j + 2 < raw.len() && raw[j + 2] == b'{' {
1108 let mut close = j + 3;
1109 let mut has_digit = false;
1110 while close < raw.len() && Self::is_hex_digit(raw[close]) {
1111 has_digit = true;
1112 close += 1;
1113 }
1114 if close >= raw.len() {
1115 self.parse_error_at(
1116 self.u32_from_usize(body_start + close),
1117 0,
1118 diagnostic_messages::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
1119 diagnostic_codes::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
1120 );
1121 return None;
1122 }
1123 if raw[close] == b'}' {
1124 if !has_digit {
1125 self.parse_error_at(
1126 self.u32_from_usize(body_start + close),
1127 1,
1128 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1129 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1130 );
1131 }
1132 } else if !has_digit {
1133 self.parse_error_at(
1134 self.u32_from_usize(body_start + j + 3),
1135 1,
1136 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1137 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1138 );
1139 } else {
1140 self.parse_error_at(
1141 self.u32_from_usize(body_start + close),
1142 1,
1143 diagnostic_messages::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
1144 diagnostic_codes::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
1145 );
1146 self.parse_error_at(
1147 self.u32_from_usize(body_start + close),
1148 1,
1149 diagnostic_messages::UNEXPECTED_DID_YOU_MEAN_TO_ESCAPE_IT_WITH_BACKSLASH,
1150 diagnostic_codes::UNEXPECTED_DID_YOU_MEAN_TO_ESCAPE_IT_WITH_BACKSLASH,
1151 );
1152 }
1153 Some(close + 1)
1154 } else {
1155 let first = j + 2;
1156 let second = j + 3;
1157 let third = j + 4;
1158 let fourth = j + 5;
1159 if first >= raw.len() || !Self::is_hex_digit(raw[first]) {
1160 self.parse_error_at(
1161 self.u32_from_usize(body_start + first),
1162 u32::from(first < raw.len()),
1163 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1164 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1165 );
1166 } else if second >= raw.len() || !Self::is_hex_digit(raw[second]) {
1167 self.parse_error_at(
1168 self.u32_from_usize(body_start + second),
1169 u32::from(second < raw.len()),
1170 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1171 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1172 );
1173 } else if third >= raw.len() || !Self::is_hex_digit(raw[third]) {
1174 self.parse_error_at(
1175 self.u32_from_usize(body_start + third),
1176 u32::from(third < raw.len()),
1177 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1178 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1179 );
1180 } else if fourth >= raw.len() || !Self::is_hex_digit(raw[fourth]) {
1181 self.parse_error_at(
1182 self.u32_from_usize(body_start + fourth),
1183 u32::from(fourth < raw.len()),
1184 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1185 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1186 );
1187 }
1188 Some(j + 2)
1189 }
1190 }
1191
1192 pub(crate) fn error_expression_expected(&mut self) {
1198 if self.should_report_error() {
1202 use tsz_common::diagnostics::diagnostic_codes;
1203 self.parse_error_at_current_token(
1204 "Expression expected.",
1205 diagnostic_codes::EXPRESSION_EXPECTED,
1206 );
1207 }
1208 }
1209
1210 pub(crate) fn error_expression_or_comma_expected(&mut self) {
1213 if self.should_report_error() {
1214 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
1215 self.parse_error_at_current_token(
1216 diagnostic_messages::EXPRESSION_OR_COMMA_EXPECTED,
1217 diagnostic_codes::EXPRESSION_OR_COMMA_EXPECTED,
1218 );
1219 }
1220 }
1221
1222 pub(crate) fn error_argument_expression_expected(&mut self) {
1225 if self.should_report_error() {
1226 use tsz_common::diagnostics::diagnostic_codes;
1227 self.parse_error_at_current_token(
1228 "Argument expression expected.",
1229 diagnostic_codes::ARGUMENT_EXPRESSION_EXPECTED,
1230 );
1231 }
1232 }
1233
1234 pub(crate) fn error_type_expected(&mut self) {
1236 use tsz_common::diagnostics::diagnostic_codes;
1237 self.parse_error_at_current_token("Type expected", diagnostic_codes::TYPE_EXPECTED);
1238 }
1239
1240 pub(crate) fn error_identifier_expected(&mut self) {
1242 if self.is_token(SyntaxKind::Unknown) {
1246 if self.should_report_error() {
1247 use tsz_common::diagnostics::diagnostic_codes;
1248 self.parse_error_at_current_token(
1249 "Invalid character.",
1250 diagnostic_codes::INVALID_CHARACTER,
1251 );
1252 }
1253 return;
1254 }
1255 if self.should_report_error() {
1259 use tsz_common::diagnostics::diagnostic_codes;
1260 self.parse_error_at_current_token(
1261 "Identifier expected",
1262 diagnostic_codes::IDENTIFIER_EXPECTED,
1263 );
1264 }
1265 }
1266
1267 #[inline]
1270 pub(crate) const fn is_reserved_word(&self) -> bool {
1271 self.current_token as u16 >= SyntaxKind::FIRST_RESERVED_WORD as u16
1274 && self.current_token as u16 <= SyntaxKind::LAST_RESERVED_WORD as u16
1275 }
1276
1277 const fn current_keyword_text(&self) -> &'static str {
1279 match self.current_token {
1280 SyntaxKind::BreakKeyword => "break",
1281 SyntaxKind::CaseKeyword => "case",
1282 SyntaxKind::CatchKeyword => "catch",
1283 SyntaxKind::ClassKeyword => "class",
1284 SyntaxKind::ConstKeyword => "const",
1285 SyntaxKind::ContinueKeyword => "continue",
1286 SyntaxKind::DebuggerKeyword => "debugger",
1287 SyntaxKind::DefaultKeyword => "default",
1288 SyntaxKind::DeleteKeyword => "delete",
1289 SyntaxKind::DoKeyword => "do",
1290 SyntaxKind::ElseKeyword => "else",
1291 SyntaxKind::EnumKeyword => "enum",
1292 SyntaxKind::ExportKeyword => "export",
1293 SyntaxKind::ExtendsKeyword => "extends",
1294 SyntaxKind::FalseKeyword => "false",
1295 SyntaxKind::FinallyKeyword => "finally",
1296 SyntaxKind::ForKeyword => "for",
1297 SyntaxKind::FunctionKeyword => "function",
1298 SyntaxKind::IfKeyword => "if",
1299 SyntaxKind::ImportKeyword => "import",
1300 SyntaxKind::InKeyword => "in",
1301 SyntaxKind::InstanceOfKeyword => "instanceof",
1302 SyntaxKind::NewKeyword => "new",
1303 SyntaxKind::NullKeyword => "null",
1304 SyntaxKind::ReturnKeyword => "return",
1305 SyntaxKind::SuperKeyword => "super",
1306 SyntaxKind::SwitchKeyword => "switch",
1307 SyntaxKind::ThisKeyword => "this",
1308 SyntaxKind::ThrowKeyword => "throw",
1309 SyntaxKind::TrueKeyword => "true",
1310 SyntaxKind::TryKeyword => "try",
1311 SyntaxKind::TypeOfKeyword => "typeof",
1312 SyntaxKind::VarKeyword => "var",
1313 SyntaxKind::VoidKeyword => "void",
1314 SyntaxKind::WhileKeyword => "while",
1315 SyntaxKind::WithKeyword => "with",
1316 _ => "reserved word",
1317 }
1318 }
1319
1320 pub(crate) fn error_reserved_word_identifier(&mut self) {
1322 if self.should_report_error() {
1324 use tsz_common::diagnostics::diagnostic_codes;
1325 let word = self.current_keyword_text();
1326 if self.is_token(SyntaxKind::YieldKeyword) && self.in_generator_context() {
1327 self.parse_error_at_current_token(
1328 "Identifier expected. 'yield' is a reserved word in strict mode.",
1329 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_IN_STRICT_MODE,
1330 );
1331 self.next_token();
1333 return;
1334 }
1335 self.parse_error_at_current_token(
1336 &format!(
1337 "Identifier expected. '{word}' is a reserved word that cannot be used here."
1338 ),
1339 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_THAT_CANNOT_BE_USED_HERE,
1340 );
1341 self.next_token();
1343 }
1344 }
1345
1346 pub(crate) fn error_token_expected(&mut self, token: &str) {
1348 if self.is_token(SyntaxKind::Unknown) {
1354 if self.should_report_error() {
1355 use tsz_common::diagnostics::diagnostic_codes;
1356 self.parse_error_at_current_token(
1357 "Invalid character.",
1358 diagnostic_codes::INVALID_CHARACTER,
1359 );
1360 }
1361 return;
1362 }
1363 if self.should_report_error() {
1367 use tsz_common::diagnostics::diagnostic_codes;
1368 self.parse_error_at_current_token(
1369 &format!("'{token}' expected."),
1370 diagnostic_codes::EXPECTED,
1371 );
1372 }
1373 }
1374
1375 pub(crate) fn error_comma_expected(&mut self) {
1377 self.error_token_expected(",");
1378 }
1379
1380 pub(crate) fn is_parameter_start(&mut self) -> bool {
1382 self.is_parameter_modifier()
1384 || self.is_token(SyntaxKind::AtToken) || self.is_token(SyntaxKind::DotDotDotToken) || self.is_identifier_or_keyword()
1387 || self.is_token(SyntaxKind::OpenBraceToken) || self.is_token(SyntaxKind::OpenBracketToken) }
1390
1391 pub(crate) fn error_unterminated_template_literal_at(&mut self, start: u32, end: u32) {
1393 use tsz_common::diagnostics::diagnostic_codes;
1394 let length = end.saturating_sub(start).max(1);
1395 self.parse_error_at(
1396 start,
1397 length,
1398 "Unterminated template literal.",
1399 diagnostic_codes::UNTERMINATED_TEMPLATE_LITERAL,
1400 );
1401 }
1402
1403 pub(crate) fn error_declaration_expected(&mut self) {
1405 use tsz_common::diagnostics::diagnostic_codes;
1406 self.parse_error_at_current_token(
1407 "Declaration expected",
1408 diagnostic_codes::DECLARATION_EXPECTED,
1409 );
1410 }
1411
1412 pub(crate) fn error_statement_expected(&mut self) {
1414 use tsz_common::diagnostics::diagnostic_codes;
1415 self.parse_error_at_current_token(
1416 "Statement expected",
1417 diagnostic_codes::STATEMENT_EXPECTED,
1418 );
1419 }
1420
1421 pub(crate) fn check_using_outside_block(&mut self, statement: NodeIndex) {
1423 use crate::parser::node_flags;
1424 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
1425
1426 if statement.is_none() {
1427 return;
1428 }
1429
1430 if let Some(node) = self.arena.get(statement) {
1432 if node.kind == syntax_kind_ext::VARIABLE_STATEMENT {
1434 let is_using = (node.flags
1436 & self.u16_from_node_flags(node_flags::USING | node_flags::AWAIT_USING))
1437 != 0;
1438 if is_using {
1439 self.parse_error_at(
1441 node.pos,
1442 node.end.saturating_sub(node.pos).max(1),
1443 diagnostic_messages::DECLARATIONS_CAN_ONLY_BE_DECLARED_INSIDE_A_BLOCK,
1444 diagnostic_codes::DECLARATIONS_CAN_ONLY_BE_DECLARED_INSIDE_A_BLOCK,
1445 );
1446 }
1447 }
1448 }
1449 }
1450
1451 pub(crate) fn error_unexpected_token(&mut self) {
1453 use tsz_common::diagnostics::diagnostic_codes;
1454 self.parse_error_at_current_token("Unexpected token", diagnostic_codes::UNEXPECTED_TOKEN);
1455 }
1456
1457 pub(crate) fn parse_semicolon(&mut self) {
1459 if self.is_token(SyntaxKind::SemicolonToken) {
1460 self.next_token();
1461 } else if self.is_token(SyntaxKind::Unknown) {
1462 } else if !self.can_parse_semicolon() {
1465 if self.should_report_error() {
1471 self.error_token_expected(";");
1472 }
1473 }
1474 }
1475
1476 pub(crate) fn parse_error_for_missing_semicolon_after(&mut self, expression: NodeIndex) {
1488 use crate::parser::spelling;
1489 use tsz_common::diagnostics::diagnostic_codes;
1490
1491 let Some((pos, len, expression_text)) =
1492 self.missing_semicolon_after_expression_text(expression)
1493 else {
1494 if self.should_report_error() {
1495 self.error_token_expected(";");
1496 }
1497 return;
1498 };
1499
1500 if self.parse_missing_semicolon_keyword_error(pos, len, &expression_text) {
1501 return;
1502 }
1503
1504 if self.should_suppress_type_or_keyword_suggestion_for_missing_semicolon(
1505 expression_text.as_str(),
1506 pos,
1507 ) {
1508 return;
1509 }
1510
1511 if let Some(suggestion) = spelling::suggest_keyword(&expression_text) {
1512 if !self.should_suppress_type_or_keyword_suggestion_for_missing_semicolon(
1513 suggestion.as_str(),
1514 pos,
1515 ) {
1516 self.parse_error_at(
1517 pos,
1518 len,
1519 &format!("Unknown keyword or identifier. Did you mean '{suggestion}'?"),
1520 diagnostic_codes::UNKNOWN_KEYWORD_OR_IDENTIFIER_DID_YOU_MEAN,
1521 );
1522 }
1523 return;
1524 }
1525
1526 if self.is_token(SyntaxKind::Unknown) {
1527 return;
1528 }
1529
1530 if self.should_report_error() {
1531 self.parse_error_at(
1532 pos,
1533 len,
1534 "Unexpected keyword or identifier.",
1535 diagnostic_codes::UNEXPECTED_KEYWORD_OR_IDENTIFIER,
1536 );
1537 }
1538 }
1539
1540 fn missing_semicolon_after_expression_text(
1541 &self,
1542 expression: NodeIndex,
1543 ) -> Option<(u32, u32, String)> {
1544 let node = self.arena.get(expression)?;
1545
1546 if node.kind != SyntaxKind::Identifier as u16 {
1547 return None;
1548 }
1549
1550 let source = self.scanner.source_text();
1553 let text = &source[node.pos as usize..node.end as usize];
1554 if text.is_empty() {
1555 return None;
1556 }
1557
1558 Some((node.pos, node.end - node.pos, text.to_string()))
1559 }
1560
1561 fn parse_missing_semicolon_keyword_error(
1562 &mut self,
1563 pos: u32,
1564 len: u32,
1565 expression_text: &str,
1566 ) -> bool {
1567 use tsz_common::diagnostics::diagnostic_codes;
1568
1569 match expression_text {
1570 "const" | "let" | "var" => {
1571 self.parse_error_at(
1572 pos,
1573 len,
1574 "Variable declaration not allowed at this location.",
1575 diagnostic_codes::VARIABLE_DECLARATION_NOT_ALLOWED_AT_THIS_LOCATION,
1576 );
1577 true
1578 }
1579 "declare" => true,
1580 "interface" => {
1581 if self.is_token(SyntaxKind::OpenBraceToken) {
1582 self.parse_error_at_current_token(
1583 "Interface must be given a name.",
1584 diagnostic_codes::INTERFACE_MUST_BE_GIVEN_A_NAME,
1585 );
1586 } else {
1587 let name = self.scanner.get_token_value_ref().to_string();
1588 self.parse_error_at_current_token(
1589 &format!("Interface name cannot be '{name}'."),
1590 diagnostic_codes::EXPECTED,
1591 );
1592 }
1593 true
1594 }
1595 "type" => {
1596 self.parse_error_at_current_token("'=' expected.", diagnostic_codes::EXPECTED);
1597 true
1598 }
1599 _ => false,
1600 }
1601 }
1602
1603 fn should_suppress_type_or_keyword_suggestion_for_missing_semicolon(
1604 &self,
1605 text: &str,
1606 token_pos: u32,
1607 ) -> bool {
1608 if !matches!(
1609 text,
1610 "string"
1611 | "number"
1612 | "boolean"
1613 | "symbol"
1614 | "bigint"
1615 | "object"
1616 | "void"
1617 | "undefined"
1618 | "null"
1619 | "never"
1620 | "unknown"
1621 | "any"
1622 ) {
1623 return false;
1624 }
1625
1626 let source = self.scanner.source_text().as_bytes();
1627 let mut i = token_pos as usize;
1628 while i > 0 && source[i - 1].is_ascii_whitespace() {
1629 i -= 1;
1630 }
1631 i > 0 && source[i - 1] == b':'
1632 }
1633
1634 pub(crate) fn can_parse_semicolon(&self) -> bool {
1647 if self.is_token(SyntaxKind::SemicolonToken) {
1649 return true;
1650 }
1651
1652 if self.is_token(SyntaxKind::CloseBraceToken) {
1654 return true;
1655 }
1656
1657 if self.is_token(SyntaxKind::EndOfFileToken) {
1659 return true;
1660 }
1661
1662 self.scanner.has_preceding_line_break()
1664 }
1665
1666 pub(crate) fn can_parse_semicolon_for_restricted_production(&self) -> bool {
1677 if self.is_token(SyntaxKind::SemicolonToken) {
1679 return true;
1680 }
1681
1682 if self.is_token(SyntaxKind::CloseBraceToken) {
1684 return true;
1685 }
1686
1687 if self.is_token(SyntaxKind::EndOfFileToken) {
1689 return true;
1690 }
1691
1692 if self.scanner.has_preceding_line_break() {
1695 return true;
1696 }
1697
1698 false
1699 }
1700
1701 pub(crate) const fn is_at_expression_end(&self) -> bool {
1713 match self.token() {
1714 SyntaxKind::SemicolonToken
1716 | SyntaxKind::CloseBraceToken
1717 | SyntaxKind::CloseParenToken
1718 | SyntaxKind::CloseBracketToken
1719 | SyntaxKind::EndOfFileToken => true,
1720 _ => false,
1725 }
1726 }
1727
1728 pub(crate) const fn is_statement_start(&self) -> bool {
1730 matches!(
1731 self.token(),
1732 SyntaxKind::VarKeyword
1733 | SyntaxKind::LetKeyword
1734 | SyntaxKind::ConstKeyword
1735 | SyntaxKind::FunctionKeyword
1736 | SyntaxKind::ClassKeyword
1737 | SyntaxKind::IfKeyword
1738 | SyntaxKind::ForKeyword
1739 | SyntaxKind::WhileKeyword
1740 | SyntaxKind::DoKeyword
1741 | SyntaxKind::SwitchKeyword
1742 | SyntaxKind::TryKeyword
1743 | SyntaxKind::CatchKeyword
1744 | SyntaxKind::FinallyKeyword
1745 | SyntaxKind::WithKeyword
1746 | SyntaxKind::DebuggerKeyword
1747 | SyntaxKind::ReturnKeyword
1748 | SyntaxKind::BreakKeyword
1749 | SyntaxKind::ContinueKeyword
1750 | SyntaxKind::ThrowKeyword
1751 | SyntaxKind::YieldKeyword
1752 | SyntaxKind::AsyncKeyword
1753 | SyntaxKind::UsingKeyword
1754 | SyntaxKind::AwaitKeyword
1755 | SyntaxKind::InterfaceKeyword
1756 | SyntaxKind::TypeKeyword
1757 | SyntaxKind::EnumKeyword
1758 | SyntaxKind::NamespaceKeyword
1759 | SyntaxKind::ModuleKeyword
1760 | SyntaxKind::ImportKeyword
1761 | SyntaxKind::ExportKeyword
1762 | SyntaxKind::DeclareKeyword
1763 | SyntaxKind::Identifier
1764 | SyntaxKind::StringLiteral
1765 | SyntaxKind::AtToken
1766 | SyntaxKind::NumericLiteral
1767 | SyntaxKind::BigIntLiteral
1768 | SyntaxKind::TrueKeyword
1769 | SyntaxKind::FalseKeyword
1770 | SyntaxKind::NullKeyword
1771 | SyntaxKind::ThisKeyword
1772 | SyntaxKind::SuperKeyword
1773 | SyntaxKind::ExclamationToken
1774 | SyntaxKind::TildeToken
1775 | SyntaxKind::PlusToken
1776 | SyntaxKind::MinusToken
1777 | SyntaxKind::PlusPlusToken
1778 | SyntaxKind::MinusMinusToken
1779 | SyntaxKind::TypeOfKeyword
1780 | SyntaxKind::VoidKeyword
1781 | SyntaxKind::DeleteKeyword
1782 | SyntaxKind::OpenBraceToken
1783 | SyntaxKind::SemicolonToken
1784 | SyntaxKind::OpenParenToken
1785 | SyntaxKind::OpenBracketToken
1786 | SyntaxKind::LessThanToken
1787 )
1788 }
1789
1790 pub(crate) const fn is_resync_sync_point(&self) -> bool {
1794 self.is_statement_start()
1795 || matches!(
1796 self.token(),
1797 SyntaxKind::ElseKeyword
1798 | SyntaxKind::CaseKeyword
1799 | SyntaxKind::DefaultKeyword
1800 | SyntaxKind::CatchKeyword
1801 | SyntaxKind::FinallyKeyword
1802 | SyntaxKind::CommaToken
1803 )
1804 }
1805
1806 pub(crate) fn resync_after_error_with_statement_starts(
1811 &mut self,
1812 allow_statement_starts: bool,
1813 ) {
1814 if self.is_resync_sync_point_with_statement_starts(allow_statement_starts) {
1816 return;
1817 }
1818
1819 let mut brace_depth = 0u32;
1821 let mut paren_depth = 0u32;
1822 let mut bracket_depth = 0u32;
1823 let max_iterations = 1000; for _ in 0..max_iterations {
1826 if self.is_token(SyntaxKind::EndOfFileToken) {
1828 break;
1829 }
1830
1831 match self.token() {
1833 SyntaxKind::OpenBraceToken => {
1834 brace_depth += 1;
1835 self.next_token();
1836 continue;
1837 }
1838 SyntaxKind::CloseBraceToken => {
1839 if brace_depth > 0 {
1840 brace_depth -= 1;
1841 self.next_token();
1842 continue;
1843 }
1844 self.next_token();
1846 break;
1847 }
1848 SyntaxKind::OpenParenToken => {
1849 paren_depth += 1;
1850 self.next_token();
1851 continue;
1852 }
1853 SyntaxKind::CloseParenToken => {
1854 if paren_depth > 0 {
1855 paren_depth -= 1;
1856 self.next_token();
1857 continue;
1858 }
1859 self.next_token();
1862 if self.is_resync_sync_point_with_statement_starts(allow_statement_starts) {
1863 break;
1864 }
1865 continue;
1866 }
1867 SyntaxKind::OpenBracketToken => {
1868 bracket_depth += 1;
1869 self.next_token();
1870 continue;
1871 }
1872 SyntaxKind::CloseBracketToken => {
1873 if bracket_depth > 0 {
1874 bracket_depth -= 1;
1875 self.next_token();
1876 continue;
1877 }
1878 self.next_token();
1880 continue;
1881 }
1882 SyntaxKind::SemicolonToken => {
1883 self.next_token();
1885 break;
1886 }
1887 _ => {}
1888 }
1889
1890 if brace_depth == 0
1892 && paren_depth == 0
1893 && bracket_depth == 0
1894 && self.is_resync_sync_point_with_statement_starts(allow_statement_starts)
1895 {
1896 break;
1897 }
1898
1899 self.next_token();
1901 }
1902 }
1903
1904 fn is_resync_sync_point_with_statement_starts(&self, allow_statement_starts: bool) -> bool {
1905 self.is_resync_sync_point()
1906 && (allow_statement_starts || self.token() != SyntaxKind::Identifier)
1907 }
1908
1909 pub(crate) fn resync_after_error(&mut self) {
1911 self.resync_after_error_with_statement_starts(true);
1912 }
1913
1914 pub(crate) const fn is_expression_start(&self) -> bool {
1920 matches!(
1921 self.token(),
1922 SyntaxKind::NumericLiteral
1923 | SyntaxKind::BigIntLiteral
1924 | SyntaxKind::StringLiteral
1925 | SyntaxKind::NoSubstitutionTemplateLiteral
1926 | SyntaxKind::TemplateHead
1927 | SyntaxKind::TemplateMiddle
1928 | SyntaxKind::TemplateTail
1929 | SyntaxKind::TrueKeyword
1930 | SyntaxKind::FalseKeyword
1931 | SyntaxKind::NullKeyword
1932 | SyntaxKind::Identifier
1933 | SyntaxKind::ThisKeyword
1934 | SyntaxKind::SuperKeyword
1935 | SyntaxKind::ImportKeyword
1936 | SyntaxKind::TypeKeyword
1937 | SyntaxKind::AnyKeyword
1938 | SyntaxKind::StringKeyword
1939 | SyntaxKind::NumberKeyword
1940 | SyntaxKind::BooleanKeyword
1941 | SyntaxKind::SymbolKeyword
1942 | SyntaxKind::BigIntKeyword
1943 | SyntaxKind::ObjectKeyword
1944 | SyntaxKind::NeverKeyword
1945 | SyntaxKind::UnknownKeyword
1946 | SyntaxKind::UndefinedKeyword
1947 | SyntaxKind::RequireKeyword
1948 | SyntaxKind::ModuleKeyword
1949 | SyntaxKind::NamespaceKeyword
1950 | SyntaxKind::AsyncKeyword
1951 | SyntaxKind::AwaitKeyword
1952 | SyntaxKind::YieldKeyword
1953 | SyntaxKind::LetKeyword
1954 | SyntaxKind::NewKeyword
1955 | SyntaxKind::ClassKeyword
1956 | SyntaxKind::FunctionKeyword
1957 | SyntaxKind::DeleteKeyword
1958 | SyntaxKind::VoidKeyword
1959 | SyntaxKind::TypeOfKeyword
1960 | SyntaxKind::InstanceOfKeyword
1961 | SyntaxKind::StaticKeyword
1962 | SyntaxKind::AbstractKeyword
1963 | SyntaxKind::OverrideKeyword
1964 | SyntaxKind::ReadonlyKeyword
1965 | SyntaxKind::AccessorKeyword
1966 | SyntaxKind::GetKeyword
1967 | SyntaxKind::SetKeyword
1968 | SyntaxKind::DeclareKeyword
1969 | SyntaxKind::PublicKeyword
1970 | SyntaxKind::ProtectedKeyword
1971 | SyntaxKind::PrivateKeyword
1972 | SyntaxKind::OfKeyword
1973 | SyntaxKind::SatisfiesKeyword
1974 | SyntaxKind::FromKeyword
1975 | SyntaxKind::AsKeyword
1976 | SyntaxKind::IsKeyword
1977 | SyntaxKind::AssertKeyword
1978 | SyntaxKind::AssertsKeyword
1979 | SyntaxKind::IntrinsicKeyword
1980 | SyntaxKind::OutKeyword
1981 | SyntaxKind::InferKeyword
1982 | SyntaxKind::ConstructorKeyword
1983 | SyntaxKind::UsingKeyword
1984 | SyntaxKind::KeyOfKeyword
1985 | SyntaxKind::UniqueKeyword
1986 | SyntaxKind::GlobalKeyword
1987 | SyntaxKind::InterfaceKeyword
1988 | SyntaxKind::EnumKeyword
1989 | SyntaxKind::DeferKeyword
1990 | SyntaxKind::PrivateIdentifier
1991 | SyntaxKind::PlusToken
1992 | SyntaxKind::MinusToken
1993 | SyntaxKind::AsteriskToken
1994 | SyntaxKind::TildeToken
1995 | SyntaxKind::ExclamationToken
1996 | SyntaxKind::PlusPlusToken
1997 | SyntaxKind::MinusMinusToken
1998 | SyntaxKind::OpenParenToken
1999 | SyntaxKind::OpenBracketToken
2000 | SyntaxKind::OpenBraceToken
2001 | SyntaxKind::LessThanToken
2002 | SyntaxKind::SlashToken
2003 | SyntaxKind::SlashEqualsToken
2004 | SyntaxKind::AtToken
2005 )
2006 }
2007
2008 pub(crate) const fn is_binary_operator(&self) -> bool {
2010 let precedence = self.get_operator_precedence(self.token());
2011 precedence > 0
2012 }
2013
2014 pub(crate) fn resync_to_next_expression_boundary(&mut self) {
2016 let max_iterations = 100;
2017 for _ in 0..max_iterations {
2018 if self.is_token(SyntaxKind::EndOfFileToken) {
2019 break;
2020 }
2021 if self.is_expression_boundary() {
2022 break;
2023 }
2024 if self.is_binary_operator() {
2025 break;
2026 }
2027 if self.is_expression_start() {
2028 break;
2029 }
2030 self.next_token();
2031 }
2032 }
2033
2034 pub(crate) const fn is_expression_boundary(&self) -> bool {
2036 matches!(
2037 self.token(),
2038 SyntaxKind::SemicolonToken
2039 | SyntaxKind::CloseBraceToken
2040 | SyntaxKind::CloseParenToken
2041 | SyntaxKind::CloseBracketToken
2042 | SyntaxKind::CommaToken
2043 | SyntaxKind::ColonToken
2044 | SyntaxKind::CaseKeyword
2045 | SyntaxKind::DefaultKeyword
2046 | SyntaxKind::ElseKeyword
2047 | SyntaxKind::WhileKeyword | SyntaxKind::AsKeyword
2049 | SyntaxKind::SatisfiesKeyword
2050 )
2051 }
2052
2053 pub(crate) fn create_missing_expression(&mut self) -> NodeIndex {
2056 let pos = self.token_pos();
2057 self.arena.add_identifier(
2059 SyntaxKind::Identifier as u16,
2060 pos,
2061 pos,
2062 IdentifierData {
2063 atom: Atom::NONE,
2064 escaped_text: String::new(),
2065 original_text: None,
2066 type_arguments: None,
2067 },
2068 )
2069 }
2070
2071 pub(crate) fn try_recover_binary_rhs(&mut self) -> NodeIndex {
2074 if self.is_expression_boundary() || self.is_statement_start() {
2076 self.create_missing_expression()
2077 } else {
2078 NodeIndex::NONE
2079 }
2080 }
2081
2082 pub(crate) fn try_rescan_greater_token(&mut self) -> SyntaxKind {
2085 if self.current_token == SyntaxKind::GreaterThanToken {
2086 self.current_token = self.scanner.re_scan_greater_token();
2087 }
2088 self.current_token
2089 }
2090
2091 pub(crate) fn parse_expected_greater_than(&mut self) {
2094 match self.current_token {
2095 SyntaxKind::GreaterThanToken => {
2096 self.next_token();
2098 }
2099 SyntaxKind::GreaterThanGreaterThanToken => {
2100 self.scanner.set_pos(self.scanner.get_pos() - 1);
2103 self.current_token = SyntaxKind::GreaterThanToken;
2104 }
2105 SyntaxKind::GreaterThanGreaterThanGreaterThanToken => {
2106 self.scanner.set_pos(self.scanner.get_pos() - 2);
2109 self.current_token = SyntaxKind::GreaterThanGreaterThanToken;
2110 }
2111 SyntaxKind::GreaterThanEqualsToken => {
2112 self.scanner.set_pos(self.scanner.get_pos() - 1);
2114 self.current_token = SyntaxKind::EqualsToken;
2115 }
2116 SyntaxKind::GreaterThanGreaterThanEqualsToken => {
2117 self.scanner.set_pos(self.scanner.get_pos() - 2);
2119 self.current_token = SyntaxKind::GreaterThanEqualsToken;
2120 }
2121 SyntaxKind::GreaterThanGreaterThanGreaterThanEqualsToken => {
2122 self.scanner.set_pos(self.scanner.get_pos() - 3);
2124 self.current_token = SyntaxKind::GreaterThanGreaterThanEqualsToken;
2125 }
2126 _ => {
2127 self.error_token_expected(">");
2129 }
2130 }
2131 }
2132
2133 pub(crate) const fn is_less_than_or_compound(&self) -> bool {
2136 matches!(
2137 self.current_token,
2138 SyntaxKind::LessThanToken
2139 | SyntaxKind::LessThanLessThanToken
2140 | SyntaxKind::LessThanLessThanEqualsToken
2141 )
2142 }
2143
2144 pub(crate) fn parse_expected_less_than(&mut self) {
2154 match self.current_token {
2155 SyntaxKind::LessThanToken => {
2156 self.next_token();
2157 }
2158 SyntaxKind::LessThanLessThanToken => {
2159 self.current_token = SyntaxKind::LessThanToken;
2163 }
2164 SyntaxKind::LessThanLessThanEqualsToken => {
2165 self.current_token = SyntaxKind::LessThanEqualsToken;
2168 }
2169 _ => {
2170 self.error_token_expected("<");
2171 }
2172 }
2173 }
2174
2175 pub(crate) const fn make_node_list(&self, nodes: Vec<NodeIndex>) -> NodeList {
2177 let _ = self;
2178 NodeList {
2179 nodes,
2180 pos: 0,
2181 end: 0,
2182 has_trailing_comma: false,
2183 }
2184 }
2185
2186 pub(crate) const fn get_operator_precedence(&self, token: SyntaxKind) -> u8 {
2188 match token {
2189 SyntaxKind::CommaToken => 1,
2190 SyntaxKind::EqualsToken
2191 | SyntaxKind::PlusEqualsToken
2192 | SyntaxKind::MinusEqualsToken
2193 | SyntaxKind::AsteriskEqualsToken
2194 | SyntaxKind::AsteriskAsteriskEqualsToken
2195 | SyntaxKind::SlashEqualsToken
2196 | SyntaxKind::PercentEqualsToken
2197 | SyntaxKind::LessThanLessThanEqualsToken
2198 | SyntaxKind::GreaterThanGreaterThanEqualsToken
2199 | SyntaxKind::GreaterThanGreaterThanGreaterThanEqualsToken
2200 | SyntaxKind::AmpersandEqualsToken
2201 | SyntaxKind::BarEqualsToken
2202 | SyntaxKind::BarBarEqualsToken
2203 | SyntaxKind::AmpersandAmpersandEqualsToken
2204 | SyntaxKind::QuestionQuestionEqualsToken
2205 | SyntaxKind::CaretEqualsToken => 2,
2206 SyntaxKind::QuestionToken => 3,
2207 SyntaxKind::BarBarToken | SyntaxKind::QuestionQuestionToken => 4,
2208 SyntaxKind::AmpersandAmpersandToken => 5,
2209 SyntaxKind::BarToken => 6,
2210 SyntaxKind::CaretToken => 7,
2211 SyntaxKind::AmpersandToken => 8,
2212 SyntaxKind::EqualsEqualsToken
2213 | SyntaxKind::ExclamationEqualsToken
2214 | SyntaxKind::EqualsEqualsEqualsToken
2215 | SyntaxKind::ExclamationEqualsEqualsToken => 9,
2216 SyntaxKind::InKeyword => {
2218 if self.in_disallow_in_context() {
2219 0
2220 } else {
2221 10
2222 }
2223 }
2224 SyntaxKind::LessThanToken
2225 | SyntaxKind::GreaterThanToken
2226 | SyntaxKind::LessThanEqualsToken
2227 | SyntaxKind::GreaterThanEqualsToken
2228 | SyntaxKind::InstanceOfKeyword
2229 | SyntaxKind::AsKeyword
2230 | SyntaxKind::SatisfiesKeyword => 10,
2231 SyntaxKind::LessThanLessThanToken
2232 | SyntaxKind::GreaterThanGreaterThanToken
2233 | SyntaxKind::GreaterThanGreaterThanGreaterThanToken => 11,
2234 SyntaxKind::PlusToken | SyntaxKind::MinusToken => 12,
2235 SyntaxKind::AsteriskToken | SyntaxKind::SlashToken | SyntaxKind::PercentToken => 13,
2236 SyntaxKind::AsteriskAsteriskToken => 14,
2237 _ => 0,
2238 }
2239 }
2240
2241 pub(crate) fn push_label_scope(&mut self) {
2243 let new_depth = self.label_scopes.len() + 1;
2244 trace!(pos = self.token_pos(), new_depth, "push_label_scope");
2245 self.label_scopes.push(FxHashMap::default());
2246 }
2247
2248 pub(crate) fn pop_label_scope(&mut self) {
2250 let old_depth = self.label_scopes.len();
2251 trace!(pos = self.token_pos(), old_depth, "pop_label_scope");
2252 self.label_scopes.pop();
2253 }
2254
2255 pub(crate) fn check_duplicate_label(&mut self, label_name: &str, label_pos: u32) -> bool {
2258 let scope_depth = self.label_scopes.len();
2259 trace!(label_name, label_pos, scope_depth, "check_duplicate_label");
2260 if let Some(current_scope) = self.label_scopes.last_mut() {
2261 if current_scope.contains_key(label_name) {
2262 use tsz_common::diagnostics::diagnostic_codes;
2264 let message = format!("Duplicate label '{label_name}'.");
2265 trace!(label_name, "duplicate label found");
2266 self.parse_error_at(
2267 label_pos,
2268 self.u32_from_usize(label_name.len()),
2269 &message,
2270 diagnostic_codes::DUPLICATE_LABEL,
2271 );
2272 return true;
2273 }
2274 trace!(label_name, "adding label to scope");
2276 current_scope.insert(label_name.to_string(), label_pos);
2277 }
2278 false
2279 }
2280}
2281
2282