leo_input/errors/
parser.rs

1// Copyright (C) 2019-2021 Aleo Systems Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use 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}