ludus/src/errors.rs

93 lines
3.2 KiB
Rust
Raw Normal View History

// use crate::process::{LErr, Trace};
use crate::lexer::Token;
2024-12-13 00:01:51 +00:00
use crate::validator::VErr;
use chumsky::error::RichPattern;
use chumsky::prelude::*;
2024-12-13 00:01:51 +00:00
const SEPARATOR: &str = "\n\n";
2024-12-13 00:01:51 +00:00
fn line_number(src: &'static str, span: SimpleSpan) -> usize {
src.chars().take(span.start).filter(|c| *c == '\n').count()
}
fn get_line(src: &'static str, line: usize) -> String {
src.split("\n").nth(line).unwrap().to_string()
}
pub fn lexing(errs: Vec<Rich<'static, char>>, src: &'static str, input: &'static str) -> String {
let mut msgs = vec!["Ludus found some errors.".to_string()];
for err in errs {
let mut msg = vec![];
let line_number = line_number(src, *err.span());
let line = get_line(src, line_number);
let char = src.chars().nth(err.span().start).unwrap();
msg.push(format!("Syntax error: unexpected {char}"));
msg.push(format!(" on line {} in {}", line_number + 1, input));
msg.push(format!(" >>> {line}"));
msgs.push(msg.join("\n"));
}
msgs.join(SEPARATOR)
}
pub fn validation(errs: Vec<VErr>) -> String {
let mut msgs = vec!["Ludus found some errors.".to_string()];
for err in errs {
let mut msg = vec![];
let line_number = line_number(err.src, *err.span);
let line = get_line(err.src, line_number);
msg.push(format!("Validation error: {}", err.msg));
msg.push(format!(" on line {} in {}", line_number + 1, err.input));
msg.push(format!(" >>> {line}"));
msgs.push(msg.join("\n"));
}
msgs.join(SEPARATOR)
}
pub fn parsing(errs: Vec<Rich<'static, Token>>, src: &'static str, input: &'static str) -> String {
let mut msgs = vec!["Ludus found some errors.".to_string()];
2024-12-13 00:01:51 +00:00
for err in errs {
let mut msg = vec![];
let line_number = line_number(src, *err.span());
let line = get_line(src, line_number);
let details = parsing_message(err);
msg.push(format!("Syntax error: {}", details));
msg.push(format!(" on line {} in {}", line_number + 1, input));
msg.push(format!(" >>> {line}"));
msgs.push(msg.join("\n"))
2024-12-13 00:01:51 +00:00
}
msgs.join(SEPARATOR)
}
fn parsing_message(err: Rich<'static, Token>) -> String {
let found = match err.found() {
Some(token) => token.show(),
None => "end of input".to_string(),
};
let expected = err.expected();
let mut expecteds = vec![];
for pattern in expected {
let shown = match pattern {
RichPattern::Token(t) => t.show(),
RichPattern::Label(s) => s.to_string(),
RichPattern::Identifier(s) => s.clone(),
RichPattern::Any => "any".to_string(),
RichPattern::SomethingElse => "something else".to_string(),
RichPattern::EndOfInput => "eof".to_string(),
};
expecteds.push(shown);
}
let expecteds = if expecteds.iter().any(|e| e == &"else".to_string()) {
vec!["else".to_string()]
} else {
expecteds
};
let expecteds = if expecteds.iter().any(|e| e == &"then".to_string()) {
vec!["then".to_string()]
} else {
expecteds
};
let expecteds = expecteds.join(" | ");
format!("Ludus did not expect to see: {found}\n expected: {expecteds}")
2024-12-13 00:01:51 +00:00
}