prism_parser/error/
tree_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, 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#[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 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}