microcad_lang/parse/
parse_error.rs1use crate::{parse::*, ty::*};
7use microcad_lang_base::{SrcRef, SrcReferrer};
8use microcad_syntax::ast::LiteralErrorKind;
9use miette::{Diagnostic, SourceCode};
10use thiserror::Error;
11
12#[derive(Debug, Error, Diagnostic)]
14#[allow(missing_docs)]
15pub enum ParseError {
16 #[error("Error parsing floating point literal: {0}")]
17 ParseFloatError(#[label("{0}")] Refer<std::num::ParseFloatError>),
18
19 #[error("Error parsing integer literal: {0}")]
20 ParseIntError(#[label("{0}")] Refer<std::num::ParseIntError>),
21
22 #[error("Unknown unit: {0}")]
23 UnknownUnit(#[label("Unknown unit")] Refer<String>),
24
25 #[error("Unexpected token")]
26 UnexpectedToken(#[label("Unexpected token")] SrcRef),
27
28 #[error("Missing type or value for definition parameter: {0}")]
29 ParameterMissingTypeOrValue(#[label("Missing type or value")] Identifier),
30
31 #[error("Duplicate argument: {id}")]
32 DuplicateArgument {
33 #[label(primary, "Duplicate argument")]
34 id: Identifier,
35 #[label("Previous declaration")]
36 previous: Identifier,
37 },
38
39 #[error("Duplicate id: {id}")]
40 DuplicateIdentifier {
41 #[label(primary, "Duplicate identifier")]
42 id: Identifier,
43 #[label("Previous declaration")]
44 previous: Identifier,
45 },
46
47 #[error("Duplicate id in tuple: {id}")]
48 DuplicateTupleIdentifier {
49 #[label(primary, "Duplicate identifier")]
50 id: Identifier,
51 #[label("Previous declaration")]
52 previous: Identifier,
53 },
54
55 #[error("Duplicate unnamed type in tuple: {ty}")]
56 DuplicateTupleType {
57 #[label(primary, "Duplicate item")]
58 ty: Refer<Type>,
59 #[label("Previous declaration")]
60 previous: Refer<Type>,
61 },
62
63 #[error("Loading of source file {1:?} failed: {2}")]
64 LoadSource(SrcRef, std::path::PathBuf, std::io::Error),
65
66 #[error("Invalid id '{0}'")]
68 InvalidIdentifier(Refer<String>),
69
70 #[error("Element is not available")]
71 NotAvailable(#[label("Element is not available")] SrcRef),
72
73 #[error("Unknown type: {0}")]
74 UnknownType(#[label("Unknown type")] Refer<String>),
75
76 #[error("If expression must return a value in all cases")]
77 IncompleteIfExpression(#[label("Incomplete if expression")] SrcRef),
78
79 #[error("Invalid matrix type: {0}")]
81 InvalidMatrixType(Refer<String>),
82
83 #[error("Invalid glob pattern, wildcard must be at the end of the pattern")]
85 InvalidGlobPattern(SrcRef),
86
87 #[error("Glob imports can't be given an alias")]
89 UseGlobAlias(SrcRef),
90
91 #[error(transparent)]
93 #[diagnostic(transparent)]
94 AstParser(Refer<microcad_syntax::ParseError>),
95
96 #[error("Invalid literal: {error}")]
98 InvalidLiteral {
99 error: LiteralErrorKind,
100 #[label("{error}")]
101 src_ref: SrcRef,
102 },
103
104 #[error("Invalid expression")]
106 InvalidExpression { src_ref: SrcRef },
107
108 #[error("Invalid statement")]
110 InvalidStatement { src_ref: SrcRef },
111
112 #[error("range expressions must be between integers")]
114 InvalidRangeType { src_ref: SrcRef },
115}
116
117pub type ParseResult<T> = Result<T, ParseError>;
119
120impl SrcReferrer for ParseError {
121 fn src_ref(&self) -> SrcRef {
122 match self {
123 ParseError::ParameterMissingTypeOrValue(id)
124 | ParseError::DuplicateArgument { id, .. }
125 | ParseError::DuplicateIdentifier { id, .. }
126 | ParseError::DuplicateTupleIdentifier { id, .. } => id.src_ref(),
127 ParseError::UnexpectedToken(src_ref)
128 | ParseError::NotAvailable(src_ref)
129 | ParseError::IncompleteIfExpression(src_ref)
130 | ParseError::LoadSource(src_ref, ..)
131 | ParseError::InvalidGlobPattern(src_ref)
132 | ParseError::UseGlobAlias(src_ref)
133 | ParseError::InvalidLiteral { src_ref, .. }
134 | ParseError::InvalidExpression { src_ref }
135 | ParseError::InvalidStatement { src_ref }
136 | ParseError::InvalidRangeType { src_ref } => src_ref.clone(),
137 ParseError::ParseFloatError(parse_float_error) => parse_float_error.src_ref(),
138 ParseError::ParseIntError(parse_int_error) => parse_int_error.src_ref(),
139 ParseError::InvalidIdentifier(id) => id.src_ref(),
140 ParseError::UnknownUnit(unit) => unit.src_ref(),
141 ParseError::DuplicateTupleType { ty, .. } => ty.src_ref(),
142 ParseError::UnknownType(ty) => ty.src_ref(),
143 ParseError::InvalidMatrixType(ty) => ty.src_ref(),
144 ParseError::AstParser(err) => err.src_ref(),
145 }
146 }
147}
148
149impl ParseError {
150 pub fn with_source(self, source: String) -> ParseErrorsWithSource {
152 ParseErrorsWithSource {
153 errors: vec![self],
154 source_code: Some(source),
155 source_hash: 0,
156 }
157 }
158}
159
160#[derive(Debug, Error)]
162#[error("Failed to parse")] pub struct ParseErrorsWithSource {
164 pub errors: Vec<ParseError>,
166 pub source_code: Option<String>,
168 pub source_hash: u64,
170}
171
172impl From<ParseError> for ParseErrorsWithSource {
173 fn from(value: ParseError) -> Self {
174 ParseErrorsWithSource {
175 errors: vec![value],
176 source_code: None,
177 source_hash: 0,
178 }
179 }
180}
181
182impl From<Vec<ParseError>> for ParseErrorsWithSource {
183 fn from(value: Vec<ParseError>) -> Self {
184 ParseErrorsWithSource {
185 errors: value,
186 source_code: None,
187 source_hash: 0,
188 }
189 }
190}
191
192impl Diagnostic for ParseErrorsWithSource {
193 fn source_code(&self) -> Option<&dyn SourceCode> {
194 self.source_code
195 .as_ref()
196 .map(|source| source as &dyn SourceCode)
197 }
198
199 fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
200 Some(Box::new(
201 self.errors.iter().map(|e| -> &dyn Diagnostic { e }),
202 ))
203 }
204}
205
206impl SrcReferrer for ParseErrorsWithSource {
207 fn src_ref(&self) -> SrcRef {
208 self.errors[0].src_ref()
209 }
210}