Skip to main content

rune_cfg/
error.rs

1// Author: Dustin Pilgrim
2// License: MIT
3
4use std::fmt;
5
6/// The main error type for RUNE parsing and lexing.
7#[derive(Debug, Clone, PartialEq)]
8pub enum RuneError {
9    SyntaxError {
10        message: String,
11        line: usize,
12        column: usize,
13        hint: Option<String>,
14        code: Option<u32>,
15    },
16    InvalidToken {
17        token: String,
18        line: usize,
19        column: usize,
20        hint: Option<String>,
21        code: Option<u32>,
22    },
23    UnexpectedEof {
24        message: String,
25        line: usize,
26        column: usize,
27        hint: Option<String>,
28        code: Option<u32>,
29    },
30    TypeError {
31        message: String,
32        line: usize,
33        column: usize,
34        hint: Option<String>,
35        code: Option<u32>,
36    },
37    /// Raised when a string literal is not closed.
38    UnclosedString {
39        quote: char,
40        line: usize,
41        column: usize,
42        hint: Option<String>,
43        code: Option<u32>,
44    },
45    /// Raised for unexpected characters or tokens.
46    UnexpectedCharacter {
47        character: char,
48        line: usize,
49        column: usize,
50        hint: Option<String>,
51        code: Option<u32>,
52    },
53    FileError {
54        message: String,
55        path: String,
56        hint: Option<String>,
57        code: Option<u32>,
58    },
59    /// Raised for runtime issues, such as missing environment variables.
60    RuntimeError {
61        message: String,
62        hint: Option<String>,
63        code: Option<u32>,
64    },
65    ValidationError {
66        message: String,
67        line: usize,
68        column: usize,
69        hint: Option<String>,
70        code: Option<u32>,
71    },
72}
73
74impl fmt::Display for RuneError {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        match self {
77            RuneError::SyntaxError { message, line, hint, code, .. } => {
78                if *line > 0 {
79                    write!(f, "[RUNE] Syntax Error at line {}: {}", line, message)?;
80                } else {
81                    write!(f, "[RUNE] Syntax Error: {}", message)?;
82                }
83                if let Some(h) = hint {
84                    write!(f, " Hint: {}", h)?;
85                }
86                if let Some(c) = code {
87                    write!(f, " Code: {}", c)?;
88                }
89                Ok(())
90            }
91            RuneError::InvalidToken { token, line, hint, code, .. } => {
92                if *line > 0 {
93                    write!(f, "[RUNE] Invalid Token '{}' at line {}", token, line)?;
94                } else {
95                    write!(f, "[RUNE] Invalid Token '{}'", token)?;
96                }
97                if let Some(h) = hint {
98                    write!(f, " Hint: {}", h)?;
99                }
100                if let Some(c) = code {
101                    write!(f, " Code: {}", c)?;
102                }
103                Ok(())
104            }
105            RuneError::UnexpectedEof { message, line, hint, code, .. } => {
106                if *line > 0 {
107                    write!(f, "[RUNE] Unexpected EOF at line {}: {}", line, message)?;
108                } else {
109                    write!(f, "[RUNE] Unexpected EOF: {}", message)?;
110                }
111                if let Some(h) = hint {
112                    write!(f, " Hint: {}", h)?;
113                }
114                if let Some(c) = code {
115                    write!(f, " Code: {}", c)?;
116                }
117                Ok(())
118            }
119            RuneError::TypeError { message, line, hint, code, .. } => {
120                if *line > 0 {
121                    write!(f, "[RUNE] Type Error at line {}: {}", line, message)?;
122                } else {
123                    write!(f, "[RUNE] Type Error: {}", message)?;
124                }
125                if let Some(h) = hint {
126                    write!(f, " Hint: {}", h)?;
127                }
128                if let Some(c) = code {
129                    write!(f, " Code: {}", c)?;
130                }
131                Ok(())
132            }
133            RuneError::UnclosedString { quote, line, hint, code, .. } => {
134                if *line > 0 {
135                    write!(f, "[RUNE] Unclosed string starting with '{}' at line {}", quote, line)?;
136                } else {
137                    write!(f, "[RUNE] Unclosed string starting with '{}'", quote)?;
138                }
139                if let Some(h) = hint {
140                    write!(f, " Hint: {}", h)?;
141                }
142                if let Some(c) = code {
143                    write!(f, " Code: {}", c)?;
144                }
145                Ok(())
146            }
147            RuneError::UnexpectedCharacter { character, line, hint, code, .. } => {
148                if *line > 0 {
149                    write!(f, "[RUNE] Unexpected character '{}' at line {}", character, line)?;
150                } else {
151                    write!(f, "[RUNE] Unexpected character '{}'", character)?;
152                }
153                if let Some(h) = hint {
154                    write!(f, " Hint: {}", h)?;
155                }
156                if let Some(c) = code {
157                    write!(f, " Code: {}", c)?;
158                }
159                Ok(())
160            }
161            RuneError::FileError { message, path, hint, code } => {
162                write!(f, "[RUNE] File Error '{}': {}", path, message)?;
163                if let Some(h) = hint {
164                    write!(f, " Hint: {}", h)?;
165                }
166                if let Some(c) = code {
167                    write!(f, " Code: {}", c)?;
168                }
169                Ok(())
170            }
171            RuneError::RuntimeError { message, hint, code } => {
172                write!(f, "[RUNE] Runtime Error: {}", message)?;
173                if let Some(h) = hint {
174                    write!(f, " Hint: {}", h)?;
175                }
176                if let Some(c) = code {
177                    write!(f, " Code: {}", c)?;
178                }
179                Ok(())
180            }
181            RuneError::ValidationError { message, hint, code, .. } => {
182                write!(f, "{}", message)?;
183                if let Some(h) = hint {
184                    write!(f, "\nHint: {}", h)?;
185                }
186                if let Some(c) = code {
187                    write!(f, " [E{}]", c)?;
188                }
189                Ok(())
190            }
191        }
192    }
193}
194
195impl std::error::Error for RuneError {}