1use std::{fmt, ops::Range};
2
3
4#[derive(Debug, Clone, Copy)]
7pub struct InvalidToken {
8 pub(crate) expected: TokenKind,
9 pub(crate) actual: TokenKind,
10 pub(crate) span: Span,
11}
12
13impl InvalidToken {
14 pub fn to_compile_error(&self) -> proc_macro::TokenStream {
18 use proc_macro::{Delimiter, Ident, Group, Punct, Spacing, TokenTree};
19
20 let span = match self.span {
21 Span::One(s) => s,
22 #[cfg(feature = "proc-macro2")]
23 Span::Two(s) => s.unwrap(),
24 };
25 let msg = self.to_string();
26 let tokens = vec![
27 TokenTree::from(Ident::new("compile_error", span)),
28 TokenTree::from(Punct::new('!', Spacing::Alone)),
29 TokenTree::from(Group::new(
30 Delimiter::Parenthesis,
31 TokenTree::from(proc_macro::Literal::string(&msg)).into(),
32 )),
33 ];
34
35
36 tokens.into_iter().map(|mut t| { t.set_span(span); t }).collect()
37 }
38
39 #[cfg(feature = "proc-macro2")]
43 pub fn to_compile_error2(&self) -> proc_macro2::TokenStream {
44 use proc_macro2::{Delimiter, Ident, Group, Punct, Spacing, TokenTree};
45
46 let span = match self.span {
47 Span::One(s) => proc_macro2::Span::from(s),
48 Span::Two(s) => s,
49 };
50 let msg = self.to_string();
51 let tokens = vec![
52 TokenTree::from(Ident::new("compile_error", span)),
53 TokenTree::from(Punct::new('!', Spacing::Alone)),
54 TokenTree::from(Group::new(
55 Delimiter::Parenthesis,
56 TokenTree::from(proc_macro2::Literal::string(&msg)).into(),
57 )),
58 ];
59
60
61 tokens.into_iter().map(|mut t| { t.set_span(span); t }).collect()
62 }
63}
64
65impl std::error::Error for InvalidToken {}
66
67impl fmt::Display for InvalidToken {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 fn kind_desc(kind: TokenKind) -> &'static str {
70 match kind {
71 TokenKind::Punct => "a punctuation character",
72 TokenKind::Ident => "an identifier",
73 TokenKind::Group => "a group",
74 TokenKind::Literal => "a literal",
75 TokenKind::BoolLit => "a bool literal (`true` or `false`)",
76 TokenKind::ByteLit => "a byte literal (e.g. `b'r')",
77 TokenKind::ByteStringLit => r#"a byte string literal (e.g. `b"fox"`)"#,
78 TokenKind::CharLit => "a character literal (e.g. `'P'`)",
79 TokenKind::FloatLit => "a float literal (e.g. `3.14`)",
80 TokenKind::IntegerLit => "an integer literal (e.g. `27`)",
81 TokenKind::StringLit => r#"a string literal (e.g. "Ferris")"#,
82 }
83 }
84
85 write!(f, "expected {}, but found {}", kind_desc(self.expected), kind_desc(self.actual))
86 }
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90pub(crate) enum TokenKind {
91 Punct,
92 Ident,
93 Group,
94 Literal,
95 BoolLit,
96 ByteLit,
97 ByteStringLit,
98 CharLit,
99 FloatLit,
100 IntegerLit,
101 StringLit,
102}
103
104#[derive(Debug, Clone, Copy)]
106pub(crate) enum Span {
107 One(proc_macro::Span),
108 #[cfg(feature = "proc-macro2")]
109 Two(proc_macro2::Span),
110}
111
112impl From<proc_macro::Span> for Span {
113 fn from(src: proc_macro::Span) -> Self {
114 Self::One(src)
115 }
116}
117
118#[cfg(feature = "proc-macro2")]
119impl From<proc_macro2::Span> for Span {
120 fn from(src: proc_macro2::Span) -> Self {
121 Self::Two(src)
122 }
123}
124
125#[derive(Debug, Clone)]
154pub struct ParseError {
155 pub(crate) span: Option<Range<usize>>,
156 pub(crate) kind: ParseErrorKind,
157}
158
159impl ParseError {
160 pub fn span(&self) -> Option<Range<usize>> {
164 self.span.clone()
165 }
166}
167
168pub(crate) fn perr(span: impl SpanLike, kind: ParseErrorKind) -> ParseError {
172 ParseError {
173 span: span.into_span(),
174 kind,
175 }
176}
177
178pub(crate) trait SpanLike {
179 fn into_span(self) -> Option<Range<usize>>;
180}
181
182impl SpanLike for Option<Range<usize>> {
183 #[inline(always)]
184 fn into_span(self) -> Option<Range<usize>> {
185 self
186 }
187}
188impl SpanLike for Range<usize> {
189 #[inline(always)]
190 fn into_span(self) -> Option<Range<usize>> {
191 Some(self)
192 }
193}
194impl SpanLike for usize {
195 #[inline(always)]
196 fn into_span(self) -> Option<Range<usize>> {
197 Some(self..self + 1)
198 }
199}
200
201
202#[derive(Debug, Clone, Copy, PartialEq, Eq)]
204#[non_exhaustive]
205pub(crate) enum ParseErrorKind {
206 Empty,
208
209 UnexpectedChar,
211
212 InvalidLiteral,
214
215 DoesNotStartWithDigit,
217
218 InvalidDigit,
220
221 NoDigits,
223
224 NoExponentDigits,
226
227 UnknownEscape,
229
230 UnterminatedEscape,
233
234 InvalidXEscape,
236
237 NonAsciiXEscape,
239
240 UnicodeEscapeInByteLiteral,
242
243 InvalidStartOfUnicodeEscape,
245
246 UnicodeEscapeWithoutBrace,
248
249 NonHexDigitInUnicodeEscape,
252
253 TooManyDigitInUnicodeEscape,
255
256 InvalidUnicodeEscapeChar,
258
259 UnterminatedUnicodeEscape,
261
262 UnterminatedCharLiteral,
264
265 OverlongCharLiteral,
267
268 EmptyCharLiteral,
270
271 UnterminatedByteLiteral,
272 OverlongByteLiteral,
273 EmptyByteLiteral,
274 NonAsciiInByteLiteral,
275
276 UnescapedSingleQuote,
279
280 UnescapedSpecialWhitespace,
282
283 DoesNotStartWithQuote,
287
288 UnterminatedRawString,
290
291 UnterminatedString,
293
294 InvalidStringLiteralStart,
296
297 InvalidByteLiteralStart,
299
300 InvalidByteStringLiteralStart,
301
302 IsolatedCr,
305
306 InvalidSuffix,
308
309 UnexpectedIntegerLit,
312
313 IntegerSuffixStartingWithE,
316}
317
318impl std::error::Error for ParseError {}
319
320impl fmt::Display for ParseError {
321 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
322 use ParseErrorKind::*;
323
324 let description = match self.kind {
325 Empty => "input is empty",
326 UnexpectedChar => "unexpected character",
327 InvalidLiteral => "invalid literal",
328 DoesNotStartWithDigit => "number literal does not start with decimal digit",
329 InvalidDigit => "integer literal contains a digit invalid for its base",
330 NoDigits => "integer literal does not contain any digits",
331 NoExponentDigits => "exponent of floating point literal does not contain any digits",
332 UnknownEscape => "unknown escape",
333 UnterminatedEscape => "unterminated escape: input ended too soon",
334 InvalidXEscape => r"invalid `\x` escape: not followed by two hex digits",
335 NonAsciiXEscape => r"`\x` escape in char/string literal exceed ASCII range",
336 UnicodeEscapeInByteLiteral => r"`\u{...}` escape in byte (string) literal not allowed",
337 InvalidStartOfUnicodeEscape => r"invalid start of `\u{...}` escape",
338 UnicodeEscapeWithoutBrace => r"`Unicode \u{...}` escape without opening brace",
339 NonHexDigitInUnicodeEscape => r"non-hex digit found in `\u{...}` escape",
340 TooManyDigitInUnicodeEscape => r"more than six digits in `\u{...}` escape",
341 InvalidUnicodeEscapeChar => r"value specified in `\u{...}` escape is not a valid char",
342 UnterminatedUnicodeEscape => r"unterminated `\u{...}` escape",
343 UnterminatedCharLiteral => "character literal is not terminated",
344 OverlongCharLiteral => "character literal contains more than one character",
345 EmptyCharLiteral => "empty character literal",
346 UnterminatedByteLiteral => "byte literal is not terminated",
347 OverlongByteLiteral => "byte literal contains more than one byte",
348 EmptyByteLiteral => "empty byte literal",
349 NonAsciiInByteLiteral => "non ASCII character in byte (string) literal",
350 UnescapedSingleQuote => "character literal contains unescaped ' character",
351 UnescapedSpecialWhitespace => r"unescaped newline (\n), tab (\t) or cr (\r) character",
352 DoesNotStartWithQuote => "invalid start for char/byte/string literal",
353 UnterminatedRawString => "unterminated raw (byte) string literal",
354 UnterminatedString => "unterminated (byte) string literal",
355 InvalidStringLiteralStart => "invalid start for string literal",
356 InvalidByteLiteralStart => "invalid start for byte literal",
357 InvalidByteStringLiteralStart => "invalid start for byte string literal",
358 IsolatedCr => r"`\r` not immediately followed by `\n` in string",
359 InvalidSuffix => "literal suffix is not a valid identifier",
360 UnexpectedIntegerLit => "expected float literal, but found integer",
361 IntegerSuffixStartingWithE => "integer literal suffix must not start with 'e' or 'E'",
362 };
363
364 description.fmt(f)?;
365 if let Some(span) = &self.span {
366 write!(f, " (at {}..{})", span.start, span.end)?;
367 }
368
369 Ok(())
370 }
371}