prism_parser/error/
tree_error.rs

1use 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, ReportBuilder};
6use std::cmp::max;
7use std::hash::Hash;
8use std::mem;
9
10#[derive(Clone, Debug)]
11pub struct ErrorTree<L: Eq + Hash + Clone>(Option<L>, Vec<Self>);
12
13impl<L: Eq + Hash + Clone> ErrorTree<L> {
14    fn merge(mut self, mut other: Self) -> Self {
15        if self.0.is_none() && other.0.is_none() {
16            self.1.append(&mut other.1);
17            self
18        } else {
19            ErrorTree(None, vec![self, other])
20        }
21    }
22
23    fn label(self, l: L) -> Self {
24        if self.0.is_none() {
25            ErrorTree(Some(l), self.1)
26        } else {
27            ErrorTree(Some(l), vec![self])
28        }
29    }
30
31    pub fn into_paths(&self) -> Vec<Vec<&L>> {
32        let mut subs = self
33            .1
34            .iter()
35            .flat_map(|t| t.into_paths())
36            .collect::<Vec<_>>();
37        if let Some(l) = &self.0 {
38            if subs.is_empty() {
39                subs.push(vec![l]);
40            } else {
41                subs.iter_mut().for_each(|v| {
42                    v.push(l);
43                });
44            }
45        }
46        subs
47    }
48}
49
50/// ErrorTree keeps track of all information that it is provided, it is really verbose
51#[derive(Clone)]
52pub struct TreeError<'grm> {
53    pub span: Span,
54    pub labels: ErrorTree<ErrorLabel<'grm>>,
55}
56
57impl<'grm> TreeError<'grm> {
58    fn add_label(&mut self, label: ErrorLabel<'grm>) {
59        let mut tree = ErrorTree(None, vec![]);
60        mem::swap(&mut self.labels, &mut tree);
61        tree = tree.label(label);
62        mem::swap(&mut self.labels, &mut tree);
63    }
64}
65
66impl<'grm> ParseError for TreeError<'grm> {
67    type L = ErrorLabel<'grm>;
68
69    fn new(span: Span) -> Self {
70        Self {
71            span,
72            labels: ErrorTree(None, vec![]),
73        }
74    }
75
76    fn add_label_explicit(&mut self, l: Self::L) {
77        self.add_label(l)
78    }
79
80    fn add_label_implicit(&mut self, l: Self::L) {
81        self.add_label(l)
82    }
83
84    fn merge(mut self, other: Self) -> Self {
85        assert_eq!(self.span.start, other.span.start);
86        self.labels = self.labels.merge(other.labels);
87        Self {
88            span: Span::new(self.span.start, max(self.span.end, other.span.end)),
89            labels: self.labels,
90        }
91    }
92
93    fn set_end(&mut self, end: Pos) {
94        self.span.end = end;
95    }
96
97    fn report(&self, enable_debug: bool) -> Report<'static, Span> {
98        let mut report: ReportBuilder<Span> = base_report(self.span);
99
100        //Add labels
101        for path in self.labels.into_paths() {
102            let path = path
103                .iter()
104                .filter(|l| enable_debug || !l.is_debug())
105                .collect::<Vec<_>>();
106            if path.is_empty() {
107                continue;
108            }
109            let label = &path[0];
110
111            report = report.with_label(
112                Label::new(label.span())
113                    .with_message(
114                        path.iter()
115                            .map(|v| v.to_string())
116                            .collect::<Vec<_>>()
117                            .join(" <- ")
118                            .to_string(),
119                    )
120                    .with_order(-(<Pos as Into<usize>>::into(label.span().start) as i32)),
121            );
122        }
123
124        report.finish()
125    }
126}