prism_parser/error/
set_error.rs1use crate::core::pos::Pos;
2use crate::core::span::Span;
3use crate::error::error_printer::{base_report, ErrorLabel};
4use crate::error::ParseError;
5use ariadne::{Label, Report};
6use std::cmp::max;
7use std::collections::{BTreeMap, HashSet};
8
9#[derive(Clone)]
11pub struct SetError<'grm> {
12    pub span: Span,
13    pub labels: HashSet<ErrorLabel<'grm>>,
14    pub explicit: bool,
15}
16
17impl<'grm> ParseError for SetError<'grm> {
18    type L = ErrorLabel<'grm>;
19
20    fn new(span: Span) -> Self {
21        Self {
22            span,
23            labels: HashSet::new(),
24            explicit: false,
25        }
26    }
27
28    fn add_label_explicit(&mut self, label: Self::L) {
29        if !self.explicit {
30            self.explicit = true;
31            self.labels.clear();
32        }
33        self.labels.insert(label);
34    }
35
36    fn add_label_implicit(&mut self, label: Self::L) {
37        if self.explicit {
38            return;
39        }
40        self.labels.insert(label);
41    }
42
43    fn merge(mut self, other: Self) -> Self {
44        assert_eq!(self.span.start, other.span.start);
45        for e in other.labels {
46            self.labels.insert(e);
47        }
48        Self {
49            span: Span::new(self.span.start, max(self.span.end, other.span.end)),
50            labels: self.labels,
51            explicit: self.explicit || other.explicit,
52        }
53    }
54
55    fn set_end(&mut self, end: Pos) {
56        self.span.end = end;
57    }
58
59    fn report(&self, enable_debug: bool) -> Report<'static, Span> {
60        let mut report = base_report(self.span);
61
62        let mut labels_map: BTreeMap<Pos, Vec<_>> = BTreeMap::new();
63        for l in self.labels.iter().filter(|l| enable_debug || !l.is_debug()) {
64            labels_map.entry(l.span().start).or_default().push(l);
65        }
66
67        for (start, labels) in labels_map {
69            report = report.with_label(
70                Label::new(start.span_to(start))
71                    .with_message(format!(
72                        "Tried parsing {}",
73                        labels
74                            .iter()
75                            .map(|v| v.to_string())
76                            .collect::<Vec<_>>()
77                            .join(" / ")
78                    ))
79                    .with_order(-(<Pos as Into<usize>>::into(start) as i32)),
80            );
81        }
82
83        report.finish()
84    }
85}