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 pub(crate) fn report_invalid_string_or_template_escape_errors(&mut self) {
741 let token_text = self.scanner.get_token_text_ref().to_string();
742 if token_text.is_empty()
743 || (self.scanner.get_token_flags() & TokenFlags::ContainsInvalidEscape as u32) == 0
744 {
745 return;
746 }
747
748 let bytes = token_text.as_bytes();
749 let token_len = bytes.len();
750 let token_start = self.token_pos() as usize;
751
752 let Some((content_start_offset, content_end_offset)) =
753 self.string_template_escape_content_span(token_len, bytes)
754 else {
755 return;
756 };
757
758 if content_end_offset <= content_start_offset || content_end_offset > token_len {
759 return;
760 }
761
762 let raw = &bytes[content_start_offset..content_end_offset];
763 let content_start = token_start + content_start_offset;
764
765 let mut i = 0usize;
766
767 while i < raw.len() {
768 if raw[i] != b'\\' {
769 i += 1;
770 continue;
771 }
772 if i + 1 >= raw.len() {
773 break;
774 }
775 i = match raw[i + 1] {
776 b'x' => self.report_invalid_string_or_template_hex_escape(raw, content_start, i),
777 b'u' => {
778 self.report_invalid_string_or_template_unicode_escape(raw, content_start, i)
779 }
780 _ => i + 1,
781 };
782 }
783 }
784
785 fn string_template_escape_content_span(
786 &self,
787 token_len: usize,
788 bytes: &[u8],
789 ) -> Option<(usize, usize)> {
790 match self.current_token {
791 SyntaxKind::StringLiteral => {
792 if token_len < 2
793 || (bytes[0] != b'"' && bytes[0] != b'\'')
794 || bytes[token_len - 1] != bytes[0]
795 {
796 return None;
797 }
798 Some((1, token_len - 1))
799 }
800 SyntaxKind::NoSubstitutionTemplateLiteral => {
801 if bytes[0] != b'`' || bytes[token_len - 1] != b'`' {
802 return None;
803 }
804 Some((1, token_len - 1))
805 }
806 SyntaxKind::TemplateHead => {
807 if bytes[0] != b'`' || !bytes.ends_with(b"${") {
808 return None;
809 }
810 Some((1, token_len - 2))
811 }
812 SyntaxKind::TemplateMiddle | SyntaxKind::TemplateTail => {
813 if bytes[0] != b'}' {
814 return None;
815 }
816 if bytes.ends_with(b"${") {
817 Some((1, token_len - 2))
818 } else if bytes.ends_with(b"`") {
819 Some((1, token_len - 1))
820 } else {
821 Some((1, token_len))
822 }
823 }
824 _ => None,
825 }
826 }
827
828 fn report_invalid_string_or_template_hex_escape(
829 &mut self,
830 raw: &[u8],
831 content_start: usize,
832 i: usize,
833 ) -> usize {
834 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
835
836 let first = i + 2;
837 let second = i + 3;
838 let err_len = |offset: usize| u32::from(offset < raw.len());
839
840 if first >= raw.len() || !Self::is_hex_digit(raw[first]) {
841 self.parse_error_at(
842 self.u32_from_usize(content_start + first),
843 err_len(first),
844 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
845 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
846 );
847 } else if second >= raw.len() || !Self::is_hex_digit(raw[second]) {
848 self.parse_error_at(
849 self.u32_from_usize(content_start + second),
850 err_len(second),
851 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
852 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
853 );
854 }
855 i + 2
856 }
857
858 fn report_invalid_string_or_template_unicode_escape(
859 &mut self,
860 raw: &[u8],
861 content_start: usize,
862 i: usize,
863 ) -> usize {
864 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
865
866 if i + 2 >= raw.len() {
867 self.parse_error_at(
868 self.u32_from_usize(content_start + i + 2),
869 u32::from(i + 2 < raw.len()),
870 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
871 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
872 );
873 return i + 2;
874 }
875
876 if raw[i + 2] == b'{' {
877 let mut close = i + 3;
878 let mut has_digit = false;
879 while close < raw.len() && Self::is_hex_digit(raw[close]) {
880 has_digit = true;
881 close += 1;
882 }
883 if close >= raw.len() {
884 if !has_digit {
885 self.parse_error_at(
887 self.u32_from_usize(content_start + i + 3),
888 0,
889 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
890 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
891 );
892 } else {
893 self.parse_error_at(
895 self.u32_from_usize(content_start + close),
896 0,
897 diagnostic_messages::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
898 diagnostic_codes::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
899 );
900 }
901 } else if raw[close] == b'}' {
902 if !has_digit {
903 self.parse_error_at(
904 self.u32_from_usize(content_start + close),
905 1,
906 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
907 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
908 );
909 } else {
910 let hex_str = std::str::from_utf8(&raw[i + 3..close]).unwrap_or("");
912 if let Ok(value) = u32::from_str_radix(hex_str, 16)
913 && value > 0x10FFFF
914 {
915 self.parse_error_at(
916 self.u32_from_usize(content_start + i),
917 (close + 1 - i) as u32,
918 diagnostic_messages::AN_EXTENDED_UNICODE_ESCAPE_VALUE_MUST_BE_BETWEEN_0X0_AND_0X10FFFF_INCLUSIVE,
919 diagnostic_codes::AN_EXTENDED_UNICODE_ESCAPE_VALUE_MUST_BE_BETWEEN_0X0_AND_0X10FFFF_INCLUSIVE,
920 );
921 }
922 }
923 } else if !has_digit {
924 self.parse_error_at(
925 self.u32_from_usize(content_start + i + 3),
926 1,
927 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
928 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
929 );
930 } else {
931 self.parse_error_at(
932 self.u32_from_usize(content_start + close),
933 1,
934 diagnostic_messages::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
935 diagnostic_codes::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
936 );
937 }
938 close + 1
939 } else {
940 let first = i + 2;
941 let second = i + 3;
942 let third = i + 4;
943 let fourth = i + 5;
944 let err_len = |offset: usize| u32::from(offset < raw.len());
945
946 if first >= raw.len() || !Self::is_hex_digit(raw[first]) {
947 self.parse_error_at(
948 self.u32_from_usize(content_start + first),
949 err_len(first),
950 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
951 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
952 );
953 } else if second >= raw.len() || !Self::is_hex_digit(raw[second]) {
954 self.parse_error_at(
955 self.u32_from_usize(content_start + second),
956 err_len(second),
957 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
958 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
959 );
960 } else if third >= raw.len() || !Self::is_hex_digit(raw[third]) {
961 self.parse_error_at(
962 self.u32_from_usize(content_start + third),
963 err_len(third),
964 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
965 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
966 );
967 } else if fourth >= raw.len() || !Self::is_hex_digit(raw[fourth]) {
968 self.parse_error_at(
969 self.u32_from_usize(content_start + fourth),
970 err_len(fourth),
971 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
972 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
973 );
974 }
975 i + 2
976 }
977 }
978
979 #[inline]
980 const fn is_hex_digit(byte: u8) -> bool {
981 byte.is_ascii_hexdigit()
982 }
983
984 pub(crate) fn report_invalid_regular_expression_escape_errors(&mut self) {
986 let token_text = self.scanner.get_token_text_ref().to_string();
987 if !token_text.starts_with('/') || token_text.len() < 2 {
988 return;
989 }
990
991 let bytes = token_text.as_bytes();
992 let mut i = 1usize;
993 let mut in_escape = false;
994 let mut in_character_class = false;
995 while i < bytes.len() {
996 let ch = bytes[i];
997 if in_escape {
998 in_escape = false;
999 i += 1;
1000 continue;
1001 }
1002 if ch == b'\\' {
1003 in_escape = true;
1004 i += 1;
1005 continue;
1006 }
1007 if ch == b'[' {
1008 in_character_class = true;
1009 i += 1;
1010 continue;
1011 }
1012 if ch == b']' {
1013 in_character_class = false;
1014 i += 1;
1015 continue;
1016 }
1017 if ch == b'/' && !in_character_class {
1018 break;
1019 }
1020 i += 1;
1021 }
1022 if i >= bytes.len() {
1023 return;
1024 }
1025
1026 let body = &token_text[1..i];
1027 let flags = if i + 1 < token_text.len() {
1028 &token_text[i + 1..]
1029 } else {
1030 ""
1031 };
1032 let has_unicode_flag = flags.as_bytes().iter().any(|&b| b == b'u' || b == b'v');
1033 if !has_unicode_flag {
1034 return;
1035 }
1036
1037 let body_start = self.token_pos() as usize + 1;
1038 let raw = body.as_bytes();
1039 let mut j = 0usize;
1040
1041 while j < raw.len() {
1042 if raw[j] != b'\\' {
1043 j += 1;
1044 continue;
1045 }
1046 if j + 1 >= raw.len() {
1047 break;
1048 }
1049 match raw[j + 1] {
1050 b'x' => {
1051 j = self.report_invalid_regular_expression_hex_escape(raw, body_start, j);
1052 }
1053 b'u' => {
1054 if let Some(next) =
1055 self.report_invalid_regular_expression_unicode_escape(raw, body_start, j)
1056 {
1057 j = next;
1058 } else {
1059 break;
1060 }
1061 }
1062 _ => {
1063 j += 1;
1064 }
1065 }
1066 }
1067 }
1068
1069 fn report_invalid_regular_expression_hex_escape(
1070 &mut self,
1071 raw: &[u8],
1072 body_start: usize,
1073 j: usize,
1074 ) -> usize {
1075 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
1076
1077 let first = j + 2;
1078 let second = j + 3;
1079 if first >= raw.len() || !Self::is_hex_digit(raw[first]) {
1080 self.parse_error_at(
1081 self.u32_from_usize(body_start + first),
1082 u32::from(first < raw.len()),
1083 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1084 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1085 );
1086 } else if second >= raw.len() || !Self::is_hex_digit(raw[second]) {
1087 self.parse_error_at(
1088 self.u32_from_usize(body_start + second),
1089 u32::from(second < raw.len()),
1090 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1091 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1092 );
1093 }
1094 j + 2
1095 }
1096
1097 fn report_invalid_regular_expression_unicode_escape(
1098 &mut self,
1099 raw: &[u8],
1100 body_start: usize,
1101 j: usize,
1102 ) -> Option<usize> {
1103 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
1104
1105 if j + 2 < raw.len() && raw[j + 2] == b'{' {
1106 let mut close = j + 3;
1107 let mut has_digit = false;
1108 while close < raw.len() && Self::is_hex_digit(raw[close]) {
1109 has_digit = true;
1110 close += 1;
1111 }
1112 if close >= raw.len() {
1113 self.parse_error_at(
1114 self.u32_from_usize(body_start + close),
1115 0,
1116 diagnostic_messages::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
1117 diagnostic_codes::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
1118 );
1119 return None;
1120 }
1121 if raw[close] == b'}' {
1122 if !has_digit {
1123 self.parse_error_at(
1124 self.u32_from_usize(body_start + close),
1125 1,
1126 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1127 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1128 );
1129 }
1130 } else if !has_digit {
1131 self.parse_error_at(
1132 self.u32_from_usize(body_start + j + 3),
1133 1,
1134 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1135 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1136 );
1137 } else {
1138 self.parse_error_at(
1139 self.u32_from_usize(body_start + close),
1140 1,
1141 diagnostic_messages::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
1142 diagnostic_codes::UNTERMINATED_UNICODE_ESCAPE_SEQUENCE,
1143 );
1144 self.parse_error_at(
1145 self.u32_from_usize(body_start + close),
1146 1,
1147 diagnostic_messages::UNEXPECTED_DID_YOU_MEAN_TO_ESCAPE_IT_WITH_BACKSLASH,
1148 diagnostic_codes::UNEXPECTED_DID_YOU_MEAN_TO_ESCAPE_IT_WITH_BACKSLASH,
1149 );
1150 }
1151 Some(close + 1)
1152 } else {
1153 let first = j + 2;
1154 let second = j + 3;
1155 let third = j + 4;
1156 let fourth = j + 5;
1157 if first >= raw.len() || !Self::is_hex_digit(raw[first]) {
1158 self.parse_error_at(
1159 self.u32_from_usize(body_start + first),
1160 u32::from(first < raw.len()),
1161 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1162 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1163 );
1164 } else if second >= raw.len() || !Self::is_hex_digit(raw[second]) {
1165 self.parse_error_at(
1166 self.u32_from_usize(body_start + second),
1167 u32::from(second < raw.len()),
1168 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1169 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1170 );
1171 } else if third >= raw.len() || !Self::is_hex_digit(raw[third]) {
1172 self.parse_error_at(
1173 self.u32_from_usize(body_start + third),
1174 u32::from(third < raw.len()),
1175 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1176 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1177 );
1178 } else if fourth >= raw.len() || !Self::is_hex_digit(raw[fourth]) {
1179 self.parse_error_at(
1180 self.u32_from_usize(body_start + fourth),
1181 u32::from(fourth < raw.len()),
1182 diagnostic_messages::HEXADECIMAL_DIGIT_EXPECTED,
1183 diagnostic_codes::HEXADECIMAL_DIGIT_EXPECTED,
1184 );
1185 }
1186 Some(j + 2)
1187 }
1188 }
1189
1190 pub(crate) fn error_expression_expected(&mut self) {
1196 if self.should_report_error() {
1200 use tsz_common::diagnostics::diagnostic_codes;
1201 self.parse_error_at_current_token(
1202 "Expression expected.",
1203 diagnostic_codes::EXPRESSION_EXPECTED,
1204 );
1205 }
1206 }
1207
1208 pub(crate) fn error_expression_or_comma_expected(&mut self) {
1211 if self.should_report_error() {
1212 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
1213 self.parse_error_at_current_token(
1214 diagnostic_messages::EXPRESSION_OR_COMMA_EXPECTED,
1215 diagnostic_codes::EXPRESSION_OR_COMMA_EXPECTED,
1216 );
1217 }
1218 }
1219
1220 pub(crate) fn error_argument_expression_expected(&mut self) {
1223 if self.should_report_error() {
1224 use tsz_common::diagnostics::diagnostic_codes;
1225 self.parse_error_at_current_token(
1226 "Argument expression expected.",
1227 diagnostic_codes::ARGUMENT_EXPRESSION_EXPECTED,
1228 );
1229 }
1230 }
1231
1232 pub(crate) fn error_type_expected(&mut self) {
1234 use tsz_common::diagnostics::diagnostic_codes;
1235 self.parse_error_at_current_token("Type expected", diagnostic_codes::TYPE_EXPECTED);
1236 }
1237
1238 pub(crate) fn error_identifier_expected(&mut self) {
1240 if self.is_token(SyntaxKind::Unknown) {
1244 if self.should_report_error() {
1245 use tsz_common::diagnostics::diagnostic_codes;
1246 self.parse_error_at_current_token(
1247 "Invalid character.",
1248 diagnostic_codes::INVALID_CHARACTER,
1249 );
1250 }
1251 return;
1252 }
1253 if self.should_report_error() {
1257 use tsz_common::diagnostics::diagnostic_codes;
1258 self.parse_error_at_current_token(
1259 "Identifier expected",
1260 diagnostic_codes::IDENTIFIER_EXPECTED,
1261 );
1262 }
1263 }
1264
1265 #[inline]
1268 pub(crate) const fn is_reserved_word(&self) -> bool {
1269 self.current_token as u16 >= SyntaxKind::FIRST_RESERVED_WORD as u16
1272 && self.current_token as u16 <= SyntaxKind::LAST_RESERVED_WORD as u16
1273 }
1274
1275 const fn current_keyword_text(&self) -> &'static str {
1277 match self.current_token {
1278 SyntaxKind::BreakKeyword => "break",
1279 SyntaxKind::CaseKeyword => "case",
1280 SyntaxKind::CatchKeyword => "catch",
1281 SyntaxKind::ClassKeyword => "class",
1282 SyntaxKind::ConstKeyword => "const",
1283 SyntaxKind::ContinueKeyword => "continue",
1284 SyntaxKind::DebuggerKeyword => "debugger",
1285 SyntaxKind::DefaultKeyword => "default",
1286 SyntaxKind::DeleteKeyword => "delete",
1287 SyntaxKind::DoKeyword => "do",
1288 SyntaxKind::ElseKeyword => "else",
1289 SyntaxKind::EnumKeyword => "enum",
1290 SyntaxKind::ExportKeyword => "export",
1291 SyntaxKind::ExtendsKeyword => "extends",
1292 SyntaxKind::FalseKeyword => "false",
1293 SyntaxKind::FinallyKeyword => "finally",
1294 SyntaxKind::ForKeyword => "for",
1295 SyntaxKind::FunctionKeyword => "function",
1296 SyntaxKind::IfKeyword => "if",
1297 SyntaxKind::ImportKeyword => "import",
1298 SyntaxKind::InKeyword => "in",
1299 SyntaxKind::InstanceOfKeyword => "instanceof",
1300 SyntaxKind::NewKeyword => "new",
1301 SyntaxKind::NullKeyword => "null",
1302 SyntaxKind::ReturnKeyword => "return",
1303 SyntaxKind::SuperKeyword => "super",
1304 SyntaxKind::SwitchKeyword => "switch",
1305 SyntaxKind::ThisKeyword => "this",
1306 SyntaxKind::ThrowKeyword => "throw",
1307 SyntaxKind::TrueKeyword => "true",
1308 SyntaxKind::TryKeyword => "try",
1309 SyntaxKind::TypeOfKeyword => "typeof",
1310 SyntaxKind::VarKeyword => "var",
1311 SyntaxKind::VoidKeyword => "void",
1312 SyntaxKind::WhileKeyword => "while",
1313 SyntaxKind::WithKeyword => "with",
1314 _ => "reserved word",
1315 }
1316 }
1317
1318 pub(crate) fn error_reserved_word_identifier(&mut self) {
1320 if self.should_report_error() {
1322 use tsz_common::diagnostics::diagnostic_codes;
1323 let word = self.current_keyword_text();
1324 if self.is_token(SyntaxKind::YieldKeyword) && self.in_generator_context() {
1325 self.parse_error_at_current_token(
1326 "Identifier expected. 'yield' is a reserved word in strict mode.",
1327 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_IN_STRICT_MODE,
1328 );
1329 self.next_token();
1331 return;
1332 }
1333 self.parse_error_at_current_token(
1334 &format!(
1335 "Identifier expected. '{word}' is a reserved word that cannot be used here."
1336 ),
1337 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_THAT_CANNOT_BE_USED_HERE,
1338 );
1339 self.next_token();
1341 }
1342 }
1343
1344 pub(crate) fn error_token_expected(&mut self, token: &str) {
1346 if self.is_token(SyntaxKind::Unknown) {
1352 if self.should_report_error() {
1353 use tsz_common::diagnostics::diagnostic_codes;
1354 self.parse_error_at_current_token(
1355 "Invalid character.",
1356 diagnostic_codes::INVALID_CHARACTER,
1357 );
1358 }
1359 return;
1360 }
1361 if self.should_report_error() {
1365 use tsz_common::diagnostics::diagnostic_codes;
1366 self.parse_error_at_current_token(
1367 &format!("'{token}' expected."),
1368 diagnostic_codes::EXPECTED,
1369 );
1370 }
1371 }
1372
1373 pub(crate) fn error_comma_expected(&mut self) {
1375 self.error_token_expected(",");
1376 }
1377
1378 pub(crate) fn is_parameter_start(&mut self) -> bool {
1380 self.is_parameter_modifier()
1382 || self.is_token(SyntaxKind::AtToken) || self.is_token(SyntaxKind::DotDotDotToken) || self.is_identifier_or_keyword()
1385 || self.is_token(SyntaxKind::OpenBraceToken) || self.is_token(SyntaxKind::OpenBracketToken) }
1388
1389 pub(crate) fn error_unterminated_template_literal_at(&mut self, start: u32, end: u32) {
1391 use tsz_common::diagnostics::diagnostic_codes;
1392 let length = end.saturating_sub(start).max(1);
1393 self.parse_error_at(
1394 start,
1395 length,
1396 "Unterminated template literal.",
1397 diagnostic_codes::UNTERMINATED_TEMPLATE_LITERAL,
1398 );
1399 }
1400
1401 pub(crate) fn error_declaration_expected(&mut self) {
1403 use tsz_common::diagnostics::diagnostic_codes;
1404 self.parse_error_at_current_token(
1405 "Declaration expected",
1406 diagnostic_codes::DECLARATION_EXPECTED,
1407 );
1408 }
1409
1410 pub(crate) fn error_statement_expected(&mut self) {
1412 use tsz_common::diagnostics::diagnostic_codes;
1413 self.parse_error_at_current_token(
1414 "Statement expected",
1415 diagnostic_codes::STATEMENT_EXPECTED,
1416 );
1417 }
1418
1419 pub(crate) fn check_using_outside_block(&mut self, statement: NodeIndex) {
1421 use crate::parser::node_flags;
1422 use tsz_common::diagnostics::{diagnostic_codes, diagnostic_messages};
1423
1424 if statement.is_none() {
1425 return;
1426 }
1427
1428 if let Some(node) = self.arena.get(statement) {
1430 if node.kind == syntax_kind_ext::VARIABLE_STATEMENT {
1432 let is_using = (node.flags
1434 & self.u16_from_node_flags(node_flags::USING | node_flags::AWAIT_USING))
1435 != 0;
1436 if is_using {
1437 self.parse_error_at(
1439 node.pos,
1440 node.end.saturating_sub(node.pos).max(1),
1441 diagnostic_messages::DECLARATIONS_CAN_ONLY_BE_DECLARED_INSIDE_A_BLOCK,
1442 diagnostic_codes::DECLARATIONS_CAN_ONLY_BE_DECLARED_INSIDE_A_BLOCK,
1443 );
1444 }
1445 }
1446 }
1447 }
1448
1449 pub(crate) fn error_unexpected_token(&mut self) {
1451 use tsz_common::diagnostics::diagnostic_codes;
1452 self.parse_error_at_current_token("Unexpected token", diagnostic_codes::UNEXPECTED_TOKEN);
1453 }
1454
1455 pub(crate) fn parse_semicolon(&mut self) {
1457 if self.is_token(SyntaxKind::SemicolonToken) {
1458 self.next_token();
1459 } else if self.is_token(SyntaxKind::Unknown) {
1460 } else if !self.can_parse_semicolon() {
1463 if self.should_report_error() {
1469 self.error_token_expected(";");
1470 }
1471 }
1472 }
1473
1474 pub(crate) fn parse_error_for_missing_semicolon_after(&mut self, expression: NodeIndex) {
1486 use crate::parser::spelling;
1487 use tsz_common::diagnostics::diagnostic_codes;
1488
1489 let Some((pos, len, expression_text)) =
1490 self.missing_semicolon_after_expression_text(expression)
1491 else {
1492 if self.should_report_error() {
1493 self.error_token_expected(";");
1494 }
1495 return;
1496 };
1497
1498 if self.parse_missing_semicolon_keyword_error(pos, len, &expression_text) {
1499 return;
1500 }
1501
1502 if self.should_suppress_type_or_keyword_suggestion_for_missing_semicolon(
1503 expression_text.as_str(),
1504 pos,
1505 ) {
1506 return;
1507 }
1508
1509 if let Some(suggestion) = spelling::suggest_keyword(&expression_text) {
1510 if !self.should_suppress_type_or_keyword_suggestion_for_missing_semicolon(
1511 suggestion.as_str(),
1512 pos,
1513 ) {
1514 self.parse_error_at(
1515 pos,
1516 len,
1517 &format!("Unknown keyword or identifier. Did you mean '{suggestion}'?"),
1518 diagnostic_codes::UNKNOWN_KEYWORD_OR_IDENTIFIER_DID_YOU_MEAN,
1519 );
1520 }
1521 return;
1522 }
1523
1524 if self.is_token(SyntaxKind::Unknown) {
1525 return;
1526 }
1527
1528 if self.should_report_error() {
1529 self.parse_error_at(
1530 pos,
1531 len,
1532 "Unexpected keyword or identifier.",
1533 diagnostic_codes::UNEXPECTED_KEYWORD_OR_IDENTIFIER,
1534 );
1535 }
1536 }
1537
1538 fn missing_semicolon_after_expression_text(
1539 &self,
1540 expression: NodeIndex,
1541 ) -> Option<(u32, u32, String)> {
1542 let node = self.arena.get(expression)?;
1543
1544 if node.kind != SyntaxKind::Identifier as u16 {
1545 return None;
1546 }
1547
1548 let source = self.scanner.source_text();
1551 let text = &source[node.pos as usize..node.end as usize];
1552 if text.is_empty() {
1553 return None;
1554 }
1555
1556 Some((node.pos, node.end - node.pos, text.to_string()))
1557 }
1558
1559 fn parse_missing_semicolon_keyword_error(
1560 &mut self,
1561 pos: u32,
1562 len: u32,
1563 expression_text: &str,
1564 ) -> bool {
1565 use tsz_common::diagnostics::diagnostic_codes;
1566
1567 match expression_text {
1568 "const" | "let" | "var" => {
1569 self.parse_error_at(
1570 pos,
1571 len,
1572 "Variable declaration not allowed at this location.",
1573 diagnostic_codes::VARIABLE_DECLARATION_NOT_ALLOWED_AT_THIS_LOCATION,
1574 );
1575 true
1576 }
1577 "declare" => true,
1578 "interface" => {
1579 if self.is_token(SyntaxKind::OpenBraceToken) {
1580 self.parse_error_at_current_token(
1581 "Interface must be given a name.",
1582 diagnostic_codes::INTERFACE_MUST_BE_GIVEN_A_NAME,
1583 );
1584 } else {
1585 let name = self.scanner.get_token_value_ref().to_string();
1586 self.parse_error_at_current_token(
1587 &format!("Interface name cannot be '{name}'."),
1588 diagnostic_codes::EXPECTED,
1589 );
1590 }
1591 true
1592 }
1593 "type" => {
1594 self.parse_error_at_current_token("'=' expected.", diagnostic_codes::EXPECTED);
1595 true
1596 }
1597 _ => false,
1598 }
1599 }
1600
1601 fn should_suppress_type_or_keyword_suggestion_for_missing_semicolon(
1602 &self,
1603 text: &str,
1604 token_pos: u32,
1605 ) -> bool {
1606 if !matches!(
1607 text,
1608 "string"
1609 | "number"
1610 | "boolean"
1611 | "symbol"
1612 | "bigint"
1613 | "object"
1614 | "void"
1615 | "undefined"
1616 | "null"
1617 | "never"
1618 | "unknown"
1619 | "any"
1620 ) {
1621 return false;
1622 }
1623
1624 let source = self.scanner.source_text().as_bytes();
1625 let mut i = token_pos as usize;
1626 while i > 0 && source[i - 1].is_ascii_whitespace() {
1627 i -= 1;
1628 }
1629 i > 0 && source[i - 1] == b':'
1630 }
1631
1632 pub(crate) fn can_parse_semicolon(&self) -> bool {
1645 if self.is_token(SyntaxKind::SemicolonToken) {
1647 return true;
1648 }
1649
1650 if self.is_token(SyntaxKind::CloseBraceToken) {
1652 return true;
1653 }
1654
1655 if self.is_token(SyntaxKind::EndOfFileToken) {
1657 return true;
1658 }
1659
1660 self.scanner.has_preceding_line_break()
1662 }
1663
1664 pub(crate) fn can_parse_semicolon_for_restricted_production(&self) -> bool {
1675 if self.is_token(SyntaxKind::SemicolonToken) {
1677 return true;
1678 }
1679
1680 if self.is_token(SyntaxKind::CloseBraceToken) {
1682 return true;
1683 }
1684
1685 if self.is_token(SyntaxKind::EndOfFileToken) {
1687 return true;
1688 }
1689
1690 if self.scanner.has_preceding_line_break() {
1693 return true;
1694 }
1695
1696 false
1697 }
1698
1699 pub(crate) const fn is_at_expression_end(&self) -> bool {
1711 match self.token() {
1712 SyntaxKind::SemicolonToken
1714 | SyntaxKind::CloseBraceToken
1715 | SyntaxKind::CloseParenToken
1716 | SyntaxKind::CloseBracketToken
1717 | SyntaxKind::EndOfFileToken => true,
1718 _ => false,
1723 }
1724 }
1725
1726 pub(crate) const fn is_statement_start(&self) -> bool {
1728 matches!(
1729 self.token(),
1730 SyntaxKind::VarKeyword
1731 | SyntaxKind::LetKeyword
1732 | SyntaxKind::ConstKeyword
1733 | SyntaxKind::FunctionKeyword
1734 | SyntaxKind::ClassKeyword
1735 | SyntaxKind::IfKeyword
1736 | SyntaxKind::ForKeyword
1737 | SyntaxKind::WhileKeyword
1738 | SyntaxKind::DoKeyword
1739 | SyntaxKind::SwitchKeyword
1740 | SyntaxKind::TryKeyword
1741 | SyntaxKind::CatchKeyword
1742 | SyntaxKind::FinallyKeyword
1743 | SyntaxKind::WithKeyword
1744 | SyntaxKind::DebuggerKeyword
1745 | SyntaxKind::ReturnKeyword
1746 | SyntaxKind::BreakKeyword
1747 | SyntaxKind::ContinueKeyword
1748 | SyntaxKind::ThrowKeyword
1749 | SyntaxKind::YieldKeyword
1750 | SyntaxKind::AsyncKeyword
1751 | SyntaxKind::UsingKeyword
1752 | SyntaxKind::AwaitKeyword
1753 | SyntaxKind::InterfaceKeyword
1754 | SyntaxKind::TypeKeyword
1755 | SyntaxKind::EnumKeyword
1756 | SyntaxKind::NamespaceKeyword
1757 | SyntaxKind::ModuleKeyword
1758 | SyntaxKind::ImportKeyword
1759 | SyntaxKind::ExportKeyword
1760 | SyntaxKind::DeclareKeyword
1761 | SyntaxKind::Identifier
1762 | SyntaxKind::StringLiteral
1763 | SyntaxKind::AtToken
1764 | SyntaxKind::NumericLiteral
1765 | SyntaxKind::BigIntLiteral
1766 | SyntaxKind::TrueKeyword
1767 | SyntaxKind::FalseKeyword
1768 | SyntaxKind::NullKeyword
1769 | SyntaxKind::ThisKeyword
1770 | SyntaxKind::SuperKeyword
1771 | SyntaxKind::ExclamationToken
1772 | SyntaxKind::TildeToken
1773 | SyntaxKind::PlusToken
1774 | SyntaxKind::MinusToken
1775 | SyntaxKind::PlusPlusToken
1776 | SyntaxKind::MinusMinusToken
1777 | SyntaxKind::TypeOfKeyword
1778 | SyntaxKind::VoidKeyword
1779 | SyntaxKind::DeleteKeyword
1780 | SyntaxKind::OpenBraceToken
1781 | SyntaxKind::SemicolonToken
1782 | SyntaxKind::OpenParenToken
1783 | SyntaxKind::OpenBracketToken
1784 | SyntaxKind::LessThanToken
1785 )
1786 }
1787
1788 pub(crate) const fn is_resync_sync_point(&self) -> bool {
1792 self.is_statement_start()
1793 || matches!(
1794 self.token(),
1795 SyntaxKind::ElseKeyword
1796 | SyntaxKind::CaseKeyword
1797 | SyntaxKind::DefaultKeyword
1798 | SyntaxKind::CatchKeyword
1799 | SyntaxKind::FinallyKeyword
1800 | SyntaxKind::CommaToken
1801 )
1802 }
1803
1804 pub(crate) fn resync_after_error_with_statement_starts(
1809 &mut self,
1810 allow_statement_starts: bool,
1811 ) {
1812 if self.is_resync_sync_point_with_statement_starts(allow_statement_starts) {
1814 return;
1815 }
1816
1817 let mut brace_depth = 0u32;
1819 let mut paren_depth = 0u32;
1820 let mut bracket_depth = 0u32;
1821 let max_iterations = 1000; for _ in 0..max_iterations {
1824 if self.is_token(SyntaxKind::EndOfFileToken) {
1826 break;
1827 }
1828
1829 match self.token() {
1831 SyntaxKind::OpenBraceToken => {
1832 brace_depth += 1;
1833 self.next_token();
1834 continue;
1835 }
1836 SyntaxKind::CloseBraceToken => {
1837 if brace_depth > 0 {
1838 brace_depth -= 1;
1839 self.next_token();
1840 continue;
1841 }
1842 self.next_token();
1844 break;
1845 }
1846 SyntaxKind::OpenParenToken => {
1847 paren_depth += 1;
1848 self.next_token();
1849 continue;
1850 }
1851 SyntaxKind::CloseParenToken => {
1852 if paren_depth > 0 {
1853 paren_depth -= 1;
1854 self.next_token();
1855 continue;
1856 }
1857 self.next_token();
1860 if self.is_resync_sync_point_with_statement_starts(allow_statement_starts) {
1861 break;
1862 }
1863 continue;
1864 }
1865 SyntaxKind::OpenBracketToken => {
1866 bracket_depth += 1;
1867 self.next_token();
1868 continue;
1869 }
1870 SyntaxKind::CloseBracketToken => {
1871 if bracket_depth > 0 {
1872 bracket_depth -= 1;
1873 self.next_token();
1874 continue;
1875 }
1876 self.next_token();
1878 continue;
1879 }
1880 SyntaxKind::SemicolonToken => {
1881 self.next_token();
1883 break;
1884 }
1885 _ => {}
1886 }
1887
1888 if brace_depth == 0
1890 && paren_depth == 0
1891 && bracket_depth == 0
1892 && self.is_resync_sync_point_with_statement_starts(allow_statement_starts)
1893 {
1894 break;
1895 }
1896
1897 self.next_token();
1899 }
1900 }
1901
1902 fn is_resync_sync_point_with_statement_starts(&self, allow_statement_starts: bool) -> bool {
1903 self.is_resync_sync_point()
1904 && (allow_statement_starts || self.token() != SyntaxKind::Identifier)
1905 }
1906
1907 pub(crate) fn resync_after_error(&mut self) {
1909 self.resync_after_error_with_statement_starts(true);
1910 }
1911
1912 pub(crate) const fn is_expression_start(&self) -> bool {
1918 matches!(
1919 self.token(),
1920 SyntaxKind::NumericLiteral
1921 | SyntaxKind::BigIntLiteral
1922 | SyntaxKind::StringLiteral
1923 | SyntaxKind::NoSubstitutionTemplateLiteral
1924 | SyntaxKind::TemplateHead
1925 | SyntaxKind::TemplateMiddle
1926 | SyntaxKind::TemplateTail
1927 | SyntaxKind::TrueKeyword
1928 | SyntaxKind::FalseKeyword
1929 | SyntaxKind::NullKeyword
1930 | SyntaxKind::Identifier
1931 | SyntaxKind::ThisKeyword
1932 | SyntaxKind::SuperKeyword
1933 | SyntaxKind::ImportKeyword
1934 | SyntaxKind::TypeKeyword
1935 | SyntaxKind::AnyKeyword
1936 | SyntaxKind::StringKeyword
1937 | SyntaxKind::NumberKeyword
1938 | SyntaxKind::BooleanKeyword
1939 | SyntaxKind::SymbolKeyword
1940 | SyntaxKind::BigIntKeyword
1941 | SyntaxKind::ObjectKeyword
1942 | SyntaxKind::NeverKeyword
1943 | SyntaxKind::UnknownKeyword
1944 | SyntaxKind::UndefinedKeyword
1945 | SyntaxKind::RequireKeyword
1946 | SyntaxKind::ModuleKeyword
1947 | SyntaxKind::NamespaceKeyword
1948 | SyntaxKind::AsyncKeyword
1949 | SyntaxKind::AwaitKeyword
1950 | SyntaxKind::YieldKeyword
1951 | SyntaxKind::LetKeyword
1952 | SyntaxKind::NewKeyword
1953 | SyntaxKind::ClassKeyword
1954 | SyntaxKind::FunctionKeyword
1955 | SyntaxKind::DeleteKeyword
1956 | SyntaxKind::VoidKeyword
1957 | SyntaxKind::TypeOfKeyword
1958 | SyntaxKind::InstanceOfKeyword
1959 | SyntaxKind::StaticKeyword
1960 | SyntaxKind::AbstractKeyword
1961 | SyntaxKind::OverrideKeyword
1962 | SyntaxKind::ReadonlyKeyword
1963 | SyntaxKind::AccessorKeyword
1964 | SyntaxKind::GetKeyword
1965 | SyntaxKind::SetKeyword
1966 | SyntaxKind::DeclareKeyword
1967 | SyntaxKind::PublicKeyword
1968 | SyntaxKind::ProtectedKeyword
1969 | SyntaxKind::PrivateKeyword
1970 | SyntaxKind::OfKeyword
1971 | SyntaxKind::SatisfiesKeyword
1972 | SyntaxKind::FromKeyword
1973 | SyntaxKind::AsKeyword
1974 | SyntaxKind::IsKeyword
1975 | SyntaxKind::AssertKeyword
1976 | SyntaxKind::AssertsKeyword
1977 | SyntaxKind::IntrinsicKeyword
1978 | SyntaxKind::OutKeyword
1979 | SyntaxKind::InferKeyword
1980 | SyntaxKind::ConstructorKeyword
1981 | SyntaxKind::UsingKeyword
1982 | SyntaxKind::KeyOfKeyword
1983 | SyntaxKind::UniqueKeyword
1984 | SyntaxKind::GlobalKeyword
1985 | SyntaxKind::InterfaceKeyword
1986 | SyntaxKind::EnumKeyword
1987 | SyntaxKind::DeferKeyword
1988 | SyntaxKind::PrivateIdentifier
1989 | SyntaxKind::PlusToken
1990 | SyntaxKind::MinusToken
1991 | SyntaxKind::AsteriskToken
1992 | SyntaxKind::TildeToken
1993 | SyntaxKind::ExclamationToken
1994 | SyntaxKind::PlusPlusToken
1995 | SyntaxKind::MinusMinusToken
1996 | SyntaxKind::OpenParenToken
1997 | SyntaxKind::OpenBracketToken
1998 | SyntaxKind::OpenBraceToken
1999 | SyntaxKind::LessThanToken
2000 | SyntaxKind::SlashToken
2001 | SyntaxKind::SlashEqualsToken
2002 | SyntaxKind::AtToken
2003 )
2004 }
2005
2006 pub(crate) const fn is_binary_operator(&self) -> bool {
2008 let precedence = self.get_operator_precedence(self.token());
2009 precedence > 0
2010 }
2011
2012 pub(crate) fn resync_to_next_expression_boundary(&mut self) {
2014 let max_iterations = 100;
2015 for _ in 0..max_iterations {
2016 if self.is_token(SyntaxKind::EndOfFileToken) {
2017 break;
2018 }
2019 if self.is_expression_boundary() {
2020 break;
2021 }
2022 if self.is_binary_operator() {
2023 break;
2024 }
2025 if self.is_expression_start() {
2026 break;
2027 }
2028 self.next_token();
2029 }
2030 }
2031
2032 pub(crate) const fn is_expression_boundary(&self) -> bool {
2034 matches!(
2035 self.token(),
2036 SyntaxKind::SemicolonToken
2037 | SyntaxKind::CloseBraceToken
2038 | SyntaxKind::CloseParenToken
2039 | SyntaxKind::CloseBracketToken
2040 | SyntaxKind::CommaToken
2041 | SyntaxKind::ColonToken
2042 | SyntaxKind::CaseKeyword
2043 | SyntaxKind::DefaultKeyword
2044 | SyntaxKind::ElseKeyword
2045 | SyntaxKind::WhileKeyword | SyntaxKind::AsKeyword
2047 | SyntaxKind::SatisfiesKeyword
2048 )
2049 }
2050
2051 pub(crate) fn create_missing_expression(&mut self) -> NodeIndex {
2054 let pos = self.token_pos();
2055 self.arena.add_identifier(
2057 SyntaxKind::Identifier as u16,
2058 pos,
2059 pos,
2060 IdentifierData {
2061 atom: Atom::NONE,
2062 escaped_text: String::new(),
2063 original_text: None,
2064 type_arguments: None,
2065 },
2066 )
2067 }
2068
2069 pub(crate) fn try_recover_binary_rhs(&mut self) -> NodeIndex {
2072 if self.is_expression_boundary() || self.is_statement_start() {
2074 self.create_missing_expression()
2075 } else {
2076 NodeIndex::NONE
2077 }
2078 }
2079
2080 pub(crate) fn try_rescan_greater_token(&mut self) -> SyntaxKind {
2083 if self.current_token == SyntaxKind::GreaterThanToken {
2084 self.current_token = self.scanner.re_scan_greater_token();
2085 }
2086 self.current_token
2087 }
2088
2089 pub(crate) fn parse_expected_greater_than(&mut self) {
2092 match self.current_token {
2093 SyntaxKind::GreaterThanToken => {
2094 self.next_token();
2096 }
2097 SyntaxKind::GreaterThanGreaterThanToken => {
2098 self.scanner.set_pos(self.scanner.get_pos() - 1);
2101 self.current_token = SyntaxKind::GreaterThanToken;
2102 }
2103 SyntaxKind::GreaterThanGreaterThanGreaterThanToken => {
2104 self.scanner.set_pos(self.scanner.get_pos() - 2);
2107 self.current_token = SyntaxKind::GreaterThanGreaterThanToken;
2108 }
2109 SyntaxKind::GreaterThanEqualsToken => {
2110 self.scanner.set_pos(self.scanner.get_pos() - 1);
2112 self.current_token = SyntaxKind::EqualsToken;
2113 }
2114 SyntaxKind::GreaterThanGreaterThanEqualsToken => {
2115 self.scanner.set_pos(self.scanner.get_pos() - 2);
2117 self.current_token = SyntaxKind::GreaterThanEqualsToken;
2118 }
2119 SyntaxKind::GreaterThanGreaterThanGreaterThanEqualsToken => {
2120 self.scanner.set_pos(self.scanner.get_pos() - 3);
2122 self.current_token = SyntaxKind::GreaterThanGreaterThanEqualsToken;
2123 }
2124 _ => {
2125 self.error_token_expected(">");
2127 }
2128 }
2129 }
2130
2131 pub(crate) const fn is_less_than_or_compound(&self) -> bool {
2134 matches!(
2135 self.current_token,
2136 SyntaxKind::LessThanToken
2137 | SyntaxKind::LessThanLessThanToken
2138 | SyntaxKind::LessThanLessThanEqualsToken
2139 )
2140 }
2141
2142 pub(crate) fn parse_expected_less_than(&mut self) {
2152 match self.current_token {
2153 SyntaxKind::LessThanToken => {
2154 self.next_token();
2155 }
2156 SyntaxKind::LessThanLessThanToken => {
2157 self.current_token = SyntaxKind::LessThanToken;
2161 }
2162 SyntaxKind::LessThanLessThanEqualsToken => {
2163 self.current_token = SyntaxKind::LessThanEqualsToken;
2166 }
2167 _ => {
2168 self.error_token_expected("<");
2169 }
2170 }
2171 }
2172
2173 pub(crate) const fn make_node_list(&self, nodes: Vec<NodeIndex>) -> NodeList {
2175 let _ = self;
2176 NodeList {
2177 nodes,
2178 pos: 0,
2179 end: 0,
2180 has_trailing_comma: false,
2181 }
2182 }
2183
2184 pub(crate) const fn get_operator_precedence(&self, token: SyntaxKind) -> u8 {
2186 match token {
2187 SyntaxKind::CommaToken => 1,
2188 SyntaxKind::EqualsToken
2189 | SyntaxKind::PlusEqualsToken
2190 | SyntaxKind::MinusEqualsToken
2191 | SyntaxKind::AsteriskEqualsToken
2192 | SyntaxKind::AsteriskAsteriskEqualsToken
2193 | SyntaxKind::SlashEqualsToken
2194 | SyntaxKind::PercentEqualsToken
2195 | SyntaxKind::LessThanLessThanEqualsToken
2196 | SyntaxKind::GreaterThanGreaterThanEqualsToken
2197 | SyntaxKind::GreaterThanGreaterThanGreaterThanEqualsToken
2198 | SyntaxKind::AmpersandEqualsToken
2199 | SyntaxKind::BarEqualsToken
2200 | SyntaxKind::BarBarEqualsToken
2201 | SyntaxKind::AmpersandAmpersandEqualsToken
2202 | SyntaxKind::QuestionQuestionEqualsToken
2203 | SyntaxKind::CaretEqualsToken => 2,
2204 SyntaxKind::QuestionToken => 3,
2205 SyntaxKind::BarBarToken | SyntaxKind::QuestionQuestionToken => 4,
2206 SyntaxKind::AmpersandAmpersandToken => 5,
2207 SyntaxKind::BarToken => 6,
2208 SyntaxKind::CaretToken => 7,
2209 SyntaxKind::AmpersandToken => 8,
2210 SyntaxKind::EqualsEqualsToken
2211 | SyntaxKind::ExclamationEqualsToken
2212 | SyntaxKind::EqualsEqualsEqualsToken
2213 | SyntaxKind::ExclamationEqualsEqualsToken => 9,
2214 SyntaxKind::InKeyword => {
2216 if self.in_disallow_in_context() {
2217 0
2218 } else {
2219 10
2220 }
2221 }
2222 SyntaxKind::LessThanToken
2223 | SyntaxKind::GreaterThanToken
2224 | SyntaxKind::LessThanEqualsToken
2225 | SyntaxKind::GreaterThanEqualsToken
2226 | SyntaxKind::InstanceOfKeyword
2227 | SyntaxKind::AsKeyword
2228 | SyntaxKind::SatisfiesKeyword => 10,
2229 SyntaxKind::LessThanLessThanToken
2230 | SyntaxKind::GreaterThanGreaterThanToken
2231 | SyntaxKind::GreaterThanGreaterThanGreaterThanToken => 11,
2232 SyntaxKind::PlusToken | SyntaxKind::MinusToken => 12,
2233 SyntaxKind::AsteriskToken | SyntaxKind::SlashToken | SyntaxKind::PercentToken => 13,
2234 SyntaxKind::AsteriskAsteriskToken => 14,
2235 _ => 0,
2236 }
2237 }
2238
2239 pub(crate) fn push_label_scope(&mut self) {
2241 let new_depth = self.label_scopes.len() + 1;
2242 trace!(pos = self.token_pos(), new_depth, "push_label_scope");
2243 self.label_scopes.push(FxHashMap::default());
2244 }
2245
2246 pub(crate) fn pop_label_scope(&mut self) {
2248 let old_depth = self.label_scopes.len();
2249 trace!(pos = self.token_pos(), old_depth, "pop_label_scope");
2250 self.label_scopes.pop();
2251 }
2252
2253 pub(crate) fn check_duplicate_label(&mut self, label_name: &str, label_pos: u32) -> bool {
2256 let scope_depth = self.label_scopes.len();
2257 trace!(label_name, label_pos, scope_depth, "check_duplicate_label");
2258 if let Some(current_scope) = self.label_scopes.last_mut() {
2259 if current_scope.contains_key(label_name) {
2260 use tsz_common::diagnostics::diagnostic_codes;
2262 let message = format!("Duplicate label '{label_name}'.");
2263 trace!(label_name, "duplicate label found");
2264 self.parse_error_at(
2265 label_pos,
2266 self.u32_from_usize(label_name.len()),
2267 &message,
2268 diagnostic_codes::DUPLICATE_LABEL,
2269 );
2270 return true;
2271 }
2272 trace!(label_name, "adding label to scope");
2274 current_scope.insert(label_name.to_string(), label_pos);
2275 }
2276 false
2277 }
2278}
2279
2280