mirror of
https://forge.katzen.cafe/katzen-cafe/iowo.git
synced 2025-09-24 23:41:30 +02:00
lang: funky basic error reporting stuff
This commit is contained in:
parent
ae60db7721
commit
84448af714
8 changed files with 122 additions and 18 deletions
87
crates/lang/src/err_reporting.rs
Normal file
87
crates/lang/src/err_reporting.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
use std::{collections::HashMap, fs};
|
||||
|
||||
use ariadne::{sources, Label, Report, Source};
|
||||
use chumsky::{
|
||||
error::{self, Rich},
|
||||
ParseResult,
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use crate::{
|
||||
parser::{ast::File, Span},
|
||||
tokens::Token,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Stage {
|
||||
Lex,
|
||||
Parse,
|
||||
}
|
||||
|
||||
impl Stage {
|
||||
fn variants() -> [Stage; 2] {
|
||||
[Stage::Lex, Stage::Parse]
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ErrorCollector<'filename, 'tokens, 'src> {
|
||||
files: HashMap<&'filename str, &'src str>,
|
||||
raw_errors: IndexMap<(&'filename str, Stage), Vec<error::Rich<'tokens, Token<'src>, Span>>>,
|
||||
}
|
||||
|
||||
impl<'filename, 'tokens, 'src> ErrorCollector<'filename, 'tokens, 'src> {
|
||||
pub fn new(files: Vec<(&'filename str, &'src str)>) -> Self {
|
||||
Self {
|
||||
files: HashMap::from_iter(files.clone()),
|
||||
raw_errors: files
|
||||
.iter()
|
||||
.flat_map(|(name, _)| Stage::variants().map(|s| (name, s)))
|
||||
.map(|(name, stage)| ((*name, stage), Vec::new()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_many(
|
||||
&mut self,
|
||||
file: &'filename str,
|
||||
curr_stage: Stage,
|
||||
mut errs: Vec<error::Rich<'tokens, Token<'src>, Span>>,
|
||||
) {
|
||||
let err_vec = self
|
||||
.raw_errors
|
||||
.get_mut(&(file, curr_stage))
|
||||
.expect("filename should exist");
|
||||
err_vec.append(&mut errs);
|
||||
}
|
||||
|
||||
pub fn analyze_and_report(self) {
|
||||
let ErrorCollector { files, raw_errors } = self;
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn report_raw(self) {
|
||||
let ErrorCollector { files, raw_errors } = self;
|
||||
|
||||
for ((file, stage), errs) in raw_errors.into_iter() {
|
||||
for err in errs {
|
||||
Report::build(ariadne::ReportKind::Error, file, err.span().start)
|
||||
.with_message(format!("error at stage {stage:?}, {:?}", err.reason()))
|
||||
.with_label(
|
||||
Label::new((file, err.span().into_range())).with_message(format!(
|
||||
"found: {:?}",
|
||||
err.found().expect("errors should have a reason")
|
||||
)),
|
||||
)
|
||||
.with_help(format!(
|
||||
"expected: {:?}",
|
||||
err.expected().collect::<Vec<_>>()
|
||||
))
|
||||
.finish()
|
||||
.print((file, Source::from(files[file])));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct Loc<'filename>(&'filename str, Span);
|
Loading…
Add table
Add a link
Reference in a new issue