1use std::{
2 error,
3 fmt::{self, Display},
4};
5
6use crate::{source::Location, token::Token};
7
8#[derive(Debug, Clone, PartialEq)]
9pub struct Error {
10 pub location: Location,
11 pub kind: ErrorKind,
12}
13
14impl Error {
15 pub fn new(kind: ErrorKind, location: Location) -> Error {
16 Error { kind, location }
17 }
18}
19
20#[derive(Debug, Clone, PartialEq)]
21pub enum ErrorKind {
22 UnexpectedCharacter(char),
23 UnmatchedDedent,
24 MixedTabsAndSpaces,
25 NonAsciiBytes { offset: usize },
26 UnicodeDecode { offset: usize },
27 UnterminatedString,
28 UnexpectedToken { token: Token, expected: Vec<String> },
29 UnexpectedEof,
30}
31
32impl error::Error for Error {
33 fn description(&self) -> &str {
34 match self.kind {
35 ErrorKind::UnexpectedCharacter(_) => "unexpected character",
36 ErrorKind::UnmatchedDedent => "unmatched indentation",
37 ErrorKind::MixedTabsAndSpaces => "inconsistent use of tabs and spaces",
38 ErrorKind::NonAsciiBytes { .. } => "bytes can only contains ASCII characters",
39 ErrorKind::UnicodeDecode { .. } => "malformed unicode escape",
40 ErrorKind::UnterminatedString => "unterminated string",
41 ErrorKind::UnexpectedToken { .. } => "unexpected token, expected one of: ",
42 ErrorKind::UnexpectedEof => "unexpected EOF",
43 }
44 }
45}
46
47impl Display for Error {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 write!(f, "{}", self.kind)
50 }
51}
52
53impl Display for ErrorKind {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 match self {
56 ErrorKind::UnexpectedCharacter(c) => write!(f, "unexpected character \"{}\"", c),
57 ErrorKind::UnmatchedDedent => write!(f, "unmatched indentation"),
58 ErrorKind::MixedTabsAndSpaces => write!(f, "inconsistent use of tabs and spaces"),
59 ErrorKind::NonAsciiBytes { .. } => {
60 write!(f, "bytes can only contains ASCII characters")
61 }
62 ErrorKind::UnicodeDecode { .. } => write!(f, "malformed unicode escape"),
63 ErrorKind::UnterminatedString => write!(f, "unterminated string"),
64 ErrorKind::UnexpectedToken { token, expected } => {
65 write!(f, "unexpected {}, expected one of: ", token,)?;
66 let mut it = expected.iter();
67 write!(f, "{}", it.next().unwrap())?;
68 for e in it {
69 write!(f, ", {}", e)?;
70 }
71 Ok(())
72 }
73 ErrorKind::UnexpectedEof => write!(f, "unexpected EOF"),
74 }
75 }
76}
77
78impl From<lalrpop_util::ParseError<Location, Token, Error>> for Error {
79 fn from(e: lalrpop_util::ParseError<Location, Token, Error>) -> Error {
80 use lalrpop_util::ParseError::*;
81 match e {
82 e @ InvalidToken { .. } => {
83 unreachable!("{:?}", e)
87 }
88 e @ UnrecognizedEOF { .. } => {
89 unreachable!("{:?}", e)
92 }
93 UnrecognizedToken {
94 token: (start, Token::Eof, _),
95 ..
96 } => Error::new(ErrorKind::UnexpectedEof, start),
97 UnrecognizedToken {
98 token: (start, token, _),
99 expected,
100 } => Error::new(ErrorKind::UnexpectedToken { token, expected }, start),
101 e @ ExtraToken { .. } => {
102 unreachable!("{:?}", e)
105 }
106 User { error } => error,
107 }
108 }
109}