1use crate::{
18 ast::Rule,
19 errors::SyntaxError as InputSyntaxError,
20 expressions::{ArrayInlineExpression, Expression},
21 sections::Header,
22 tables::Table,
23 types::{DataType, IntegerType, Type},
24 values::{NumberValue, Value},
25};
26
27use pest::{
28 error::{Error, ErrorVariant},
29 Span,
30};
31use std::{num::ParseIntError, path::PathBuf, str::ParseBoolError};
32
33#[derive(Debug, Error)]
34pub enum InputParserError {
35 #[error("Program input value {} not found", _0)]
36 InputNotFound(String),
37
38 #[error("Cannot read from the provided file path - {:?}", _0)]
39 FileReadError(PathBuf),
40
41 #[error("{}", _0)]
42 ParseIntError(#[from] ParseIntError),
43
44 #[error("{}", _0)]
45 ParseBoolError(#[from] ParseBoolError),
46
47 #[error("{}", _0)]
48 SyntaxError(#[from] InputSyntaxError),
49
50 #[error("Unable to construct program input abstract syntax tree")]
51 SyntaxTreeError,
52}
53
54impl InputParserError {
55 pub fn set_path(&mut self, path: &str, _content: &[String]) {
56 if let InputParserError::SyntaxError(error) = self {
57 let new_error: Error<Rule> = match error {
58 InputSyntaxError::Error(error) => {
59 let new_error = error.clone();
60 new_error.with_path(path)
61 }
62 };
63
64 tracing::error!("{}", new_error);
65
66 *error = InputSyntaxError::Error(new_error);
67 }
68 }
69
70 pub fn get_path(&self) -> Option<&str> {
71 None
72 }
73
74 fn new_from_span(message: String, span: &Span) -> Self {
75 let error = Error::new_from_span(ErrorVariant::CustomError { message }, span.to_owned());
76
77 InputParserError::SyntaxError(InputSyntaxError::from(error))
78 }
79
80 pub fn array_index(actual: String, span: &Span) -> Self {
81 let message = format!("Expected constant number for array index, found `{}`", actual);
82
83 Self::new_from_span(message, span)
84 }
85
86 pub fn integer_type_mismatch(expected: IntegerType, received: IntegerType, span: &Span) -> Self {
87 let message = format!("expected data type `{}`, found `{}`", expected, received);
88
89 Self::new_from_span(message, span)
90 }
91
92 pub fn invalid_char(character: String, span: &Span) -> Self {
93 let message = format!("Expected valid character found `{}`", character);
94
95 Self::new_from_span(message, span)
96 }
97
98 pub fn invalid_string_dimensions(span: &Span) -> Self {
99 let message = "String type defintion of a char array should not be multi-dimensional".to_string();
100
101 Self::new_from_span(message, span)
102 }
103
104 pub fn invalid_string_length(expected: usize, received: usize, span: &Span) -> Self {
105 let message = format!(
106 "Expected size of char array `{}` to match string size instead received `{}`",
107 expected, received
108 );
109
110 Self::new_from_span(message, span)
111 }
112
113 pub fn implicit_type(data_type: DataType, implicit: NumberValue) -> Self {
114 let message = format!("expected `{}`, found `{}`", data_type, implicit);
115
116 Self::new_from_span(message, implicit.span())
117 }
118
119 pub fn implicit_group(number: NumberValue) -> Self {
120 let message = format!("group coordinates should be in (x, y)group format, found `{}`", number);
121
122 Self::new_from_span(message, number.span())
123 }
124
125 pub fn data_type_mismatch(data_type: DataType, value: Value) -> Self {
126 let message = format!("expected data type `{}`, found `{}`", data_type, value);
127
128 Self::new_from_span(message, value.span())
129 }
130
131 pub fn expression_type_mismatch(type_: Type, expression: Expression) -> Self {
132 let message = format!("expected expression type `{}`, found `{}`", type_, expression);
133 let span = expression.span().to_owned();
134
135 Self::new_from_span(message, &span)
136 }
137
138 pub fn array_inline_length(number: usize, array: ArrayInlineExpression) -> Self {
139 let message = format!(
140 "expected an array with a fixed size of {} elements, found one with {} elements",
141 number,
142 array.expressions.len()
143 );
144 let span = array.span.to_owned();
145
146 Self::new_from_span(message, &span)
147 }
148
149 pub fn array_init_length(expected: Vec<usize>, actual: Vec<usize>, span: &Span) -> Self {
150 let message = format!(
151 "expected an array with a fixed size of {:?} elements, found one with {:?} elements",
152 expected, actual
153 );
154
155 Self::new_from_span(message, span)
156 }
157
158 pub fn input_section_header(header: Header) -> Self {
159 let message = format!("the section header `{}` is not valid in an input `.in` file", header);
160 let span = header.span();
161
162 Self::new_from_span(message, &span)
163 }
164
165 pub fn public_section(header: Header) -> Self {
166 let message = format!("the section header `{}` is not a public section", header);
167 let span = header.span();
168
169 Self::new_from_span(message, &span)
170 }
171
172 pub fn private_section(header: Header) -> Self {
173 let message = format!("the section header `{}` is not a private section", header);
174 let span = header.span();
175
176 Self::new_from_span(message, &span)
177 }
178
179 pub fn table(table: Table) -> Self {
180 let message = format!(
181 "the double bracket section `{}` is not valid in an input `.in` file",
182 table
183 );
184
185 Self::new_from_span(message, &table.span)
186 }
187
188 pub fn tuple_length(expected: usize, actual: usize, span: &Span) -> Self {
189 let message = format!(
190 "expected a tuple with {} elements, found a tuple with {} elements",
191 expected, actual
192 );
193
194 Self::new_from_span(message, &span)
195 }
196
197 pub fn section(header: Header) -> Self {
198 let message = format!(
199 "the section header `{}` must have a double bracket visibility in a state `.state` file",
200 header
201 );
202 let span = header.span();
203
204 Self::new_from_span(message, &span)
205 }
206}
207
208impl From<Error<Rule>> for InputParserError {
209 fn from(error: Error<Rule>) -> Self {
210 InputParserError::SyntaxError(InputSyntaxError::from(error))
211 }
212}