diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index 2fb7cc773f9572..a9c19384aeaf3c 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -1262,8 +1262,7 @@ fn (mut s Scanner) ident_string() string { u_escapes_pos << s.pos - 1 } // Unknown escape sequence - if c !in [`x`, `u`, `e`, `n`, `r`, `t`, `v`, `a`, `f`, `b`, `\\`, `\``, `$`, `@`, `?`, `{`, `}`, `'`, `"`] - && !c.is_digit() { + if !is_escape_sequence(c) && !c.is_digit() { s.error('`${c.ascii_str()}` unknown escape sequence') } } @@ -1448,6 +1447,12 @@ fn trim_slash_line_break(s string) string { return ret_str } +[inline] +fn is_escape_sequence(c u8) bool { + return c in [`x`, `u`, `e`, `n`, `r`, `t`, `v`, `a`, `f`, `b`, `\\`, `\``, `$`, `@`, `?`, `{`, + `}`, `'`, `"`] +} + /// ident_char is called when a backtick "single-char" is parsed from the code /// it is needed because some runes (chars) are written with escape sequences /// the string it returns should be a standardized, simplified version of the character @@ -1541,10 +1546,15 @@ fn (mut s Scanner) ident_char() string { lspos) } } - } else if c == '\n' { + } else if c.ends_with('\n') { s.add_error_detail_with_pos('use quotes for strings, backticks for characters', lspos) s.error_with_pos('invalid character literal, use \`\\n\` instead', lspos) + } else if c.len > len { + ch := c[c.len - 1] + if !is_escape_sequence(ch) && !ch.is_digit() { + s.error('`${ch.ascii_str()}` unknown escape sequence') + } } // Escapes a `'` character if c == "'" { diff --git a/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_1_err.out b/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_1_err.out new file mode 100644 index 00000000000000..d93d7b286bcfa3 --- /dev/null +++ b/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_1_err.out @@ -0,0 +1,13 @@ +vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_1_err.vv:2:6: error: invalid character literal, use `\n` instead + 1 | fn main() { + 2 | _ = `\ + | ^ + 3 | ` + 4 | } +Details: +vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_1_err.vv:2:6: details: use quotes for strings, backticks for characters + 1 | fn main() { + 2 | _ = `\ + | ^ + 3 | ` + 4 | } diff --git a/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_1_err.vv b/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_1_err.vv new file mode 100644 index 00000000000000..316e6be868ecb8 --- /dev/null +++ b/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_1_err.vv @@ -0,0 +1,4 @@ +fn main() { + _ = `\ +` +} diff --git a/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_2_err.out b/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_2_err.out new file mode 100644 index 00000000000000..cc33e4c40c6e6f --- /dev/null +++ b/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_2_err.out @@ -0,0 +1,5 @@ +vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_2_err.vv:2:9: error: `j` unknown escape sequence + 1 | fn main() { + 2 | _ = `\j` + | ^ + 3 | } diff --git a/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_2_err.vv b/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_2_err.vv new file mode 100644 index 00000000000000..3ca44160504c16 --- /dev/null +++ b/vlib/v/scanner/tests/unknown_escape_sequence_in_ident_char_2_err.vv @@ -0,0 +1,3 @@ +fn main() { + _ = `\j` +}