@@ -55,7 +55,7 @@ pub mut:
5555 is_nested_string bool // '${'abc':-12s}'
5656 is_inter_start bool // for hacky string interpolation TODO simplify
5757 is_inter_end bool
58- str_helper_tokens []u8 // ', ", 0 (string interpolation with lcbr), { (block)
58+ str_helper_tokens []u8 = [] u8 {cap: 16 } // ', ", 0 (string interpolation with lcbr), { (block)
5959 line_comment string
6060 last_lt int = - 1 // position of latest <
6161 is_print_line_on_error bool
@@ -78,11 +78,11 @@ pub mut:
7878 should_abort bool // when too many errors/warnings/notices are accumulated, should_abort becomes true, and the scanner should stop
7979
8080 // the following are used only inside ident_string, but are here to avoid allocating new arrays for the most common case of strings without escapes
81- all_pos []int
82- u16_ escapes_pos []int // pos list of \uXXXX
83- u32_ escapes_pos []int // pos list of \UXXXXXXXX
84- h_escapes_pos []int // pos list of \xXX
85- str_segments []string
81+ all_pos []int = [] int {cap: 30 }
82+ u16_ escapes_pos []int = [] int {cap: 10 } // pos list of \uXXXX
83+ u32_ escapes_pos []int = [] int {cap: 10 } // pos list of \UXXXXXXXX
84+ h_escapes_pos []int = [] int {cap: 10 } // pos list of \xXX
85+ str_segments []string = [] string {cap: 10 }
8686}
8787
8888/*
@@ -154,7 +154,13 @@ const internally_generated_v_code = 'internally_generated_v_code'
154154
155155// new scanner from string.
156156pub fn new_scanner (text string , comments_mode CommentsMode, pref_ & pref.Preferences) & Scanner {
157- mut s := & Scanner{
157+ mut s := new_plain_scanner (text, comments_mode, pref_)
158+ s.scan_all_tokens_in_buffer ()
159+ return s
160+ }
161+
162+ fn new_plain_scanner (text string , comments_mode CommentsMode, pref_ & pref.Preferences) & Scanner {
163+ return & Scanner{
158164 pref: pref_
159165 text: text
160166 all_tokens: []token.Token{cap: text.len / 3 }
@@ -166,8 +172,6 @@ pub fn new_scanner(text string, comments_mode CommentsMode, pref_ &pref.Preferen
166172 file_path: internally_generated_v_code
167173 file_base: internally_generated_v_code
168174 }
169- s.scan_all_tokens_in_buffer ()
170- return s
171175}
172176
173177@[unsafe ]
@@ -832,11 +836,14 @@ pub fn (mut s Scanner) text_scan() token.Token {
832836 return s.new_token (.rsbr, '' , 1 )
833837 }
834838 `{` {
835- // Skip { in `${` in strings
836- if 255 != s.str_quote () {
837- s.str_helper_tokens << 0
838- } else {
839- s.str_helper_tokens << c
839+ // Keep interpolation helper state only while scanning string interpolation.
840+ if s.str_helper_tokens.len > 0 {
841+ // Skip { in `${` in strings
842+ if 255 != s.str_quote () {
843+ s.str_helper_tokens << 0
844+ } else {
845+ s.str_helper_tokens << c
846+ }
840847 }
841848 if s.is_inside_string && s.text[s.pos - 1 ] == `$` {
842849 continue
@@ -855,24 +862,23 @@ pub fn (mut s Scanner) text_scan() token.Token {
855862 // s = `hello ${name} !`
856863 if s.str_helper_tokens.len > 0 {
857864 s.str_helper_tokens.delete_last ()
858- }
859- quote := s.str_quote ()
860- if 255 != quote {
861- if s.pos < s.text.len - 1 {
862- s.pos++
863- } else {
864- s.error ('unfinished string literal' )
865- }
866- if s.text[s.pos] == quote {
867- s.is_inside_string = false
868- s.str_helper_tokens.delete_last ()
869- return s.new_token (.string, '' , 1 )
865+ quote := s.str_quote ()
866+ if 255 != quote {
867+ if s.pos < s.text.len - 1 {
868+ s.pos++
869+ } else {
870+ s.error ('unfinished string literal' )
871+ }
872+ if s.text[s.pos] == quote {
873+ s.is_inside_string = false
874+ s.str_helper_tokens.delete_last ()
875+ return s.new_token (.string, '' , 1 )
876+ }
877+ ident_string := s.ident_string ()
878+ return s.new_token (.string, ident_string, ident_string.len + 2 ) // + two quotes
870879 }
871- ident_string := s.ident_string ()
872- return s.new_token (.string, ident_string, ident_string.len + 2 ) // + two quotes
873- } else {
874- return s.new_token (.rcbr, '' , 1 )
875880 }
881+ return s.new_token (.rcbr, '' , 1 )
876882 }
877883 `&` {
878884 if nextc == `&` {
0 commit comments