Skip to content

Commit 69aef06

Browse files
committed
Support nested interpolation
1 parent aa96754 commit 69aef06

File tree

1 file changed

+31
-14
lines changed

1 file changed

+31
-14
lines changed

numbat/src/tokenizer.rs

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,12 @@ enum InterpolationState {
222222
/// We are not inside curly braces.
223223
Outside,
224224
/// We are currently scanning the inner part of an interpolation.
225-
Inside,
225+
Inside(u32),
226226
}
227227

228228
impl InterpolationState {
229229
fn is_inside(&self) -> bool {
230-
matches!(self, InterpolationState::Inside)
230+
matches!(self, InterpolationState::Inside(_))
231231
}
232232
}
233233

@@ -595,29 +595,41 @@ impl Tokenizer {
595595
if self.match_char(input, '"') {
596596
TokenKind::StringFixed
597597
} else if self.match_char(input, '{') {
598-
self.interpolation_state = InterpolationState::Inside;
598+
self.interpolation_state = InterpolationState::Inside(0);
599599
self.interpolation_start = self.last;
600600
TokenKind::StringInterpolationStart
601601
} else {
602602
return Err(TokenizerError {
603603
kind: TokenizerErrorKind::UnterminatedString,
604604
span: Span {
605-
start: self.token_start,
605+
start: self.string_start,
606606
end: self.current,
607607
code_source_id: self.code_source_id,
608608
},
609609
});
610610
}
611611
}
612-
InterpolationState::Inside => {
613-
return Err(TokenizerError {
614-
kind: TokenizerErrorKind::UnterminatedStringInterpolation,
615-
span: Span {
616-
start: self.interpolation_start,
617-
end: self.last,
618-
code_source_id: self.code_source_id,
619-
},
620-
});
612+
InterpolationState::Inside(i) => {
613+
self.string_start = self.token_start;
614+
615+
self.consume_string(input)?;
616+
617+
if self.match_char(input, '"') {
618+
TokenKind::StringFixed
619+
} else if self.match_char(input, '{') {
620+
self.interpolation_state = InterpolationState::Inside(i + 1);
621+
self.interpolation_start = self.last;
622+
TokenKind::StringInterpolationStart
623+
} else {
624+
return Err(TokenizerError {
625+
kind: TokenizerErrorKind::UnterminatedStringInterpolation,
626+
span: Span {
627+
start: self.interpolation_start,
628+
end: self.last,
629+
code_source_id: self.code_source_id,
630+
},
631+
});
632+
}
621633
}
622634
},
623635
':' if self.interpolation_state.is_inside() => {
@@ -656,7 +668,12 @@ impl Tokenizer {
656668
self.consume_string(input)?;
657669

658670
if self.match_char(input, '"') {
659-
self.interpolation_state = InterpolationState::Outside;
671+
match self.interpolation_state {
672+
InterpolationState::Inside(i) if i > 0 => {
673+
self.interpolation_state = InterpolationState::Inside(i - 1)
674+
}
675+
_ => self.interpolation_state = InterpolationState::Outside,
676+
}
660677
TokenKind::StringInterpolationEnd
661678
} else if self.match_char(input, '{') {
662679
self.interpolation_start = self.last;

0 commit comments

Comments
 (0)