scanner: fix new string interpolation - nested quotes (#16345)

This commit is contained in:
yuyi 2022-11-08 22:51:02 +08:00 committed by GitHub
parent bc30608e92
commit c7d0f0561e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 11 deletions

View file

@ -1326,9 +1326,15 @@ fn (mut s Scanner) ident_string() string {
fn (s Scanner) is_valid_interpolation(start_pos int) bool { fn (s Scanner) is_valid_interpolation(start_pos int) bool {
mut is_valid_inter := true mut is_valid_inter := true
mut has_rcbr := false mut has_rcbr := false
mut is_assign := true mut inside_par := false
for i := start_pos; i < s.text.len - 1; i++ { for i := start_pos; i < s.text.len - 1; i++ {
if s.text[i] == s.quote { if s.text[i] == `(` {
inside_par = true
}
if s.text[i] == `)` && inside_par {
inside_par = false
}
if s.text[i] == s.quote && !inside_par {
break break
} }
if s.text[i] == `}` { if s.text[i] == `}` {
@ -1337,12 +1343,12 @@ fn (s Scanner) is_valid_interpolation(start_pos int) bool {
} }
if s.text[i] == `=` && (s.text[i - 1] in [`!`, `>`, `<`] || s.text[i + 1] == `=`) { if s.text[i] == `=` && (s.text[i - 1] in [`!`, `>`, `<`] || s.text[i + 1] == `=`) {
// `!=` `>=` `<=` `==` // `!=` `>=` `<=` `==`
is_assign = false return true
} }
if (s.text[i] == `=` && is_assign) || (s.text[i] == `:` && s.text[i + 1].is_space()) { if s.text[i] == `=` || (s.text[i] == `:` && s.text[i + 1].is_space()) {
// We reached the end of the line or string without reaching "}". // We reached the end of the line or string without reaching "}".
// Also if there's "=", there's no way it's a valid interpolation expression: // Also if there's "=", there's no way it's a valid interpolation expression:
// e.g. `println("{a.b = 42}")` `println('{foo:bar}')` // e.g. `println("{a.b = 42}")` `println('{foo: bar}')`
is_valid_inter = false is_valid_inter = false
break break
} }

View file

@ -16,13 +16,11 @@ fn test_string_new_interpolation() {
println('{a}{{{{{b}}}}}') println('{a}{{{{{b}}}}}')
assert '{a}{{{{{b}}}}}' == '1{{{{2}}}}' assert '{a}{{{{{b}}}}}' == '1{{{{2}}}}'
// vfmt off
s := 'hello' s := 'hello'
println('{s == "hello"}') println('{s == 'hello'}')
assert '{s == "hello"}' == 'true' assert '{s == 'hello'}' == 'true'
println('{s != "hello"}') println('{s != 'hello'}')
assert '{s != "hello"}' == 'false' assert '{s != 'hello'}' == 'false'
// vfmt on
n := 22 n := 22
println('{n >= 10}') println('{n >= 10}')
@ -39,4 +37,21 @@ fn test_string_new_interpolation() {
println('{@FILE}') println('{@FILE}')
assert '{@FILE}'.contains('string_new_interpolation_test.v') assert '{@FILE}'.contains('string_new_interpolation_test.v')
ret := foo()
println(ret)
assert ret == r'[]T{aaa, bbb, ccc}'
}
fn foo() string {
match true {
true {
fields := ['aaa', 'bbb', 'ccc']
return '[]T{{fields.join(', ')}}'
}
else {
fields := ['aaa', 'bbb', 'ccc']
return 'const ({fields.join(' ')})'
}
}
} }