Add fancy errors

This commit is contained in:
Jeff 2024-03-06 16:24:48 -05:00
parent 13394e6a8f
commit da5122358e
2 changed files with 34 additions and 42 deletions

View File

@ -1,53 +1,21 @@
use std::sync::PoisonError; use std::sync::PoisonError;
use ariadne::{Color, Label, Report, ReportKind}; use ariadne::{Label, Report, ReportKind};
use chumsky::{prelude::Rich, span::SimpleSpan}; use chumsky::{prelude::Rich, span::SimpleSpan};
use crate::{abstract_tree::Type, lexer::Token}; use crate::{abstract_tree::Type, lexer::Token};
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum Error { pub enum Error {
Parse { Parse { expected: String, span: SimpleSpan },
expected: String, Lex { expected: String, span: SimpleSpan },
found: Option<String>,
span: SimpleSpan,
},
Lex {
expected: String,
found: Option<char>,
span: SimpleSpan,
},
Runtime(RuntimeError), Runtime(RuntimeError),
} }
impl Error {
pub fn report(&self, source: &str) -> Report {
match self {
Error::Parse {
expected,
found,
span,
} => Report::build(ReportKind::Custom("Parsing Error", Color::Red), (), 0).finish(),
Error::Lex {
expected,
found,
span,
} => Report::build(ReportKind::Custom("Lexing Error", Color::Red), (), 0)
.with_label(Label::new(span.start..span.end).with_message(format!(
"Exptected {expected} but found {}.",
found.unwrap_or(' '),
)))
.finish(),
Error::Runtime(_) => todo!(),
}
}
}
impl From<Rich<'_, char>> for Error { impl From<Rich<'_, char>> for Error {
fn from(error: Rich<'_, char>) -> Self { fn from(error: Rich<'_, char>) -> Self {
Error::Lex { Error::Lex {
expected: error.expected().map(|error| error.to_string()).collect(), expected: error.expected().map(|error| error.to_string()).collect(),
found: error.reason().found().map(|c| c.clone()),
span: error.span().clone(), span: error.span().clone(),
} }
} }
@ -57,7 +25,6 @@ impl<'src> From<Rich<'_, Token<'src>>> for Error {
fn from(error: Rich<'_, Token<'src>>) -> Self { fn from(error: Rich<'_, Token<'src>>) -> Self {
Error::Parse { Error::Parse {
expected: error.expected().map(|error| error.to_string()).collect(), expected: error.expected().map(|error| error.to_string()).collect(),
found: error.reason().found().map(|c| c.to_string()),
span: error.span().clone(), span: error.span().clone(),
} }
} }
@ -120,3 +87,30 @@ pub struct TypeCheckError {
pub actual: Type, pub actual: Type,
pub expected: Type, pub expected: Type,
} }
pub fn create_report<'a>(errors: &'a [Error]) -> Report<'a> {
let mut report = Report::build(ReportKind::Error, (), 0);
for error in errors {
match error {
Error::Parse { expected, span } => {
report = report.with_label(
Label::new(span.start..span.end).with_message(format!("Expected {expected}.")),
);
}
Error::Lex { expected, span } => {
let expected = match expected.as_str() {
"" => "something else",
expected => expected,
};
report = report.with_label(
Label::new(span.start..span.end).with_message(format!("Expected {expected}.")),
);
}
Error::Runtime(_) => todo!(),
}
}
report.finish()
}

View File

@ -6,7 +6,7 @@ use colored::Colorize;
use std::{fs::read_to_string, io::Write}; use std::{fs::read_to_string, io::Write};
use dust_lang::{context::Context, Interpreter}; use dust_lang::{context::Context, error::create_report, Interpreter};
/// Command-line arguments to be parsed. /// Command-line arguments to be parsed.
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -52,10 +52,8 @@ fn main() {
println!("{value}") println!("{value}")
} }
} }
Err(errors) => { Err(errors) => create_report(&errors)
for error in errors { .eprint(Source::from(&source))
error.report(&source).eprint(Source::from(&source)).unwrap(); .unwrap(),
}
}
} }
} }