Errors - ErrorHandler now includes info about the stage that failed
This commit is contained in:
parent
da50da4e08
commit
a69fea5538
3 changed files with 36 additions and 17 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue