smt_lang/
error.rs

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
101//------------------------- To Entry -------------------------
102
103pub 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}