scanner: fix interpolation with string args (#7214)

pull/7226/head
yuyi 2020-12-10 02:58:27 +08:00 committed by GitHub
parent cf755d40b7
commit 5fa1e403ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 6 deletions

View File

@ -26,6 +26,7 @@ pub mut:
is_inside_string bool is_inside_string bool
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_debug bool is_debug bool
line_comment string line_comment string
// prev_tok TokenKind // prev_tok TokenKind
@ -34,6 +35,7 @@ pub mut:
is_print_colored_error bool is_print_colored_error bool
is_print_rel_paths_on_error bool is_print_rel_paths_on_error bool
quote byte // which quote is used to denote current string: ' or " quote byte // which quote is used to denote current string: ' or "
inter_quote byte
line_ends []int // the positions of source lines ends (i.e. \n signs) line_ends []int // the positions of source lines ends (i.e. \n signs)
nr_lines int // total number of lines in the source file that were scanned nr_lines int // total number of lines in the source file that were scanned
is_vh bool // Keep newlines is_vh bool // Keep newlines
@ -716,12 +718,14 @@ fn (mut s Scanner) text_scan() token.Token {
`}` { `}` {
// s = `hello $name !` // s = `hello $name !`
// s = `hello ${name} !` // s = `hello ${name} !`
if s.is_inside_string { if s.is_enclosed_inter {
s.pos++ s.pos++
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
return s.new_token(.string, '', 1) return s.new_token(.string, '', 1)
} }
s.is_enclosed_inter = false
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
} else { } else {
@ -993,15 +997,23 @@ fn (mut s Scanner) ident_string() string {
is_quote := q == single_quote || q == double_quote is_quote := q == single_quote || q == double_quote
is_raw := is_quote && s.pos > 0 && s.text[s.pos - 1] == `r` is_raw := is_quote && s.pos > 0 && s.text[s.pos - 1] == `r`
is_cstr := is_quote && s.pos > 0 && s.text[s.pos - 1] == `c` is_cstr := is_quote && s.pos > 0 && s.text[s.pos - 1] == `c`
if is_quote && !s.is_inside_string { if is_quote {
if s.is_inside_string {
s.inter_quote = q
} else {
s.quote = q s.quote = q
} }
}
// if s.file_path.contains('string_test') { // if s.file_path.contains('string_test') {
// println('\nident_string() at char=${s.text[s.pos].str()}') // println('\nident_string() at char=${s.text[s.pos].str()}')
// println('linenr=$s.line_nr quote= $qquote ${qquote.str()}') // println('linenr=$s.line_nr quote= $qquote ${qquote.str()}')
// } // }
mut n_cr_chars := 0 mut n_cr_chars := 0
mut start := s.pos mut start := s.pos
if s.text[start] == s.quote ||
(s.text[start] == s.inter_quote && (s.is_inter_start || s.is_enclosed_inter)) {
start++
}
s.is_inside_string = false s.is_inside_string = false
slash := `\\` slash := `\\`
for { for {
@ -1016,6 +1028,9 @@ fn (mut s Scanner) ident_string() string {
// handle '123\\' slash at the end // handle '123\\' slash at the end
break break
} }
if c == s.inter_quote && (s.is_inter_start || s.is_enclosed_inter) {
break
}
if c == `\r` { if c == `\r` {
n_cr_chars++ n_cr_chars++
} }
@ -1054,6 +1069,7 @@ fn (mut s Scanner) ident_string() string {
// ${var} (ignore in vfmt mode) (skip \$) // ${var} (ignore in vfmt mode) (skip \$)
if prevc == `$` && c == `{` && !is_raw && s.count_symbol_before(s.pos - 2, slash) % 2 == 0 { if prevc == `$` && c == `{` && !is_raw && s.count_symbol_before(s.pos - 2, slash) % 2 == 0 {
s.is_inside_string = true s.is_inside_string = true
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
@ -1068,9 +1084,6 @@ fn (mut s Scanner) ident_string() string {
} }
} }
mut lit := '' mut lit := ''
if s.text[start] == s.quote {
start++
}
mut end := s.pos mut end := s.pos
if s.is_inside_string { if s.is_inside_string {
end++ end++

View File

@ -0,0 +1,9 @@
fn show_info(a string) string {
return a
}
fn test_interpolation_string_args() {
assert '${show_info("abc")}' == 'abc'
assert '${show_info("bac")}' == 'bac'
assert '${"aaa"}' == 'aaa'
}