1use std::fmt;
3
4use eure_tree::tree::InputSpan;
5use parol_runtime::{LexerError, ParolError, ParserError, SyntaxError};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct EureParseError {
10 pub entries: Vec<ParseErrorEntry>,
11}
12
13impl EureParseError {
14 pub fn new_entry(span: Option<InputSpan>, message: String, kind: ParseErrorKind) -> Self {
15 Self {
16 entries: vec![ParseErrorEntry {
17 span,
18 message,
19 kind,
20 source: vec![],
21 }],
22 }
23 }
24}
25
26impl fmt::Display for EureParseError {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 for (i, entry) in self.entries.iter().enumerate() {
29 if i > 0 {
30 writeln!(f)?;
31 }
32 write!(f, "{}", entry)?;
33 }
34 Ok(())
35 }
36}
37
38impl std::error::Error for EureParseError {}
39
40impl fmt::Display for ParseErrorEntry {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 write!(f, "{}", self.message)?;
43 if let Some(span) = &self.span {
44 write!(f, " at {}..{}", span.start, span.end)?;
45 }
46 Ok(())
47 }
48}
49
50#[derive(Debug, Clone, PartialEq, Eq)]
51pub struct ParseErrorEntry {
52 pub span: Option<InputSpan>,
54 pub message: String,
56 pub kind: ParseErrorKind,
58 pub source: Vec<ParseErrorEntry>,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq)]
63pub enum ParseErrorKind {
64 SyntaxError {
66 unexpected_tokens: Vec<UnexpectedToken>,
67 expected_tokens: Vec<String>,
68 },
69 UnprocessedInput,
70 LexerError,
72 Other,
74}
75
76#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct UnexpectedToken {
78 pub name: String,
79 pub token_type: String,
80 pub token: InputSpan,
81}
82
83impl From<parol_runtime::UnexpectedToken> for UnexpectedToken {
84 fn from(
85 parol_runtime::UnexpectedToken {
86 name,
87 token_type,
88 token,
89 }: parol_runtime::UnexpectedToken,
90 ) -> Self {
91 Self {
92 name,
93 token_type,
94 token: InputSpan {
95 start: token.start,
96 end: token.end,
97 },
98 }
99 }
100}
101
102impl From<ParolError> for EureParseError {
103 fn from(error: ParolError) -> Self {
104 match error {
105 ParolError::ParserError(parser_error) => parser_error.into(),
106 ParolError::LexerError(lexer_error) => lexer_error.into(),
107 ParolError::UserError(error) => error.into(),
108 }
109 }
110}
111
112impl From<ParserError> for EureParseError {
113 fn from(error: ParserError) -> Self {
114 match error {
115 ParserError::TreeError { source } => source.into(),
116 ParserError::DataError(error) => {
117 EureParseError::new_entry(None, error.to_string(), ParseErrorKind::Other)
118 }
119 ParserError::PredictionError { cause } => {
120 EureParseError::new_entry(None, cause, ParseErrorKind::Other)
121 }
122 ParserError::SyntaxErrors { entries } => EureParseError {
123 entries: entries.into_iter().map(ParseErrorEntry::from).collect(),
124 },
125 ParserError::UnprocessedInput {
126 input: _,
127 last_token,
128 } => EureParseError::new_entry(
129 Some(InputSpan {
130 start: last_token.start,
131 end: last_token.end,
132 }),
133 "Unprocessed input".to_string(),
134 ParseErrorKind::UnprocessedInput,
135 ),
136 ParserError::Unsupported {
137 context,
138 error_location,
139 } => EureParseError::new_entry(
140 Some(InputSpan {
141 start: error_location.start,
142 end: error_location.end,
143 }),
144 format!("Unsupported: {context}"),
145 ParseErrorKind::Other,
146 ),
147 ParserError::TooManyErrors { count } => EureParseError::new_entry(
148 None,
149 format!("Too many errors: {count}"),
150 ParseErrorKind::Other,
151 ),
152 ParserError::RecoveryFailed => EureParseError::new_entry(
153 None,
154 "Recovery failed".to_string(),
155 ParseErrorKind::Other,
156 ),
157 ParserError::InternalError(error) => EureParseError::new_entry(
158 None,
159 format!("Internal error: {error}"),
160 ParseErrorKind::Other,
161 ),
162 }
163 }
164}
165
166impl From<parol_runtime::syntree::Error> for EureParseError {
167 fn from(error: parol_runtime::syntree::Error) -> Self {
168 EureParseError::new_entry(None, error.to_string(), ParseErrorKind::Other)
169 }
170}
171
172impl From<parol_runtime::SyntaxError> for ParseErrorEntry {
173 fn from(error: parol_runtime::SyntaxError) -> Self {
174 let SyntaxError {
175 cause,
176 input: _,
177 error_location,
178 unexpected_tokens,
179 expected_tokens,
180 source,
181 } = error;
182 ParseErrorEntry {
183 span: Some(InputSpan {
184 start: error_location.start,
185 end: error_location.end,
186 }),
187 message: cause,
188 kind: ParseErrorKind::SyntaxError {
189 unexpected_tokens: unexpected_tokens
190 .into_iter()
191 .map(UnexpectedToken::from)
192 .collect(),
193 expected_tokens: expected_tokens.iter().cloned().collect(),
194 },
195 source: source
196 .map(|source| EureParseError::from(*source).entries)
197 .unwrap_or_default(),
198 }
199 }
200}
201
202impl From<LexerError> for EureParseError {
203 fn from(error: LexerError) -> Self {
204 match error {
205 LexerError::TokenBufferEmptyError => EureParseError::new_entry(
206 None,
207 "Token buffer empty".to_string(),
208 ParseErrorKind::LexerError,
209 ),
210 LexerError::InternalError(error) => EureParseError::new_entry(
211 None,
212 format!("Internal error: {error}"),
213 ParseErrorKind::Other,
214 ),
215 LexerError::LookaheadExceedsMaximum => EureParseError::new_entry(
216 None,
217 "Lookahead exceeds maximum".to_string(),
218 ParseErrorKind::LexerError,
219 ),
220 LexerError::LookaheadExceedsTokenBufferLength => EureParseError::new_entry(
221 None,
222 "Lookahead exceeds token buffer length".to_string(),
223 ParseErrorKind::LexerError,
224 ),
225 LexerError::ScannerStackEmptyError => EureParseError::new_entry(
226 None,
227 "Scanner stack empty".to_string(),
228 ParseErrorKind::LexerError,
229 ),
230 LexerError::RecoveryError(error) => EureParseError::new_entry(
231 None,
232 format!("Recovery error: {error}"),
233 ParseErrorKind::LexerError,
234 ),
235 }
236 }
237}
238
239impl From<anyhow::Error> for EureParseError {
240 fn from(error: anyhow::Error) -> Self {
241 EureParseError::new_entry(None, error.to_string(), ParseErrorKind::Other)
242 }
243}