Improved error reports
This commit is contained in:
parent
331506af1b
commit
bbbfed7913
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -61,6 +61,15 @@ dependencies = [
|
|||
"x11rb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ariadne"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1cb2a2046bea8ce5e875551f5772024882de0b540c7f93dfc5d6cf1ca8b030c"
|
||||
dependencies = [
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic_refcell"
|
||||
version = "0.1.8"
|
||||
|
@ -1556,6 +1565,7 @@ dependencies = [
|
|||
name = "web-lisp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ariadne",
|
||||
"chumsky",
|
||||
"eframe",
|
||||
"logos",
|
||||
|
@ -1745,3 +1755,9 @@ name = "xml-rs"
|
|||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||
|
|
|
@ -6,7 +6,8 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
logos = "*"
|
||||
eframe = "*"
|
||||
ariadne = "0.1"
|
||||
chumsky = "0.8"
|
||||
eframe = "*"
|
||||
logos = "*"
|
||||
ordered-float = "3.0"
|
||||
|
|
85
src/error.rs
Normal file
85
src/error.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
use crate::lexer::Token;
|
||||
use ariadne::{Color, Fmt, Label, Report, ReportKind, Source};
|
||||
use chumsky::error::{Simple, SimpleReason};
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Error<'a> {
|
||||
Parse(Simple<Token<'a>>),
|
||||
}
|
||||
|
||||
impl<'a> Error<'a> {
|
||||
pub fn report(&self, src: &str) -> std::io::Result<()> {
|
||||
match self {
|
||||
Error::Parse(e) => {
|
||||
let report =
|
||||
Report::<std::ops::Range<usize>>::build(ReportKind::Error, (), e.span().start);
|
||||
match e.reason() {
|
||||
SimpleReason::Unexpected => report
|
||||
.with_message(match e.found() {
|
||||
Some(Token::Error) => {
|
||||
format!("Invalid token: {}", &src[e.span()].fg(Color::Yellow))
|
||||
}
|
||||
Some(t) => format!("Unexpected token `{t:?}`"),
|
||||
None => "Unexpected end of input".to_owned(),
|
||||
})
|
||||
.with_label(
|
||||
Label::new(e.span())
|
||||
.with_message(format!(
|
||||
"Expected: {}",
|
||||
e.expected()
|
||||
.map(|exp| match exp {
|
||||
Some(expected) => format!("{expected:?}"),
|
||||
None => "end of input".to_owned(),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
))
|
||||
.with_color(Color::Red),
|
||||
),
|
||||
SimpleReason::Unclosed { span, delimiter } => {
|
||||
let msg = format!(
|
||||
"Unclosed delimiter: {:?}",
|
||||
format!("{delimiter:?}").fg(Color::Yellow)
|
||||
);
|
||||
report
|
||||
.with_message(&msg)
|
||||
.with_label(
|
||||
Label::new(span.clone())
|
||||
.with_message(msg)
|
||||
.with_color(Color::Red),
|
||||
)
|
||||
.with_label(
|
||||
Label::new(e.span())
|
||||
.with_message(format!(
|
||||
"Must be closed before {}",
|
||||
match e.found() {
|
||||
Some(x) => format!("{x:?}"),
|
||||
None => "the end of input".to_owned(),
|
||||
}
|
||||
))
|
||||
.with_color(Color::Yellow),
|
||||
)
|
||||
}
|
||||
SimpleReason::Custom(msg) => report.with_message(msg).with_label(
|
||||
Label::new(e.span())
|
||||
.with_message(msg.fg(Color::Red))
|
||||
.with_color(Color::Red),
|
||||
),
|
||||
}
|
||||
.finish()
|
||||
.print(Source::from(&src))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Display for Error<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Error::Parse(e) => write!(f, "{e:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> std::error::Error for Error<'a> {}
|
|
@ -1,3 +1,4 @@
|
|||
pub mod error;
|
||||
pub mod lexer;
|
||||
pub mod list;
|
||||
pub mod parser;
|
||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -1,17 +1,21 @@
|
|||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
use web_lisp::parser;
|
||||
use web_lisp::{error::Error, parser};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
match parser::read(&std::fs::read_to_string(
|
||||
std::env::args().nth(1).ok_or("no filename provided")?,
|
||||
)?) {
|
||||
let src = std::fs::read_to_string(std::env::args().nth(1).ok_or("no filename provided")?)?;
|
||||
|
||||
match parser::read(&src) {
|
||||
Ok(vals) => {
|
||||
for val in vals {
|
||||
println!("{val}");
|
||||
}
|
||||
}
|
||||
Err(e) => eprintln!("Parse error: {e:?}"),
|
||||
Err(errs) => {
|
||||
for err in errs {
|
||||
Error::Parse(err).report(&src)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in a new issue