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}