solar_parse/lexer/unescape/
errors.rs1use solar_interface::{BytePos, Span, diagnostics::DiagCtxt};
2use std::ops::Range;
3
4#[derive(Debug, PartialEq, Eq)]
6pub enum EscapeError {
7 LoneSlash,
9 InvalidEscape,
11 BareCarriageReturn,
13 CannotSkipMultipleLines,
28
29 HexEscapeTooShort,
31 InvalidHexEscape,
33
34 UnicodeEscapeTooShort,
36 InvalidUnicodeEscape,
38
39 StrNewline,
41 StrNonAsciiChar,
43
44 HexNotHexDigit,
46 HexBadUnderscore,
48 HexOddDigits,
50 HexPrefix,
52}
53
54impl EscapeError {
55 fn msg(&self) -> &'static str {
56 match self {
57 Self::LoneSlash => "invalid trailing slash in literal",
58 Self::InvalidEscape => "unknown character escape",
59 Self::BareCarriageReturn => "bare CR not allowed in string, use `\\r` instead",
60 Self::CannotSkipMultipleLines => "cannot skip multiple lines with `\\`",
61 Self::HexEscapeTooShort => "hex escape must be followed by 2 hex digits",
62 Self::InvalidHexEscape => "invalid character in hex escape",
63 Self::UnicodeEscapeTooShort => "unicode escape must be followed by 4 hex digits",
64 Self::InvalidUnicodeEscape => "invalid character in unicode escape",
65 Self::StrNewline => "unescaped newline",
66 Self::StrNonAsciiChar => {
67 "unicode characters are not allowed in string literals; use a `unicode\"...\"` literal instead"
68 }
69 Self::HexNotHexDigit => "invalid hex digit",
70 Self::HexBadUnderscore => "invalid underscore in hex literal",
71 Self::HexOddDigits => "odd number of hex nibbles",
72 Self::HexPrefix => "hex prefix is not allowed",
73 }
74 }
75}
76
77pub(crate) fn emit_unescape_error(
78 dcx: &DiagCtxt,
79 lit: &str,
81 err_span: Span,
83 range: Range<usize>,
85 error: EscapeError,
86) {
87 let last_char = || {
88 let c = lit[range.clone()].chars().next_back().unwrap();
89 let span = err_span.with_lo(err_span.hi() - BytePos(c.len_utf8() as u32));
90 (c, span)
91 };
92 let mut diag = dcx.err(error.msg()).span(err_span);
93 if matches!(
94 error,
95 EscapeError::InvalidEscape
96 | EscapeError::InvalidHexEscape
97 | EscapeError::InvalidUnicodeEscape
98 ) {
99 diag = diag.span(last_char().1);
100 }
101 diag.emit();
102}