scanner: fix string interpolation in raw strings

pull/2633/head
Alexander Medvednikov 2019-11-03 23:57:26 +03:00
parent 3449a8bc4d
commit 4e64a58ac1
3 changed files with 13 additions and 6 deletions

View File

@ -498,3 +498,10 @@ fn test_atoi() {
} }
} }
fn test_raw_inter() {
world := 'world'
s := r'hello\n$world'
assert s == r'hello\n$world'
assert s.contains('$')
}

View File

@ -2733,7 +2733,7 @@ fn (p mut Parser) string_expr() {
// `C.puts('hi')` => `puts("hi");` // `C.puts('hi')` => `puts("hi");`
/* /*
Calling a C function sometimes requires a call to a string method Calling a C function sometimes requires a call to a string method
C.fun('ssss'.to_wide()) => fun(string_to_wide(tos2((byte*)('ssss')))) C.fun('ssss'.to_wide()) => fun(string_to_wide(tos3("ssss")))
*/ */
if (p.calling_c && p.peek() != .dot) || (p.pref.translated && p.mod == 'main') { if (p.calling_c && p.peek() != .dot) || (p.pref.translated && p.mod == 'main') {
p.gen('"$f"') p.gen('"$f"')

View File

@ -650,11 +650,11 @@ fn (s Scanner) count_symbol_before(p int, sym byte) int {
return count return count
} }
// println('array out of bounds $idx len=$a.len')
// This is really bad. It needs a major clean up
fn (s mut Scanner) ident_string() string { fn (s mut Scanner) ident_string() string {
q := s.text[s.pos] q := s.text[s.pos]
if (q == single_quote || q == double_quote) && !s.inside_string{ is_quote := q == single_quote || q == double_quote
is_raw := is_quote && s.text[s.pos-1] == `r`
if is_quote && !s.inside_string {
s.quote = q s.quote = q
} }
//if s.file_path.contains('string_test') { //if s.file_path.contains('string_test') {
@ -688,14 +688,14 @@ fn (s mut Scanner) ident_string() string {
s.error('0 character in a string literal') s.error('0 character in a string literal')
} }
// ${var} // ${var}
if c == `{` && prevc == `$` && s.count_symbol_before(s.pos-2, slash) % 2 == 0 { if c == `{` && prevc == `$` && !is_raw && s.count_symbol_before(s.pos-2, slash) % 2 == 0 {
s.inside_string = true s.inside_string = 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
} }
// $var // $var
if (c.is_letter() || c == `_`) && prevc == `$` && s.count_symbol_before(s.pos-2, slash) % 2 == 0 { if (c.is_letter() || c == `_`) && prevc == `$` && !is_raw && s.count_symbol_before(s.pos-2, slash) % 2 == 0 {
s.inside_string = true s.inside_string = true
s.inter_start = true s.inter_start = true
s.pos -= 2 s.pos -= 2