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