use crate::tokens::{Token, TokenType};
pub struct ErrorHandler {
pub had_errors: bool,
pub had_runtime_error: bool,
pub errors: Vec<String>,
}
impl ErrorHandler {
pub fn new() -> Self {
Self {
had_errors: false,
had_runtime_error: false,
errors: Vec::new(),
}
}
pub fn reset(&mut self) {
self.had_errors = false;
self.had_runtime_error = false;
self.errors = Vec::new()
}
pub fn merge(&mut self, other: &ErrorHandler) {
self.had_errors |= other.had_errors;
self.had_runtime_error |= other.had_runtime_error;
for err in &other.errors {
self.errors.push(err.clone());
}
}
pub fn error(&mut self, line: usize, msg: &str) {
self.report(line, "", msg);
}
pub fn error_token(&mut self, token: &Token, msg: &str) {
if token.token_type == TokenType::Eof {
self.report(token.line, "at end", msg);
} else if token.token_type == TokenType::Newline {
self.report(token.line - 1, "at newline", msg);
} else {
self.report(token.line, &format!("at '{}'", token.lexeme), msg);
}
}
pub fn runtime_error_token(&mut self, token: Token, msg: &str) {
self.had_runtime_error = true;
self.errors.push(format!("{}\n[line {}]", msg, token.line));
}
pub fn runtime_error(&mut self, line: usize, msg: &str) {
self.had_runtime_error = true;
self.report(line, "", msg);
}
fn report(&mut self, line: usize, location: &str, msg: &str) {
self.had_errors = true;
self.errors
.push(format!("[line {}] Error {}: {}", line, location, msg));
}
}
impl Default for ErrorHandler {
fn default() -> Self {
Self::new()
}
}