scanner: fix string interpolation with nested string interpolation in inner quotes 2 (#19094)

This commit is contained in:
yuyi 2023-08-09 20:05:17 +08:00 committed by GitHub
parent eef9b5f168
commit 3211a653c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 5 deletions

View File

@ -38,6 +38,7 @@ pub mut:
is_inter_start bool // for hacky string interpolation TODO simplify is_inter_start bool // for hacky string interpolation TODO simplify
is_inter_end bool is_inter_end bool
is_enclosed_inter bool is_enclosed_inter bool
is_nested_enclosed_inter bool
line_comment string line_comment string
last_lt int = -1 // position of latest < last_lt int = -1 // position of latest <
is_started bool is_started bool
@ -818,7 +819,7 @@ fn (mut s Scanner) text_scan() token.Token {
return s.new_token(.lcbr, '', 1) return s.new_token(.lcbr, '', 1)
} }
`$` { `$` {
if s.is_inside_string { if s.is_inside_string || s.is_enclosed_inter {
return s.new_token(.str_dollar, '', 1) return s.new_token(.str_dollar, '', 1)
} else { } else {
return s.new_token(.dollar, '', 1) return s.new_token(.dollar, '', 1)
@ -827,7 +828,7 @@ fn (mut s Scanner) text_scan() token.Token {
`}` { `}` {
// s = `hello $name !` // s = `hello $name !`
// s = `hello ${name} !` // s = `hello ${name} !`
if s.is_enclosed_inter && s.inter_cbr_count == 0 { if (s.is_enclosed_inter || s.is_nested_enclosed_inter) && s.inter_cbr_count == 0 {
if s.pos < s.text.len - 1 { if s.pos < s.text.len - 1 {
s.pos++ s.pos++
} else { } else {
@ -835,10 +836,18 @@ fn (mut s Scanner) text_scan() token.Token {
} }
if s.text[s.pos] == s.quote { if s.text[s.pos] == s.quote {
s.is_inside_string = false s.is_inside_string = false
s.is_enclosed_inter = false if s.is_nested_enclosed_inter {
s.is_nested_enclosed_inter = false
} else {
s.is_enclosed_inter = false
}
return s.new_token(.string, '', 1) return s.new_token(.string, '', 1)
} }
s.is_enclosed_inter = false if s.is_nested_enclosed_inter {
s.is_nested_enclosed_inter = false
} else {
s.is_enclosed_inter = false
}
s.just_closed_inter = true s.just_closed_inter = true
ident_string := s.ident_string() ident_string := s.ident_string()
return s.new_token(.string, ident_string, ident_string.len + 2) // + two quotes return s.new_token(.string, ident_string, ident_string.len + 2) // + two quotes
@ -1229,7 +1238,11 @@ fn (mut s Scanner) ident_string() string {
if prevc == `$` && c == `{` && !is_raw if prevc == `$` && c == `{` && !is_raw
&& s.count_symbol_before(s.pos - 2, scanner.backslash) % 2 == 0 { && s.count_symbol_before(s.pos - 2, scanner.backslash) % 2 == 0 {
s.is_inside_string = true s.is_inside_string = true
s.is_enclosed_inter = true if s.is_enclosed_inter {
s.is_nested_enclosed_inter = true
} else {
s.is_enclosed_inter = true
}
// so that s.pos points to $ at the next step // so that s.pos points to $ at the next step
s.pos -= 2 s.pos -= 2
break break

View File

@ -28,5 +28,11 @@ fn test_string_interp_with_inner_quotes() {
println("abc ${f(123, '$x $x')} xyz") println("abc ${f(123, '$x $x')} xyz")
assert "abc ${f(123, '$x $x')} xyz" == 'abc label hi hi: 123 xyz' assert "abc ${f(123, '$x $x')} xyz" == 'abc label hi hi: 123 xyz'
println("abc ${f(123, "${x} ${x}")} xyz")
assert "abc ${f(123, "${x} ${x}")} xyz" == 'abc label hi hi: 123 xyz'
println('abc ${f(123, '${x} ${x}')} xyz')
assert 'abc ${f(123, '${x} ${x}')} xyz' == 'abc label hi hi: 123 xyz'
} }
// vfmt on // vfmt on