1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use crate::core::pos::Pos;
use crate::core::span::Span;
use crate::error::error_printer::{base_report, ErrorLabel};
use crate::error::ParseError;
use ariadne::{Label, Report, ReportBuilder};
use itertools::Itertools;
use std::cmp::max;
use std::hash::Hash;
use std::mem;

#[derive(Clone, Debug)]
pub struct ErrorTree<L: Eq + Hash + Clone>(Option<L>, Vec<Self>);

impl<L: Eq + Hash + Clone> ErrorTree<L> {
    fn merge(mut self, mut other: Self) -> Self {
        if self.0.is_none() && other.0.is_none() {
            self.1.append(&mut other.1);
            self
        } else {
            ErrorTree(None, vec![self, other])
        }
    }

    fn label(self, l: L) -> Self {
        if self.0.is_none() {
            ErrorTree(Some(l), self.1)
        } else {
            ErrorTree(Some(l), vec![self])
        }
    }

    pub fn into_paths(&self) -> Vec<Vec<&L>> {
        let mut subs = self.1.iter().map(|t| t.into_paths()).concat();
        if let Some(l) = &self.0 {
            if subs.is_empty() {
                subs.push(vec![l]);
            } else {
                subs.iter_mut().for_each(|v| {
                    v.push(l);
                });
            }
        }
        subs
    }
}

/// ErrorTree keeps track of all information that it is provided, it is really verbose
#[derive(Clone)]
pub struct TreeError<'grm> {
    pub span: Span,
    pub labels: ErrorTree<ErrorLabel<'grm>>,
}

impl<'grm> TreeError<'grm> {
    fn add_label(&mut self, label: ErrorLabel<'grm>) {
        let mut tree = ErrorTree(None, vec![]);
        mem::swap(&mut self.labels, &mut tree);
        tree = tree.label(label);
        mem::swap(&mut self.labels, &mut tree);
    }
}

impl<'grm> ParseError for TreeError<'grm> {
    type L = ErrorLabel<'grm>;

    fn new(span: Span) -> Self {
        Self {
            span,
            labels: ErrorTree(None, vec![]),
        }
    }

    fn add_label_explicit(&mut self, l: Self::L) {
        self.add_label(l)
    }

    fn add_label_implicit(&mut self, l: Self::L) {
        self.add_label(l)
    }

    fn merge(mut self, other: Self) -> Self {
        assert_eq!(self.span.start, other.span.start);
        self.labels = self.labels.merge(other.labels);
        Self {
            span: Span::new(self.span.start, max(self.span.end, other.span.end)),
            labels: self.labels,
        }
    }

    fn set_end(&mut self, end: Pos) {
        self.span.end = end;
    }

    fn report(&self, enable_debug: bool) -> Report<'static, Span> {
        let mut report: ReportBuilder<Span> = base_report(self.span);

        //Add labels
        for path in self.labels.into_paths() {
            let path = path
                .iter()
                .filter(|l| enable_debug || !l.is_debug())
                .collect_vec();
            if path.is_empty() {
                continue;
            }
            let label = &path[0];

            report = report.with_label(
                Label::new(label.span())
                    .with_message(format!("{}", path.iter().format(" <- ")))
                    .with_order(-(<Pos as Into<usize>>::into(label.span().start) as i32)),
            );
        }

        report.finish()
    }
}