88 lines
2.5 KiB
Rust
88 lines
2.5 KiB
Rust
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 {
|
|
eprintln!("e: {err:?}");
|
|
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);
|