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};
|
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
|
/// Error handler. Can be used to print error messages; will also retain the
|
||||||
/// current error status.
|
/// current error status.
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct ErrorHandler {
|
pub struct ErrorHandler {
|
||||||
had_error: bool,
|
had_error: Option<ErrorType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ErrorHandler {
|
impl ErrorHandler {
|
||||||
/// Check whether this handler reported an error.
|
/// Check whether this handler reported an error.
|
||||||
pub fn had_error(&self) -> bool {
|
pub fn had_error(&self) -> Option<ErrorType> {
|
||||||
self.had_error
|
self.had_error
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Report an error.
|
/// Report an error.
|
||||||
pub fn error(&mut self, line: usize, message: &str) {
|
pub fn error(&mut self, err_type: ErrorType, line: usize, message: &str) {
|
||||||
self.report(line, "", message)
|
self.report(err_type, line, "", message)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report(&mut self, line: usize, pos: &str, message: &str) {
|
fn report(&mut self, err_type: ErrorType, line: usize, pos: &str, message: &str) {
|
||||||
self.had_error = true;
|
if self.had_error.is_none() {
|
||||||
|
self.had_error = Option::Some(err_type);
|
||||||
|
}
|
||||||
println!("[line {line}] Error{pos}: {message}")
|
println!("[line {line}] Error{pos}: {message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,11 +60,10 @@ impl ParserError {
|
||||||
|
|
||||||
/// Report the error to an error handler.
|
/// Report the error to an error handler.
|
||||||
pub fn report(&self, err_hdl: &mut ErrorHandler) {
|
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.
|
/// An error that occurred while trying to evaluate the code.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct InterpreterError {
|
pub struct InterpreterError {
|
||||||
|
@ -72,6 +82,6 @@ impl InterpreterError {
|
||||||
|
|
||||||
/// Report the error to an error handler.
|
/// Report the error to an error handler.
|
||||||
pub fn report(&self, err_hdl: &mut ErrorHandler) {
|
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 ast::AstDumper;
|
||||||
use errors::ErrorHandler;
|
use errors::{ErrorHandler, ErrorType};
|
||||||
use interpreter::evaluate;
|
use interpreter::evaluate;
|
||||||
use parser::Parser;
|
use parser::Parser;
|
||||||
use scanner::Scanner;
|
use scanner::Scanner;
|
||||||
|
@ -72,13 +72,16 @@ fn main() -> Result<(), ExitCode> {
|
||||||
let args: Vec<String> = env::args().skip(1).collect();
|
let args: Vec<String> = env::args().skip(1).collect();
|
||||||
let n_args = args.len();
|
let n_args = args.len();
|
||||||
if n_args == 0 {
|
if n_args == 0 {
|
||||||
run_prompt()
|
run_prompt();
|
||||||
|
Ok(())
|
||||||
} else if n_args == 1 {
|
} else if n_args == 1 {
|
||||||
if run_file(&args[0]).had_error() {
|
match run_file(&args[0]).had_error() {
|
||||||
return Err(ExitCode::from(65));
|
None => Ok(()),
|
||||||
|
Some(ErrorType::Parse) => Err(ExitCode::from(65)),
|
||||||
|
Some(ErrorType::Runtime) => Err(ExitCode::from(70)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("Usage: slox [script]");
|
println!("Usage: slox [script]");
|
||||||
|
Err(ExitCode::from(1))
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::collections::HashMap;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
errors::ErrorType,
|
||||||
tokens::{Token, TokenType},
|
tokens::{Token, TokenType},
|
||||||
ErrorHandler,
|
ErrorHandler,
|
||||||
};
|
};
|
||||||
|
@ -135,7 +136,11 @@ impl Scanner {
|
||||||
// Identifiers
|
// Identifiers
|
||||||
ch if ch.is_ascii_alphabetic() => self.identifier(),
|
ch if ch.is_ascii_alphabetic() => self.identifier(),
|
||||||
// Anything else is an error
|
// 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() {
|
if self.is_at_end() {
|
||||||
err_hdl.error(self.line, "unterminated string");
|
err_hdl.error(ErrorType::Parse, self.line, "unterminated string");
|
||||||
} else {
|
} else {
|
||||||
self.current += 1; // Last '"'
|
self.current += 1; // Last '"'
|
||||||
let value = self.get_substring(self.start + 1, self.current - 1);
|
let value = self.get_substring(self.start + 1, self.current - 1);
|
||||||
|
@ -177,6 +182,7 @@ impl Scanner {
|
||||||
match tok_string.parse::<f64>() {
|
match tok_string.parse::<f64>() {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
err_hdl.error(
|
err_hdl.error(
|
||||||
|
ErrorType::Parse,
|
||||||
self.line,
|
self.line,
|
||||||
&format!(
|
&format!(
|
||||||
"Could not parse {} as a floating point number: {:?}",
|
"Could not parse {} as a floating point number: {:?}",
|
||||||
|
@ -207,7 +213,7 @@ impl Scanner {
|
||||||
let mut depth = 1;
|
let mut depth = 1;
|
||||||
loop {
|
loop {
|
||||||
if self.is_at_end() {
|
if self.is_at_end() {
|
||||||
err_hdl.error(self.line, "unterminated block comment");
|
err_hdl.error(ErrorType::Parse, self.line, "unterminated block comment");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue