rl_model/parser/
error.rs

1use lalrpop_util::lexer::Token;
2use lalrpop_util::ParseError;
3use line_col::LineColLookup;
4
5use crate::parser::Position;
6
7#[derive(Clone)]
8pub enum RlError {
9    File {
10        filename: String,
11        message: String,
12    },
13    Parse {
14        message: String,
15        position: Option<Position>,
16        expected: Vec<String>,
17    },
18    Duplicate {
19        name: String,
20        first: Option<Position>,
21        second: Option<Position>,
22    },
23    Resolve {
24        element: String,
25        position: Option<Position>,
26    },
27    Other(String),
28}
29
30impl RlError {
31    pub fn new_parse(
32        file: &str,
33        lookup: &LineColLookup,
34        error: ParseError<usize, Token, &str>,
35    ) -> Self {
36        match error {
37            ParseError::InvalidToken { location } => Self::Parse {
38                message: "invalid token".into(),
39                position: Some(Position::new(file, lookup, location)),
40                expected: Vec::new(),
41            },
42            ParseError::UnrecognizedEOF { location, expected } => Self::Parse {
43                message: "unreconized EOF".into(),
44                position: Some(Position::new(file, lookup, location)),
45                expected,
46            },
47            ParseError::UnrecognizedToken { token, expected } => Self::Parse {
48                message: format!("unreconized token '{}'", token.1),
49                position: Some(Position::new(file, lookup, token.0)),
50                expected,
51            },
52            ParseError::ExtraToken { token } => Self::Parse {
53                message: format!("extra token '{}'", token.1),
54                position: Some(Position::new(file, lookup, token.0)),
55                expected: Vec::new(),
56            },
57            ParseError::User { error } => Self::Parse {
58                message: format!("parse error '{}'", error),
59                position: None,
60                expected: Vec::new(),
61            },
62        }
63    }
64}
65
66impl std::fmt::Display for RlError {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        match self {
69            RlError::File { filename, message } => {
70                write!(f, "cannot read file {} {}", filename, message)
71            }
72            RlError::Parse {
73                message,
74                position,
75                expected,
76            } => match position {
77                Some(position) => write!(
78                    f,
79                    "parse error '{}' at {}, expecting: {:?}",
80                    message, position, expected
81                ),
82                None => write!(f, "parse error '{}', expecting: {:?}", message, expected),
83            },
84            RlError::Other(msg) => write!(f, "error: {}", msg),
85            RlError::Resolve { element, position } => {
86                if let Some(position) = position {
87                    write!(f, "unresolved {} at {}", element, position)
88                } else {
89                    write!(f, "unresolved {}", element)
90                }
91            }
92            RlError::Duplicate {
93                name,
94                first,
95                second,
96            } => match (first, second) {
97                (None, None) => write!(f, "duplicate '{}'", name),
98                (None, Some(p)) => write!(f, "duplicate '{}' at {}", name, p),
99                (Some(p), None) => write!(f, "duplicate '{}' at {}", name, p),
100                (Some(p1), Some(p2)) => write!(f, "duplicate '{}' at {} and {}", name, p1, p2),
101            },
102        }
103    }
104}