1use std::fmt::Display;
2
3use log::error;
4use pest::{iterators::Pair, Span};
5
6use crate::Rule;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum CompilerWarning {
10 StateOverwrite {
12 position: ErrorPosition,
13 state: String,
15 value_from: bool,
16 },
17}
18
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub enum CompilerError {
21 SyntaxError {
23 position: ErrorPosition,
24 message: String,
26 code: String,
28 expected: Rule,
29 found: Option<Rule>,
30 },
31
32 FileRuleError {
34 error: Box<pest::error::Error<Rule>>,
35 },
36}
37
38impl CompilerError {
39 pub fn log_error(&self) {
42 match self {
43 CompilerError::SyntaxError {
44 position,
45 message,
46 expected,
47 found,
48 ..
49 } => {
50 error!(
51 "Syntax error At position {position}: {message} - Expected {expected:?}, got {:?}",
52 found.unwrap_or(Rule::EOI)
53 );
54 }
55 CompilerError::FileRuleError { error, .. } => {
56 error!("Syntax error: {}", error);
57 }
58 }
59 }
60
61 pub fn get_message_expected(&self) -> String {
63 match &self {
64 CompilerError::SyntaxError {
65 expected, found, ..
66 } => format!("Expected {:?}, found {:?}", expected, found),
67 CompilerError::FileRuleError { error } => String::from(error.variant.message()),
68 }
69 }
70
71 pub fn code(&self) -> String {
73 match self {
74 CompilerError::SyntaxError { code, .. } => code.clone(),
75 CompilerError::FileRuleError { error, .. } => String::from(error.line()),
76 }
77 }
78
79 pub fn message(&self) -> String {
81 match self {
82 CompilerError::SyntaxError { message, .. } => String::from(message),
83 CompilerError::FileRuleError { error, .. } => error.variant.message().to_string(),
84 }
85 }
86
87 pub fn line(&self) -> usize {
89 match self {
90 CompilerError::SyntaxError { position, .. } => position.start.0,
91 CompilerError::FileRuleError { .. } => 0,
92 }
93 }
94
95 pub fn position(&self) -> ErrorPosition {
97 match self {
98 CompilerError::SyntaxError { position, .. } => *position,
99 CompilerError::FileRuleError { error, .. } => match error.line_col {
100 pest::error::LineColLocation::Pos((line, col)) => ErrorPosition {
101 start: (line, col),
102 end: None,
103 },
104 pest::error::LineColLocation::Span((line1, col1), (line2, col2)) => ErrorPosition {
105 start: (line1 - 1, col1),
106 end: Some((line2 - 1, col2)),
107 },
108 },
109 }
110 }
111
112 pub fn expected(&self) -> Rule {
114 match self {
115 CompilerError::SyntaxError { expected, .. } => *expected,
116 CompilerError::FileRuleError { error, .. } => match &error.variant {
117 pest::error::ErrorVariant::ParsingError { positives, .. } => {
118 *positives.first().unwrap()
119 }
120 _ => Rule::EOI,
121 },
122 }
123 }
124
125 pub fn found(&self) -> Option<Rule> {
127 match self {
128 CompilerError::SyntaxError { found, .. } => *found,
129 CompilerError::FileRuleError { error, .. } => match &error.variant {
130 pest::error::ErrorVariant::ParsingError { positives, .. } => {
131 Some(*positives.first().unwrap())
132 }
133 _ => None,
134 },
135 }
136 }
137}
138
139#[derive(Debug, Clone, Copy, PartialEq, Eq)]
140pub struct ErrorPosition {
142 pub start: (usize, usize),
144
145 pub end: Option<(usize, usize)>,
147}
148
149impl ErrorPosition {
150 pub fn new(start: (usize, usize), end: Option<(usize, usize)>) -> Self {
151 ErrorPosition { start, end }
152 }
153}
154
155impl Display for ErrorPosition {
156 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
157 match self.end {
158 Some(end) => write!(
159 f,
160 "{}:{} to {}:{}",
161 self.start.0, self.start.1, end.0, end.1
162 ),
163 None => write!(f, "{}:{}", self.start.0, self.start.1),
164 }
165 }
166}
167
168impl From<pest::error::LineColLocation> for ErrorPosition {
169 fn from(e: pest::error::LineColLocation) -> Self {
171 match e {
172 pest::error::LineColLocation::Pos((line, col)) => ErrorPosition {
173 start: (line - 1, col),
174 end: None,
175 },
176 pest::error::LineColLocation::Span((line1, col1), (line2, col2)) => ErrorPosition {
177 start: (line1 - 1, col1),
178 end: Some((line2 - 1, col2)),
179 },
180 }
181 }
182}
183
184impl From<pest::error::Error<Rule>> for ErrorPosition {
185 fn from(e: pest::error::Error<Rule>) -> Self {
188 match e.line_col {
189 pest::error::LineColLocation::Pos((line, col)) => ErrorPosition {
190 start: (line - 1, col),
191 end: None,
192 },
193 pest::error::LineColLocation::Span((line1, col1), (line2, col2)) => ErrorPosition {
194 start: (line1 - 1, col1),
195 end: Some((line2 - 1, col2)),
196 },
197 }
198 }
199}
200
201impl From<Span<'_>> for ErrorPosition {
202 fn from(e: Span) -> Self {
205 ErrorPosition {
206 start: (e.start_pos().line_col().0 - 1, e.start_pos().line_col().1),
207 end: Some((e.end_pos().line_col().0 - 1, e.end_pos().line_col().1)),
208 }
209 }
210}
211
212impl From<&Span<'_>> for ErrorPosition {
213 fn from(e: &Span) -> Self {
216 ErrorPosition {
217 start: (e.start_pos().line_col().0 - 1, e.start_pos().line_col().1),
218 end: Some((e.end_pos().line_col().0 - 1, e.end_pos().line_col().1)),
219 }
220 }
221}
222
223impl From<&Pair<'_, Rule>> for ErrorPosition {
224 fn from(e: &Pair<Rule>) -> Self {
227 ErrorPosition {
228 start: (e.line_col().0 - 1, e.line_col().1),
229 end: None,
230 }
231 }
232}
233
234impl From<(usize, usize)> for ErrorPosition {
235 fn from(e: (usize, usize)) -> Self {
238 ErrorPosition {
239 start: (e.0 - 1, e.1),
240 end: None,
241 }
242 }
243}