Errors - ErrorHandler now includes info about the stage that failed

This commit is contained in:
Emmanuel BENOîT 2022-12-31 14:00:23 +01:00
parent da50da4e08
commit a69fea5538
3 changed files with 36 additions and 17 deletions

View file

@ -1,25 +1,36 @@
use crate::tokens::{Token, TokenType};
/// The type of an error.
#[derive(Clone, Copy, Debug)]
pub enum ErrorType {
/// The error occurred while parsing the source code.
Parse,
/// The error occurred while trying to run the program.
Runtime,
}
/// Error handler. Can be used to print error messages; will also retain the
/// current error status.
#[derive(Default, Debug)]
pub struct ErrorHandler {
had_error: bool,
had_error: Option<ErrorType>,
}
impl ErrorHandler {
/// Check whether this handler reported an error.
pub fn had_error(&self) -> bool {
pub fn had_error(&self) -> Option<ErrorType> {
self.had_error
}
/// Report an error.
pub fn error(&mut self, line: usize, message: &str) {
self.report(line, "", message)
pub fn error(&mut self, err_type: ErrorType, line: usize, message: &str) {
self.report(err_type, line, "", message)
}
fn report(&mut self, line: usize, pos: &str, message: &str) {
self.had_error = true;
fn report(&mut self, err_type: ErrorType, line: usize, pos: &str, message: &str) {
if self.had_error.is_none() {
self.had_error = Option::Some(err_type);
}
println!("[line {line}] Error{pos}: {message}")
}
}
@ -49,11 +60,10 @@ impl ParserError {
/// Report the error to an error handler.
pub fn report(&self, err_hdl: &mut ErrorHandler) {
err_hdl.report(self.line, &self.pos, &self.message);
err_hdl.report(ErrorType::Parse, self.line, &self.pos, &self.message);
}
}
/// An error that occurred while trying to evaluate the code.
#[derive(Debug, Clone)]
pub struct InterpreterError {
@ -72,6 +82,6 @@ impl InterpreterError {
/// Report the error to an error handler.
pub fn report(&self, err_hdl: &mut ErrorHandler) {
err_hdl.report(self.line, "", &self.message);
err_hdl.report(ErrorType::Runtime, self.line, "", &self.message);
}
}

View file

@ -12,7 +12,7 @@ use std::{
};
use ast::AstDumper;
use errors::ErrorHandler;
use errors::{ErrorHandler, ErrorType};
use interpreter::evaluate;
use parser::Parser;
use scanner::Scanner;
@ -72,13 +72,16 @@ fn main() -> Result<(), ExitCode> {
let args: Vec<String> = env::args().skip(1).collect();
let n_args = args.len();
if n_args == 0 {
run_prompt()
run_prompt();
Ok(())
} else if n_args == 1 {
if run_file(&args[0]).had_error() {
return Err(ExitCode::from(65));
match run_file(&args[0]).had_error() {
None => Ok(()),
Some(ErrorType::Parse) => Err(ExitCode::from(65)),
Some(ErrorType::Runtime) => Err(ExitCode::from(70)),
}
} else {
println!("Usage: slox [script]");
Err(ExitCode::from(1))
}
Ok(())
}

View file

@ -3,6 +3,7 @@ use std::collections::HashMap;
use lazy_static::lazy_static;
use crate::{
errors::ErrorType,
tokens::{Token, TokenType},
ErrorHandler,
};
@ -135,7 +136,11 @@ impl Scanner {
// Identifiers
ch if ch.is_ascii_alphabetic() => self.identifier(),
// Anything else is an error
ch => err_hdl.error(self.line, &format!("unexpected character {:#?}", ch)),
ch => err_hdl.error(
ErrorType::Parse,
self.line,
&format!("unexpected character {:#?}", ch),
),
}
}
@ -153,7 +158,7 @@ impl Scanner {
}
if self.is_at_end() {
err_hdl.error(self.line, "unterminated string");
err_hdl.error(ErrorType::Parse, self.line, "unterminated string");
} else {
self.current += 1; // Last '"'
let value = self.get_substring(self.start + 1, self.current - 1);
@ -177,6 +182,7 @@ impl Scanner {
match tok_string.parse::<f64>() {
Err(e) => {
err_hdl.error(
ErrorType::Parse,
self.line,
&format!(
"Could not parse {} as a floating point number: {:?}",
@ -207,7 +213,7 @@ impl Scanner {
let mut depth = 1;
loop {
if self.is_at_end() {
err_hdl.error(self.line, "unterminated block comment");
err_hdl.error(ErrorType::Parse, self.line, "unterminated block comment");
return;
}