midenc_hir/parser/
error.rs

1use super::lexer::{LexicalError, Token};
2use crate::{
3    diagnostics::{miette, ByteIndex, Diagnostic, SourceSpan},
4    DisplayValues,
5};
6
7#[derive(Debug, thiserror::Error, Diagnostic)]
8pub enum ParseError {
9    #[diagnostic(transparent)]
10    #[error(transparent)]
11    Lexer(#[from] LexicalError),
12    #[error("error reading {path:?}: {source}")]
13    #[diagnostic()]
14    FileError {
15        #[source]
16        source: std::io::Error,
17        path: std::path::PathBuf,
18    },
19    #[error("invalid token")]
20    #[diagnostic()]
21    InvalidToken(#[label] SourceSpan),
22    #[error("unexpected end of file")]
23    #[diagnostic()]
24    UnexpectedEof {
25        #[label("expected one of: {}", DisplayValues::new(expected.iter()))]
26        at: SourceSpan,
27        expected: Vec<String>,
28    },
29    #[error("unrecognized token '{token}'")]
30    UnrecognizedToken {
31        #[label("expected one of: {}", DisplayValues::new(expected.iter()))]
32        span: SourceSpan,
33        token: Token,
34        expected: Vec<String>,
35    },
36    #[error("extraneous token '{token}'")]
37    ExtraToken {
38        #[label]
39        span: SourceSpan,
40        token: Token,
41    },
42    #[error("expected valid u32 immediate value, got '{value}'")]
43    InvalidU32 {
44        #[label]
45        span: SourceSpan,
46        value: isize,
47    },
48    #[error("expected valid offset value, got '{value}'")]
49    InvalidOffset {
50        #[label]
51        span: SourceSpan,
52        value: isize,
53    },
54    #[error("expected valid alignment value, got '{value}'")]
55    InvalidAlignment {
56        #[label]
57        span: SourceSpan,
58        value: isize,
59    },
60    #[error("expected valid address space, got '{value}'")]
61    InvalidAddrSpace {
62        #[label]
63        span: SourceSpan,
64        value: isize,
65    },
66    #[error("invalid function definition: cannot have empty body")]
67    EmptyFunction {
68        #[label]
69        span: SourceSpan,
70    },
71    #[error("invalid function import declaration: cannot have body")]
72    ImportedFunctionWithBody {
73        #[label]
74        span: SourceSpan,
75    },
76}
77impl Eq for ParseError {}
78impl PartialEq for ParseError {
79    fn eq(&self, other: &Self) -> bool {
80        match (self, other) {
81            (Self::Lexer(l), Self::Lexer(r)) => l == r,
82            (Self::FileError { .. }, Self::FileError { .. }) => true,
83            (Self::InvalidToken(_), Self::InvalidToken(_)) => true,
84            (
85                Self::UnexpectedEof {
86                    expected: ref l, ..
87                },
88                Self::UnexpectedEof {
89                    expected: ref r, ..
90                },
91            ) => l == r,
92            (
93                Self::UnrecognizedToken {
94                    token: lt,
95                    expected: ref l,
96                    ..
97                },
98                Self::UnrecognizedToken {
99                    token: rt,
100                    expected: ref r,
101                    ..
102                },
103            ) => lt == rt && l == r,
104            (Self::ExtraToken { token: l, .. }, Self::ExtraToken { token: r, .. }) => l == r,
105            (Self::EmptyFunction { .. }, Self::EmptyFunction { .. }) => true,
106            (Self::ImportedFunctionWithBody { .. }, Self::ImportedFunctionWithBody { .. }) => true,
107            (Self::InvalidU32 { value: l, .. }, Self::InvalidU32 { value: r, .. }) => l == r,
108            (Self::InvalidOffset { value: l, .. }, Self::InvalidOffset { value: r, .. }) => l == r,
109            (Self::InvalidAlignment { value: l, .. }, Self::InvalidAlignment { value: r, .. }) => {
110                l == r
111            }
112            (Self::InvalidAddrSpace { value: l, .. }, Self::InvalidAddrSpace { value: r, .. }) => {
113                l == r
114            }
115            _ => false,
116        }
117    }
118}
119impl From<lalrpop_util::ParseError<ByteIndex, Token, ParseError>> for ParseError {
120    fn from(err: lalrpop_util::ParseError<ByteIndex, Token, ParseError>) -> Self {
121        use lalrpop_util::ParseError as LError;
122
123        match err {
124            LError::InvalidToken { location } => {
125                Self::InvalidToken(SourceSpan::at(Default::default(), location))
126            }
127            LError::UnrecognizedEof {
128                location: at,
129                expected,
130            } => Self::UnexpectedEof {
131                at: SourceSpan::at(Default::default(), at),
132                expected,
133            },
134            LError::UnrecognizedToken {
135                token: (l, token, r),
136                expected,
137            } => Self::UnrecognizedToken {
138                span: SourceSpan::new(Default::default(), l..r),
139                token,
140                expected,
141            },
142            LError::ExtraToken {
143                token: (l, token, r),
144            } => Self::ExtraToken {
145                span: SourceSpan::new(Default::default(), l..r),
146                token,
147            },
148            LError::User { error } => error,
149        }
150    }
151}