Skip to content

Commit

Permalink
scanner: fix the new string interpolation - println('{s == 'hello'}') (
Browse files Browse the repository at this point in the history
…fix #16318) (#16319)

* scanner: fix the new string interpolation - println('{s == 'hello'}')

* fix vlib/v/eval/gen/infix_gen.v
  • Loading branch information
yuyi98 committed Nov 3, 2022
1 parent 0e8d148 commit fd40459
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 22 deletions.
2 changes: 1 addition & 1 deletion vlib/net/html/parser_test.v
Expand Up @@ -34,7 +34,7 @@ fn test_giant_string() {

fn test_script_tag() {
mut parser := Parser{}
script_content := "\nvar googletag = googletag || {};\ngoogletag.cmd = googletag.cmd || [];if(3 > 5) {console.log('Birl');}\n"
script_content := "\nvar googletag = googletag || {};\ngoogletag.cmd = googletag.cmd || [];if(3 > 5) { console.log('Birl');}\n"
temp_html := '<html><body><script>$script_content</script></body></html>'
parser.parse_html(temp_html)
assert parser.tags[2].content.len == script_content.replace('\n', '').len
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/eval/gen/infix_gen.v
Expand Up @@ -100,7 +100,7 @@ fn main() {
if op in ['<<', '>>'] && lt == 'f64' {
continue
}
b.write_string('$lt{match right{')
b.write_string('$lt{ match right{')
for ct2 in compound_types {
if op in ['<<', '>>'] && ct2 == 'Float' {
continue
Expand Down
44 changes: 24 additions & 20 deletions vlib/v/scanner/scanner.v
Expand Up @@ -109,7 +109,7 @@ pub enum CommentsMode {
// new scanner from file.
pub fn new_scanner_file(file_path string, comments_mode CommentsMode, pref &pref.Preferences) !&Scanner {
if !os.is_file(file_path) {
return error('$file_path is not a .v file')
return error('{file_path} is not a .v file')
}
raw_text := util.read_file(file_path) or { return err }
mut s := &Scanner{
Expand Down Expand Up @@ -287,7 +287,7 @@ fn (mut s Scanner) ident_bin_number() string {
s.error('number part of this binary is not provided')
} else if has_wrong_digit {
s.pos = first_wrong_digit_pos // adjust error position
s.error('this binary number has unsuitable digit `$first_wrong_digit.str()`')
s.error('this binary number has unsuitable digit `{first_wrong_digit.str()}`')
}
number := s.num_lit(start_pos, s.pos)
s.pos--
Expand Down Expand Up @@ -331,7 +331,7 @@ fn (mut s Scanner) ident_hex_number() string {
s.error('number part of this hexadecimal is not provided')
} else if has_wrong_digit {
s.pos = first_wrong_digit_pos // adjust error position
s.error('this hexadecimal number has unsuitable digit `$first_wrong_digit.str()`')
s.error('this hexadecimal number has unsuitable digit `{first_wrong_digit.str()}`')
}
number := s.num_lit(start_pos, s.pos)
s.pos--
Expand Down Expand Up @@ -371,7 +371,7 @@ fn (mut s Scanner) ident_oct_number() string {
s.error('number part of this octal is not provided')
} else if has_wrong_digit {
s.pos = first_wrong_digit_pos // adjust error position
s.error('this octal number has unsuitable digit `$first_wrong_digit.str()`')
s.error('this octal number has unsuitable digit `{first_wrong_digit.str()}`')
}
number := s.num_lit(start_pos, s.pos)
s.pos--
Expand Down Expand Up @@ -447,7 +447,7 @@ fn (mut s Scanner) ident_dec_number() string {
symbol_length++
}
float_symbol := s.text[s.pos - 2 - symbol_length..s.pos - 1]
s.warn('float literals should have a digit after the decimal point, e.g. `${float_symbol}.0`')
s.warn('float literals should have a digit after the decimal point, e.g. `{float_symbol}.0`')
}
}
}
Expand Down Expand Up @@ -481,7 +481,7 @@ fn (mut s Scanner) ident_dec_number() string {
// error check: wrong digit
s.pos = first_wrong_digit_pos // adjust error position
if !s.pref.translated {
s.error('this number has unsuitable digit `$first_wrong_digit.str()`')
s.error('this number has unsuitable digit `{first_wrong_digit.str()}`')
}
} else if s.text[s.pos - 1] in [`e`, `E`] {
// error check: 5e
Expand Down Expand Up @@ -544,7 +544,7 @@ fn (mut s Scanner) end_of_file() token.Token {
if s.eofs > 50 {
s.line_nr--
panic(
'the end of file `$s.file_path` has been reached 50 times already, the v parser is probably stuck.\n' +
'the end of file `{s.file_path}` has been reached 50 times already, the v parser is probably stuck.\n' +
'This should not happen. Please report the bug here, and include the last 2-3 lines of your source code:\n' +
'https://github.com/vlang/v/issues/new?labels=Bug&template=bug_report.md')
}
Expand All @@ -567,7 +567,7 @@ fn (mut s Scanner) scan_all_tokens_in_buffer() {
s.tidx = 0
$if debugscanner ? {
for t in s.all_tokens {
eprintln('> tidx:${t.tidx:-5} | kind: ${t.kind:-10} | lit: $t.lit')
eprintln('> tidx:{t.tidx:-5} | kind: {t.kind:-10} | lit: {t.lit}')
}
}
}
Expand Down Expand Up @@ -685,7 +685,7 @@ fn (mut s Scanner) text_scan() token.Token {
// allow `'$a.b'` and `'$a.c()'`
if s.is_inter_start && next_char == `\\`
&& s.look_ahead(2) !in [`x`, `n`, `r`, `\\`, `t`, `e`, `"`, `'`] {
s.warn('unknown escape sequence \\${s.look_ahead(2)}')
s.warn('unknown escape sequence \\{s.look_ahead(2)}')
}
if s.is_inter_start && next_char == `(` {
if s.look_ahead(2) != `)` {
Expand Down Expand Up @@ -901,7 +901,7 @@ fn (mut s Scanner) text_scan() token.Token {
mut at_error_msg := '@ must be used before keywords or compile time variables (e.g. `@type string` or `@FN`)'
// If name is all uppercase, the user is probably looking for a compile time variable ("at-token")
if name.is_upper() {
at_error_msg += '\nAvailable compile time variables:\n$token.valid_at_tokens'
at_error_msg += '\nAvailable compile time variables:\n{token.valid_at_tokens}'
}
s.error(at_error_msg)
}
Expand Down Expand Up @@ -1125,7 +1125,7 @@ fn (mut s Scanner) invalid_character() {
len := utf8_char_len(s.text[s.pos])
end := mathutil.min(s.pos + len, s.text.len)
c := s.text[s.pos..end]
s.error('invalid character `$c`')
s.error('invalid character `{c}`')
}

fn (s &Scanner) current_column() int {
Expand Down Expand Up @@ -1249,11 +1249,13 @@ fn (mut s Scanner) ident_string() string {
// e.g. "{init: " (no "}" at the end)
mut is_valid_inter := true
for i := s.pos + 1; i < s.text.len; i++ {
if s.text[i] == `}` {
if s.text[i] == `}` || (s.text[i] == `=` && (s.text[i - 1] in [`!`, `>`, `<`]
|| s.text[i + 1] == `=`)) {
// No } in this string, so it's not a valid `{x}` interpolation
// `!=` `>=` `<=` `==`
break
}
if s.text[i] in [`=`, `:`, `\n`, s.inter_quote] {
if s.text[i] in [`=`, `:`] {
// 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:
// e.g. `println("{a.b = 42}")` `println('{foo:bar}')`
Expand All @@ -1276,11 +1278,13 @@ fn (mut s Scanner) ident_string() string {
// e.g. "{init: " (no "}" at the end)
mut is_valid_inter := true
for i := s.pos; i < s.text.len; i++ {
if s.text[i] == `}` {
if s.text[i] == `}` || (s.text[i] == `=` && (s.text[i - 1] in [`!`, `>`, `<`]
|| s.text[i + 1] == `=`)) {
// No } in this string, so it's not a valid `{x}` interpolation
// `!=` `>=` `<=` `==`
break
}
if s.text[i] in [`=`, `:`, `\n`, s.inter_quote] {
if s.text[i] in [`=`, `:`] {
// 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:
// e.g. `println("{a.b = 42}")` `println('{foo:bar}')`
Expand Down Expand Up @@ -1405,7 +1409,7 @@ fn (mut s Scanner) decode_u_escape_single(str string, idx int) (int, string) {
escaped_code_point := strconv.parse_uint(str[idx + 2..end_idx], 16, 32) or { 0 }
// Check if Escaped Code Point is invalid or not
if rune(escaped_code_point).length_in_bytes() == -1 {
s.error('invalid unicode point `$str`')
s.error('invalid unicode point `{str}`')
}

return end_idx, utf32_to_str(u32(escaped_code_point))
Expand Down Expand Up @@ -1526,15 +1530,15 @@ fn (mut s Scanner) ident_char() string {
u := c.runes()
if u.len != 1 {
if escaped_hex || escaped_unicode {
s.error('invalid character literal `$orig` => `$c` ($u) (escape sequence did not refer to a singular rune)')
s.error('invalid character literal `{orig}` => `{c}` ({u}) (escape sequence did not refer to a singular rune)')
} else if u.len == 0 {
s.add_error_detail_with_pos('use quotes for strings, backticks for characters',
lspos)
s.error('invalid empty character literal `$orig`')
s.error('invalid empty character literal `{orig}`')
} else {
s.add_error_detail_with_pos('use quotes for strings, backticks for characters',
lspos)
s.error('invalid character literal `$orig` => `$c` ($u) (more than one character)')
s.error('invalid character literal `{orig}` => `{c}` ({u}) (more than one character)')
}
}
}
Expand Down Expand Up @@ -1708,6 +1712,6 @@ fn (mut s Scanner) vet_error(msg string, fix vet.FixKind) {

fn (mut s Scanner) trace(fbase string, message string) {
if s.file_base == fbase {
println('> s.trace | ${fbase:-10s} | $message')
println('> s.trace | {fbase:-10s} | {message}')
}
}
12 changes: 12 additions & 0 deletions vlib/v/tests/string_new_interpolation_test.v
Expand Up @@ -15,4 +15,16 @@ fn test_string_new_interpolation() {

println('{a}{{{{{b}}}}}')
assert '{a}{{{{{b}}}}}' == '1{{{{2}}}}'

s := 'hello'
println('{s == 'hello'}')
assert '{s == 'hello'}' == 'true'
println('{s != 'hello'}')
assert '{s != 'hello'}' == 'false'

n := 22
println('{n >= 10}')
assert '{n >= 10}' == 'true'
println('{n <= 10}')
assert '{n <= 10}' == 'false'
}

0 comments on commit fd40459

Please sign in to comment.