prism_parser/error/
error_printer.rs

1use crate::core::span::Span;
2use crate::grammar::escaped_string::EscapedString;
3use ariadne::{Color, Config, Label, LabelAttach, Report, ReportBuilder, ReportKind};
4use std::fmt::{Display, Formatter};
5
6#[derive(Eq, Hash, Clone, PartialEq)]
7pub enum ErrorLabel<'grm> {
8    Explicit(Span, EscapedString<'grm>),
9    Literal(Span, EscapedString<'grm>),
10    Debug(Span, &'grm str),
11}
12
13impl ErrorLabel<'_> {
14    pub(crate) fn span(&self) -> Span {
15        match self {
16            ErrorLabel::Explicit(s, _) => *s,
17            ErrorLabel::Literal(s, _) => *s,
18            ErrorLabel::Debug(s, _) => *s,
19        }
20    }
21
22    pub(crate) fn is_debug(&self) -> bool {
23        match self {
24            ErrorLabel::Explicit(_, _) => false,
25            ErrorLabel::Literal(_, _) => false,
26            ErrorLabel::Debug(_, _) => true,
27        }
28    }
29}
30
31impl Display for ErrorLabel<'_> {
32    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
33        match self {
34            ErrorLabel::Explicit(_, s) => write!(f, "{}", s),
35            ErrorLabel::Literal(_, s) => write!(f, "'{}'", s),
36            ErrorLabel::Debug(_, s) => write!(f, "[{}]", s),
37        }
38    }
39}
40
41pub fn base_report(span: Span) -> ReportBuilder<'static, Span> {
42    Report::build(ReportKind::Error, (), 0)
43        //Config
44        .with_config(Config::default().with_label_attach(LabelAttach::Start))
45        //Header
46        .with_message("Parsing error")
47        //Pointing label
48        .with_label(
49            Label::new(span)
50                .with_message(match span.end - span.start {
51                    0 => "Failed to parse at this location (but recovered immediately)",
52                    1 => "This character was unparsable",
53                    _ => "These characters were unparsable",
54                })
55                .with_color(Color::Red)
56                .with_priority(1)
57                .with_order(i32::MIN),
58        )
59}
60
61impl ariadne::Span for Span {
62    type SourceId = ();
63
64    fn source(&self) -> &Self::SourceId {
65        &()
66    }
67
68    fn start(&self) -> usize {
69        self.start.into()
70    }
71
72    fn end(&self) -> usize {
73        self.end.into()
74    }
75}