microcad_lang/parse/
parse_error.rs1use crate::{parse::*, ty::*};
7use microcad_syntax::ast::LiteralErrorKind;
8use miette::{Diagnostic, LabeledSpan, SourceCode};
9use std::iter::once;
10use thiserror::Error;
11
12#[derive(Debug, Error)]
14#[allow(missing_docs)]
15pub enum ParseError {
16 #[error("Error parsing floating point literal: {0}")]
18 ParseFloatError(Refer<std::num::ParseFloatError>),
19
20 #[error("Error parsing integer literal: {0}")]
22 ParseIntError(Refer<std::num::ParseIntError>),
23
24 #[error("IO Error: {0}")]
26 IoError(Refer<std::io::Error>),
27
28 #[error("Error parsing color: {0}")]
30 ParseColorError(Refer<microcad_core::ParseColorError>),
31
32 #[error("Unknown color: {0}")]
34 UnknownColorName(Refer<String>),
35
36 #[error("Unknown unit: {0}")]
38 UnknownUnit(Refer<String>),
39
40 #[error("Unexpected token")]
42 UnexpectedToken(SrcRef),
43
44 #[error("Tuple expression contains both named and positional arguments")]
46 MixedTupleArguments(SrcRef),
47
48 #[error("Duplicate named argument: {0}")]
50 DuplicateNamedArgument(Identifier),
51
52 #[error("Positional argument after named argument")]
54 PositionalArgumentAfterNamed(SrcRef),
55
56 #[error("Empty tuple expression")]
58 EmptyTupleExpression(SrcRef),
59
60 #[error("Missing type or value for definition parameter: {0}")]
62 ParameterMissingTypeOrValue(Identifier),
63
64 #[error("Duplicate parameter: {0}")]
66 DuplicateParameter(Identifier),
67
68 #[error("Duplicate argument: {0}")]
70 DuplicateArgument(Identifier),
71
72 #[error("Duplicated type name in map: {0}")]
74 DuplicatedMapType(Identifier),
75
76 #[error("Duplicate id: {0}")]
78 DuplicateIdentifier(Identifier),
79
80 #[error("Duplicate id in tuple: {0}")]
82 DuplicateTupleIdentifier(Identifier),
83
84 #[error("Duplicate unnamed type in tuple: {0}")]
86 DuplicateTupleType(Refer<Type>),
87
88 #[error("Missing format expression")]
90 MissingFormatExpression(SrcRef),
91
92 #[error("Statement between two init statements")]
94 StatementBetweenInit(SrcRef),
95
96 #[error("Loading of source file {1:?} failed: {2}")]
98 LoadSource(SrcRef, std::path::PathBuf, std::io::Error),
99
100 #[error("Grammar rule error {0}")]
102 GrammarRuleError(Refer<String>),
103
104 #[error("Invalid qualified name '{0}'")]
106 InvalidQualifiedName(Refer<String>),
107
108 #[error("Invalid id '{0}'")]
110 InvalidIdentifier(Refer<String>),
111
112 #[error("Qualified name {0} cannot be converted into an Id")]
114 QualifiedNameIsNoId(QualifiedName),
115
116 #[error("Element is not available")]
118 NotAvailable(SrcRef),
119
120 #[error("Unknown type: {0}")]
122 UnknownType(Refer<String>),
123
124 #[error("Invalid matrix type: {0}")]
126 InvalidMatrixType(Refer<String>),
127
128 #[error("If expression must return a value in all cases")]
130 IncompleteIfExpression(SrcRef),
131
132 #[error("Invalid glob pattern, wildcard must be at the end of the pattern")]
134 InvalidGlobPattern(SrcRef),
135
136 #[error("Glob imports can't be given an alias")]
138 UseGlobAlias(SrcRef),
139
140 #[error("{error}")]
142 AstParser {
143 src_ref: SrcRef,
144 error: microcad_syntax::ParseError,
145 },
146
147 #[error("Call attributes must have a plain identifier as name")]
149 InvalidAttributeCall(QualifiedName),
150
151 #[error("Invalid literal: {error}")]
153 InvalidLiteral {
154 error: LiteralErrorKind,
155 src_ref: SrcRef,
156 },
157
158 #[error("Invalid expression")]
160 InvalidExpression { src_ref: SrcRef },
161
162 #[error("Invalid statement")]
164 InvalidStatement { src_ref: SrcRef },
165
166 #[error("range expressions must be between integers")]
168 InvalidRangeType { src_ref: SrcRef },
169}
170
171pub type ParseResult<T> = Result<T, ParseError>;
173
174impl SrcReferrer for ParseError {
175 fn src_ref(&self) -> SrcRef {
176 match self {
177 ParseError::DuplicateNamedArgument(id)
178 | ParseError::ParameterMissingTypeOrValue(id)
179 | ParseError::DuplicateParameter(id)
180 | ParseError::DuplicateArgument(id)
181 | ParseError::DuplicatedMapType(id)
182 | ParseError::DuplicateIdentifier(id)
183 | ParseError::DuplicateTupleIdentifier(id) => id.src_ref(),
184 ParseError::QualifiedNameIsNoId(name) | ParseError::InvalidAttributeCall(name) => {
185 name.src_ref()
186 }
187 ParseError::UnexpectedToken(src_ref)
188 | ParseError::MixedTupleArguments(src_ref)
189 | ParseError::PositionalArgumentAfterNamed(src_ref)
190 | ParseError::EmptyTupleExpression(src_ref)
191 | ParseError::MissingFormatExpression(src_ref)
192 | ParseError::StatementBetweenInit(src_ref)
193 | ParseError::NotAvailable(src_ref)
194 | ParseError::IncompleteIfExpression(src_ref)
195 | ParseError::LoadSource(src_ref, ..)
196 | ParseError::InvalidGlobPattern(src_ref)
197 | ParseError::UseGlobAlias(src_ref)
198 | ParseError::AstParser { src_ref, .. }
199 | ParseError::InvalidLiteral { src_ref, .. }
200 | ParseError::InvalidExpression { src_ref }
201 | ParseError::InvalidStatement { src_ref }
202 | ParseError::InvalidRangeType { src_ref } => src_ref.clone(),
203 ParseError::ParseFloatError(parse_float_error) => parse_float_error.src_ref(),
204 ParseError::ParseIntError(parse_int_error) => parse_int_error.src_ref(),
205 ParseError::IoError(error) => error.src_ref(),
206 ParseError::ParseColorError(parse_color_error) => parse_color_error.src_ref(),
207 ParseError::UnknownColorName(name) => name.src_ref(),
208 ParseError::UnknownUnit(unit) => unit.src_ref(),
209 ParseError::DuplicateTupleType(ty) => ty.src_ref(),
210 ParseError::GrammarRuleError(rule) => rule.src_ref(),
211 ParseError::InvalidQualifiedName(name) => name.src_ref(),
212 ParseError::InvalidIdentifier(id) => id.src_ref(),
213 ParseError::UnknownType(ty) => ty.src_ref(),
214 ParseError::InvalidMatrixType(ty) => ty.src_ref(),
215 }
216 }
217}
218
219impl ParseError {
220 pub fn with_source(self, source: String) -> ParseErrorsWithSource {
222 ParseErrorsWithSource {
223 errors: vec![self],
224 source_code: Some(source),
225 source_hash: 0,
226 }
227 }
228}
229
230impl Diagnostic for ParseError {
231 fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
232 let src_ref = self.src_ref().0?;
233 let message = match self {
234 ParseError::AstParser { error, .. } => {
235 return error.labels();
236 }
237 _ => self.to_string(),
238 };
239 let label = LabeledSpan::new(Some(message), src_ref.range.start, src_ref.range.len());
240 Some(Box::new(once(label)))
241 }
242}
243
244#[derive(Debug, Error)]
246#[error("Failed to parse")] pub struct ParseErrorsWithSource {
248 pub errors: Vec<ParseError>,
250 pub source_code: Option<String>,
252 pub source_hash: u64,
254}
255
256impl From<ParseError> for ParseErrorsWithSource {
257 fn from(value: ParseError) -> Self {
258 ParseErrorsWithSource {
259 errors: vec![value],
260 source_code: None,
261 source_hash: 0,
262 }
263 }
264}
265
266impl From<Vec<ParseError>> for ParseErrorsWithSource {
267 fn from(value: Vec<ParseError>) -> Self {
268 ParseErrorsWithSource {
269 errors: value,
270 source_code: None,
271 source_hash: 0,
272 }
273 }
274}
275
276impl Diagnostic for ParseErrorsWithSource {
277 fn source_code(&self) -> Option<&dyn SourceCode> {
278 self.source_code
279 .as_ref()
280 .map(|source| source as &dyn SourceCode)
281 }
282
283 fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
284 Some(Box::new(
285 self.errors.iter().map(|e| -> &dyn Diagnostic { e }),
286 ))
287 }
288}
289
290impl SrcReferrer for ParseErrorsWithSource {
291 fn src_ref(&self) -> SrcRef {
292 self.errors[0].src_ref()
293 }
294}