Add fancy errors
This commit is contained in:
parent
13394e6a8f
commit
da5122358e
66
src/error.rs
66
src/error.rs
@ -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()
|
||||||
|
}
|
||||||
|
10
src/main.rs
10
src/main.rs
@ -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(),
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user