Skip to content

Commit 3211a65

Browse files
authored
scanner: fix string interpolation with nested string interpolation in inner quotes 2 (#19094)
1 parent eef9b5f commit 3211a65

2 files changed

Lines changed: 24 additions & 5 deletions

File tree

vlib/v/scanner/scanner.v

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub mut:
3838
is_inter_start bool // for hacky string interpolation TODO simplify
3939
is_inter_end bool
4040
is_enclosed_inter bool
41+
is_nested_enclosed_inter bool
4142
line_comment string
4243
last_lt int = -1 // position of latest <
4344
is_started bool
@@ -818,7 +819,7 @@ fn (mut s Scanner) text_scan() token.Token {
818819
return s.new_token(.lcbr, '', 1)
819820
}
820821
`$` {
821-
if s.is_inside_string {
822+
if s.is_inside_string || s.is_enclosed_inter {
822823
return s.new_token(.str_dollar, '', 1)
823824
} else {
824825
return s.new_token(.dollar, '', 1)
@@ -827,18 +828,26 @@ fn (mut s Scanner) text_scan() token.Token {
827828
`}` {
828829
// s = `hello $name !`
829830
// s = `hello ${name} !`
830-
if s.is_enclosed_inter && s.inter_cbr_count == 0 {
831+
if (s.is_enclosed_inter || s.is_nested_enclosed_inter) && s.inter_cbr_count == 0 {
831832
if s.pos < s.text.len - 1 {
832833
s.pos++
833834
} else {
834835
s.error('unfinished string literal')
835836
}
836837
if s.text[s.pos] == s.quote {
837838
s.is_inside_string = false
838-
s.is_enclosed_inter = false
839+
if s.is_nested_enclosed_inter {
840+
s.is_nested_enclosed_inter = false
841+
} else {
842+
s.is_enclosed_inter = false
843+
}
839844
return s.new_token(.string, '', 1)
840845
}
841-
s.is_enclosed_inter = false
846+
if s.is_nested_enclosed_inter {
847+
s.is_nested_enclosed_inter = false
848+
} else {
849+
s.is_enclosed_inter = false
850+
}
842851
s.just_closed_inter = true
843852
ident_string := s.ident_string()
844853
return s.new_token(.string, ident_string, ident_string.len + 2) // + two quotes
@@ -1229,7 +1238,11 @@ fn (mut s Scanner) ident_string() string {
12291238
if prevc == `$` && c == `{` && !is_raw
12301239
&& s.count_symbol_before(s.pos - 2, scanner.backslash) % 2 == 0 {
12311240
s.is_inside_string = true
1232-
s.is_enclosed_inter = true
1241+
if s.is_enclosed_inter {
1242+
s.is_nested_enclosed_inter = true
1243+
} else {
1244+
s.is_enclosed_inter = true
1245+
}
12331246
// so that s.pos points to $ at the next step
12341247
s.pos -= 2
12351248
break

vlib/v/tests/string_interpolation_with_inner_quotes_test.v

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,11 @@ fn test_string_interp_with_inner_quotes() {
2828

2929
println("abc ${f(123, '$x $x')} xyz")
3030
assert "abc ${f(123, '$x $x')} xyz" == 'abc label hi hi: 123 xyz'
31+
32+
println("abc ${f(123, "${x} ${x}")} xyz")
33+
assert "abc ${f(123, "${x} ${x}")} xyz" == 'abc label hi hi: 123 xyz'
34+
35+
println('abc ${f(123, '${x} ${x}')} xyz')
36+
assert 'abc ${f(123, '${x} ${x}')} xyz' == 'abc label hi hi: 123 xyz'
3137
}
3238
// vfmt on

0 commit comments

Comments
 (0)