1use crate::parser::Position;
2use crate::problem::*;
3use d_stuff::Message;
4use lalrpop_util::lexer::Token;
5use lalrpop_util::ParseError;
6use line_col::LineColLookup;
7
8pub enum Error {
9 File {
10 filename: String,
11 message: String,
12 },
13 Parse {
14 message: String,
15 token: Option<String>,
16 position: Option<Position>,
17 expected: Vec<String>,
18 },
19 Duplicate {
20 name: String,
21 first: Option<Position>,
22 second: Option<Position>,
23 },
24 Instance {
25 name: String,
26 position: Option<Position>,
27 },
28 Resolve {
29 category: String,
30 name: String,
31 position: Option<Position>,
32 },
33 Interval {
34 name: String,
35 position: Option<Position>,
36 },
37 Parameter {
38 expr: Expr,
39 size: usize,
40 expected: usize,
41 },
42 Bounded {
43 name: String,
44 position: Option<Position>,
45 },
46 Type {
47 expr: Expr,
48 typ: Type,
49 expected: Vec<Type>,
50 },
51 Empty {
52 name: String,
53 category: String,
54 },
55 Cyclic {
56 id: ClassId,
57 },
58}
59
60impl Error {
61 pub fn new_parse(
62 file: &str,
63 lookup: &LineColLookup,
64 error: ParseError<usize, Token, &str>,
65 ) -> Self {
66 match error {
67 ParseError::InvalidToken { location } => Self::Parse {
68 message: "Invalid Token".into(),
69 token: None,
70 position: Some(Position::new(file, lookup, location)),
71 expected: Vec::new(),
72 },
73 ParseError::UnrecognizedEOF { location, expected } => Self::Parse {
74 message: "Unreconized EOF".into(),
75 token: None,
76 position: Some(Position::new(file, lookup, location)),
77 expected,
78 },
79 ParseError::UnrecognizedToken { token, expected } => Self::Parse {
80 message: "Unreconized Token".into(),
81 token: Some(token.1.to_string()),
82 position: Some(Position::new(file, lookup, token.0)),
83 expected,
84 },
85 ParseError::ExtraToken { token } => Self::Parse {
86 message: "Extra Token".into(),
87 token: Some(token.1.to_string()),
88 position: Some(Position::new(file, lookup, token.0)),
89 expected: Vec::new(),
90 },
91 ParseError::User { error } => Self::Parse {
92 message: "Parse Error".into(),
93 token: Some(error.to_string()),
94 position: None,
95 expected: Vec::new(),
96 },
97 }
98 }
99}
100
101pub fn expected_to_message(expected: &Vec<String>) -> d_stuff::Message {
104 let title = d_stuff::Text::new(
105 "Expexted",
106 termion::style::Reset.to_string(),
107 termion::color::White.fg_str(),
108 );
109
110 let mut s = "".to_string();
111 if let Some((first, others)) = expected.split_first() {
112 s.push_str(first);
113 for x in others {
114 s.push_str(&format!(" {}", x));
115 }
116 }
117 let message = d_stuff::Text::new(
118 s,
119 termion::style::Reset.to_string(),
120 termion::color::LightBlue.fg_str(),
121 );
122 d_stuff::Message::new(Some(title), message)
123}
124
125impl ToEntry for Error {
126 fn to_entry(&self, problem: &Problem) -> d_stuff::Entry {
127 match self {
128 Error::File { filename, message } => d_stuff::Entry::new(
129 d_stuff::Status::Failure,
130 d_stuff::Text::new(
131 "File",
132 termion::style::Bold.to_string(),
133 termion::color::Blue.fg_str(),
134 ),
135 Some(d_stuff::Text::new(
136 "ERROR",
137 termion::style::Reset.to_string(),
138 termion::color::Red.fg_str(),
139 )),
140 vec![
141 d_stuff::Message::new(
142 Some(d_stuff::Text::new(
143 "Cannot Read File",
144 termion::style::Reset.to_string(),
145 termion::color::Red.fg_str(),
146 )),
147 d_stuff::Text::new(
148 filename,
149 termion::style::Reset.to_string(),
150 termion::color::Cyan.fg_str(),
151 ),
152 ),
153 d_stuff::Message::new(
154 Some(d_stuff::Text::new(
155 "Message",
156 termion::style::Reset.to_string(),
157 termion::color::White.fg_str(),
158 )),
159 d_stuff::Text::new(
160 message,
161 termion::style::Reset.to_string(),
162 termion::color::LightBlue.fg_str(),
163 ),
164 ),
165 ],
166 ),
167 Error::Parse {
168 message,
169 token,
170 position,
171 expected,
172 } => {
173 let mut messages = vec![];
174
175 let title = d_stuff::Text::new(
176 message,
177 termion::style::Reset.to_string(),
178 termion::color::Red.fg_str(),
179 );
180 if let Some(token) = token {
181 messages.push(d_stuff::Message::new(
182 Some(title),
183 d_stuff::Text::new(
184 format!("'{}'", token),
185 termion::style::Reset.to_string(),
186 termion::color::LightBlue.fg_str(),
187 ),
188 ))
189 } else {
190 messages.push(d_stuff::Message::new(None, title));
191 }
192 if let Some(position) = position {
193 messages.push(position.to_message());
194 }
195 if !expected.is_empty() {
196 messages.push(expected_to_message(expected));
197 }
198
199 d_stuff::Entry::new(
200 d_stuff::Status::Failure,
201 d_stuff::Text::new(
202 "Parse",
203 termion::style::Bold.to_string(),
204 termion::color::Blue.fg_str(),
205 ),
206 Some(d_stuff::Text::new(
207 "ERROR",
208 termion::style::Reset.to_string(),
209 termion::color::Red.fg_str(),
210 )),
211 messages,
212 )
213 }
214
215 Error::Duplicate {
216 name,
217 first,
218 second,
219 } => {
220 let mut messages = vec![];
221
222 messages.push(Message::new(
223 Some(d_stuff::Text::new(
224 "Defined Twice",
225 termion::style::Reset.to_string(),
226 termion::color::Red.fg_str(),
227 )),
228 d_stuff::Text::new(
229 format!("'{}'", name),
230 termion::style::Reset.to_string(),
231 termion::color::LightBlue.fg_str(),
232 ),
233 ));
234 if let Some(position) = first {
235 messages.push(position.to_message());
236 }
237 if let Some(position) = second {
238 messages.push(position.to_message());
239 }
240
241 d_stuff::Entry::new(
242 d_stuff::Status::Failure,
243 d_stuff::Text::new(
244 "Unicity",
245 termion::style::Bold.to_string(),
246 termion::color::Blue.fg_str(),
247 ),
248 Some(d_stuff::Text::new(
249 "ERROR",
250 termion::style::Reset.to_string(),
251 termion::color::Red.fg_str(),
252 )),
253 messages,
254 )
255 }
256 Error::Instance { name, position } => {
257 let mut messages = vec![];
258
259 messages.push(Message::new(
260 Some(d_stuff::Text::new(
261 "Undefined Structure",
262 termion::style::Reset.to_string(),
263 termion::color::Red.fg_str(),
264 )),
265 d_stuff::Text::new(
266 format!("'{}'", name),
267 termion::style::Reset.to_string(),
268 termion::color::LightBlue.fg_str(),
269 ),
270 ));
271 if let Some(position) = position {
272 messages.push(position.to_message());
273 }
274
275 d_stuff::Entry::new(
276 d_stuff::Status::Failure,
277 d_stuff::Text::new(
278 "Instance",
279 termion::style::Bold.to_string(),
280 termion::color::Blue.fg_str(),
281 ),
282 Some(d_stuff::Text::new(
283 "ERROR",
284 termion::style::Reset.to_string(),
285 termion::color::Red.fg_str(),
286 )),
287 messages,
288 )
289 }
290 Error::Resolve {
291 category,
292 name,
293 position,
294 } => {
295 let mut messages = vec![];
296
297 messages.push(Message::new(
298 Some(d_stuff::Text::new(
299 format!("Undefined {}", category),
300 termion::style::Reset.to_string(),
301 termion::color::Red.fg_str(),
302 )),
303 d_stuff::Text::new(
304 format!("'{}'", name),
305 termion::style::Reset.to_string(),
306 termion::color::LightBlue.fg_str(),
307 ),
308 ));
309 if let Some(position) = position {
310 messages.push(position.to_message());
311 }
312
313 d_stuff::Entry::new(
314 d_stuff::Status::Failure,
315 d_stuff::Text::new(
316 "Resolve",
317 termion::style::Bold.to_string(),
318 termion::color::Blue.fg_str(),
319 ),
320 Some(d_stuff::Text::new(
321 "ERROR",
322 termion::style::Reset.to_string(),
323 termion::color::Red.fg_str(),
324 )),
325 messages,
326 )
327 }
328 Error::Interval { name, position } => {
329 let mut messages = vec![];
330
331 messages.push(Message::new(
332 Some(d_stuff::Text::new(
333 "Malformed Interval",
334 termion::style::Reset.to_string(),
335 termion::color::Red.fg_str(),
336 )),
337 d_stuff::Text::new(
338 format!("'{}'", name),
339 termion::style::Reset.to_string(),
340 termion::color::LightBlue.fg_str(),
341 ),
342 ));
343 if let Some(position) = position {
344 messages.push(position.to_message());
345 }
346
347 d_stuff::Entry::new(
348 d_stuff::Status::Failure,
349 d_stuff::Text::new(
350 "Interval",
351 termion::style::Bold.to_string(),
352 termion::color::Blue.fg_str(),
353 ),
354 Some(d_stuff::Text::new(
355 "ERROR",
356 termion::style::Reset.to_string(),
357 termion::color::Red.fg_str(),
358 )),
359 messages,
360 )
361 }
362 Error::Parameter {
363 expr,
364 size,
365 expected,
366 } => {
367 let mut messages = vec![];
368
369 messages.push(Message::new(
370 Some(d_stuff::Text::new(
371 "Parameter size",
372 termion::style::Reset.to_string(),
373 termion::color::Red.fg_str(),
374 )),
375 d_stuff::Text::new(
376 format!("'{}'", expr.to_lang(problem)),
377 termion::style::Reset.to_string(),
378 termion::color::LightBlue.fg_str(),
379 ),
380 ));
381 if let Some(position) = expr.position() {
382 messages.push(position.to_message());
383 }
384 messages.push(Message::new(
385 Some(d_stuff::Text::new(
386 "size",
387 termion::style::Reset.to_string(),
388 termion::color::White.fg_str(),
389 )),
390 d_stuff::Text::new(
391 size.to_string(),
392 termion::style::Reset.to_string(),
393 termion::color::LightBlue.fg_str(),
394 ),
395 ));
396 messages.push(Message::new(
397 Some(d_stuff::Text::new(
398 "expected",
399 termion::style::Reset.to_string(),
400 termion::color::White.fg_str(),
401 )),
402 d_stuff::Text::new(
403 expected.to_string(),
404 termion::style::Reset.to_string(),
405 termion::color::LightBlue.fg_str(),
406 ),
407 ));
408
409 d_stuff::Entry::new(
410 d_stuff::Status::Failure,
411 d_stuff::Text::new(
412 "Parameter",
413 termion::style::Bold.to_string(),
414 termion::color::Blue.fg_str(),
415 ),
416 Some(d_stuff::Text::new(
417 "ERROR",
418 termion::style::Reset.to_string(),
419 termion::color::Red.fg_str(),
420 )),
421 messages,
422 )
423 }
424 Error::Bounded { name, position } => {
425 let mut messages = vec![];
426
427 messages.push(Message::new(
428 Some(d_stuff::Text::new(
429 "Ubounded Type",
430 termion::style::Reset.to_string(),
431 termion::color::Red.fg_str(),
432 )),
433 d_stuff::Text::new(
434 format!("'{}'", name),
435 termion::style::Reset.to_string(),
436 termion::color::LightBlue.fg_str(),
437 ),
438 ));
439 if let Some(position) = position {
440 messages.push(position.to_message());
441 }
442
443 d_stuff::Entry::new(
444 d_stuff::Status::Failure,
445 d_stuff::Text::new(
446 "Bounded",
447 termion::style::Bold.to_string(),
448 termion::color::Blue.fg_str(),
449 ),
450 Some(d_stuff::Text::new(
451 "ERROR",
452 termion::style::Reset.to_string(),
453 termion::color::Red.fg_str(),
454 )),
455 messages,
456 )
457 }
458 Error::Type {
459 expr,
460 typ,
461 expected,
462 } => {
463 let mut messages = vec![];
464
465 messages.push(d_stuff::Message::new(
466 Some(d_stuff::Text::new(
467 "Type Error",
468 termion::style::Reset.to_string(),
469 termion::color::Red.fg_str(),
470 )),
471 d_stuff::Text::new(
472 format!("'{}'", expr.to_lang(problem)),
473 termion::style::Reset.to_string(),
474 termion::color::LightBlue.fg_str(),
475 ),
476 ));
477
478 if let Some(position) = expr.position() {
479 messages.push(position.to_message());
480 }
481
482 messages.push(d_stuff::Message::new(
483 Some(d_stuff::Text::new(
484 "Type",
485 termion::style::Reset.to_string(),
486 termion::color::White.fg_str(),
487 )),
488 d_stuff::Text::new(
489 typ.to_lang(problem),
490 termion::style::Reset.to_string(),
491 termion::color::LightBlue.fg_str(),
492 ),
493 ));
494
495 if !expected.is_empty() {
496 messages.push(expected_to_message(
497 &expected.iter().map(|t| t.to_lang(problem)).collect(),
498 ));
499 }
500
501 d_stuff::Entry::new(
502 d_stuff::Status::Failure,
503 d_stuff::Text::new(
504 "Type",
505 termion::style::Bold.to_string(),
506 termion::color::Blue.fg_str(),
507 ),
508 Some(d_stuff::Text::new(
509 "ERROR",
510 termion::style::Reset.to_string(),
511 termion::color::Red.fg_str(),
512 )),
513 messages,
514 )
515 }
516 Error::Empty { name, category } => {
517 let mut messages = vec![];
518
519 messages.push(d_stuff::Message::new(
520 Some(d_stuff::Text::new(
521 format!("Empty {}", category),
522 termion::style::Reset.to_string(),
523 termion::color::Red.fg_str(),
524 )),
525 d_stuff::Text::new(
526 format!("'{}'", name),
527 termion::style::Reset.to_string(),
528 termion::color::LightBlue.fg_str(),
529 ),
530 ));
531
532 d_stuff::Entry::new(
533 d_stuff::Status::Failure,
534 d_stuff::Text::new(
535 "Empty",
536 termion::style::Bold.to_string(),
537 termion::color::Blue.fg_str(),
538 ),
539 Some(d_stuff::Text::new(
540 "ERROR",
541 termion::style::Reset.to_string(),
542 termion::color::Red.fg_str(),
543 )),
544 messages,
545 )
546 }
547 Error::Cyclic { id } => {
548 let mut messages = vec![];
549
550 let c = problem.get(*id).unwrap();
551
552 messages.push(d_stuff::Message::new(
553 Some(d_stuff::Text::new(
554 "Cyclic Inheritance",
555 termion::style::Reset.to_string(),
556 termion::color::Red.fg_str(),
557 )),
558 d_stuff::Text::new(
559 format!("'{}'", c.name()),
560 termion::style::Reset.to_string(),
561 termion::color::LightBlue.fg_str(),
562 ),
563 ));
564
565 if let Some(position) = c.position() {
566 messages.push(position.to_message());
567 }
568
569 d_stuff::Entry::new(
570 d_stuff::Status::Failure,
571 d_stuff::Text::new(
572 "Cycle",
573 termion::style::Bold.to_string(),
574 termion::color::Blue.fg_str(),
575 ),
576 Some(d_stuff::Text::new(
577 "ERROR",
578 termion::style::Reset.to_string(),
579 termion::color::Red.fg_str(),
580 )),
581 messages,
582 )
583 }
584 }
585 }
586}