1use alloc::boxed::Box;
2use alloc::string::{String, ToString};
3use core::fmt;
4
5use crate::{SourceMap, Span, ast::lex};
6
7pub type ParseResult<T, E = ParseError> = Result<T, E>;
8
9#[non_exhaustive]
10#[derive(Debug, PartialEq, Eq)]
11pub enum ParseErrorKind {
12 Lex(lex::Error),
14 Syntax { span: Span, message: String },
17 ItemNotFound {
20 span: Span,
21 name: String,
22 kind: String,
23 hint: Option<String>,
24 },
25 TypeCycle {
27 span: Span,
28 name: String,
29 kind: String,
30 },
31}
32
33impl ParseErrorKind {
34 pub fn span(&self) -> Span {
35 match self {
36 ParseErrorKind::Lex(e) => Span::new(e.position(), e.position() + 1),
37 ParseErrorKind::Syntax { span, .. }
38 | ParseErrorKind::ItemNotFound { span, .. }
39 | ParseErrorKind::TypeCycle { span, .. } => *span,
40 }
41 }
42}
43
44impl fmt::Display for ParseErrorKind {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 match self {
47 ParseErrorKind::Lex(e) => fmt::Display::fmt(e, f),
48 ParseErrorKind::Syntax { message, .. } => message.fmt(f),
49 ParseErrorKind::ItemNotFound {
50 kind, name, hint, ..
51 } => {
52 write!(f, "{kind} `{name}` does not exist")?;
53 if let Some(hint) = hint {
54 write!(f, "\n{hint}")?;
55 }
56 Ok(())
57 }
58 ParseErrorKind::TypeCycle { kind, name, .. } => {
59 write!(f, "{kind} `{name}` depends on itself")
60 }
61 }
62 }
63}
64
65#[derive(Debug, PartialEq, Eq)]
66pub struct ParseError(Box<ParseErrorKind>);
67
68impl ParseError {
69 pub fn new_syntax(span: Span, message: impl Into<String>) -> Self {
70 ParseErrorKind::Syntax {
71 span,
72 message: message.into(),
73 }
74 .into()
75 }
76
77 pub fn kind(&self) -> &ParseErrorKind {
78 &self.0
79 }
80
81 pub fn kind_mut(&mut self) -> &mut ParseErrorKind {
82 &mut self.0
83 }
84
85 pub fn highlight(&self, source_map: &SourceMap) -> String {
87 let e = self.kind();
88 source_map
89 .highlight_span(e.span(), e)
90 .unwrap_or_else(|| e.to_string())
91 }
92}
93
94impl fmt::Display for ParseError {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 fmt::Display::fmt(self.kind(), f)
97 }
98}
99
100impl core::error::Error for ParseError {}
101
102impl From<ParseErrorKind> for ParseError {
103 fn from(kind: ParseErrorKind) -> Self {
104 ParseError(Box::new(kind))
105 }
106}
107
108impl From<lex::Error> for ParseError {
109 fn from(e: lex::Error) -> Self {
110 ParseErrorKind::Lex(e).into()
111 }
112}