lwb_parser/parser/peg/
parse_error.rs1use crate::parser::peg::parser_core_expression::ExpressionContext;
2use crate::sources::character_class::CharacterClass;
3use crate::sources::span::Span;
4use itertools::Itertools;
5use miette::{Diagnostic, LabeledSpan, Severity, SourceCode};
6use std::cmp::Ordering;
7use std::fmt::{Display, Formatter};
8use thiserror::Error;
9
10#[derive(Debug, Clone, Error)]
14#[error("A parse error occured!")]
15pub struct PEGParseError {
16 pub span: Span,
17 pub expected: Vec<Expect>,
18 pub fail_left_rec: bool,
19 pub fail_loop: bool,
20 pub msgs: Vec<(String, String)>,
22}
23
24impl Diagnostic for PEGParseError
26where
27 PEGParseError: std::error::Error,
28{
29 fn severity(&self) -> Option<Severity> {
34 Some(Severity::Error)
35 }
36
37 fn source_code(&self) -> Option<&dyn SourceCode> {
39 Some(&self.span)
40 }
41
42 fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
44 if let Some(i) = self
46 .expected
47 .iter()
48 .find(|i| matches!(i, Expect::Custom(_)))
49 {
50 let label = LabeledSpan::new_with_span(Some(i.to_string()), self.span.clone());
51
52 return Some(Box::new(vec![label].into_iter()));
53 }
54
55 let expect_str = self.expected.iter().map(|exp| exp.to_string()).join(", ");
56 let mut labels = vec![];
57
58 if self.fail_left_rec {
60 labels.push(LabeledSpan::new_with_span(Some("Encountered left recursion here. This is a problem with the grammar, and may hide other errors.".to_string()), self.span.clone()));
61 }
62
63 if self.fail_loop {
65 labels.push(LabeledSpan::new_with_span(Some("Encountered an infinite loop here. This is a problem with the grammar, and may hide other errors.".to_string()), self.span.clone()));
66 }
67
68 match self.expected.len() {
70 0 => {}
71 1 => labels.push(LabeledSpan::new_with_span(
72 Some(format!("Expected {} here", expect_str)),
73 self.span.clone(),
74 )),
75 _ => labels.push(LabeledSpan::new_with_span(
76 Some(format!("Expected one of {} here", expect_str)),
77 self.span.clone(),
78 )),
79 }
80
81 Some(Box::new(labels.into_iter()))
82 }
83
84 fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
85 let mut helps = Vec::new();
86 for (sort, msg) in &self.msgs {
87 helps.push(format!("if a {sort} would be parsed here then {msg}"));
88 }
89
90 if helps.is_empty() {
91 None
92 } else {
93 Some(Box::new(helps.join("\n")))
94 }
95 }
96}
97
98impl PEGParseError {
99 pub fn expect(span: Span, expect: Expect, sort_context: &ExpressionContext) -> Self {
100 PEGParseError {
101 span,
102 expected: vec![expect],
103 fail_left_rec: false,
104 fail_loop: false,
105 msgs: if let Some(name) = sort_context.name {
106 sort_context
107 .error
108 .iter()
109 .map(|i| (name.to_string(), i.to_string()))
110 .collect()
111 } else {
112 vec![]
113 },
114 }
115 }
116
117 pub fn fail_left_recursion(span: Span) -> Self {
118 PEGParseError {
119 span,
120 expected: vec![],
121 fail_left_rec: true,
122 fail_loop: false,
123 msgs: vec![],
124 }
125 }
126
127 pub fn fail_loop(span: Span) -> Self {
128 PEGParseError {
129 span,
130 expected: vec![],
131 fail_left_rec: false,
132 fail_loop: true,
133 msgs: vec![],
134 }
135 }
136}
137
138#[derive(Debug, Clone, Hash, Eq, PartialEq)]
140pub enum Expect {
141 ExpectCharClass(CharacterClass),
143
144 ExpectString(String),
146
147 ExpectSort(String),
149
150 NotEntireInput(),
152
153 Custom(String),
155}
156
157impl Display for Expect {
158 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
159 match self {
160 Expect::ExpectCharClass(cc) => {
161 write!(f, "{}", cc)
162 }
163 Expect::ExpectString(s) => {
164 write!(f, "\'{}\'", s)
165 }
166 Expect::ExpectSort(s) => {
167 write!(f, "{}", s)
168 }
169 Expect::NotEntireInput() => {
170 write!(f, "more input")
171 }
172 Expect::Custom(e) => {
173 write!(f, "{e}")
174 }
175 }
176 }
177}
178
179impl PEGParseError {
180 pub fn combine(mut self, mut other: PEGParseError) -> PEGParseError {
186 assert_eq!(self.span.source.name(), other.span.source.name());
187
188 match self.span.position.cmp(&other.span.position) {
190 Ordering::Less => other,
191 Ordering::Greater => self,
192 Ordering::Equal => {
193 self.span.length = self.span.length.max(other.span.length);
195 self.expected.append(&mut other.expected);
197 self.fail_left_rec |= other.fail_left_rec;
199
200 self.msgs.extend(other.msgs);
201
202 self
203 }
204 }
205 }
206
207 pub fn combine_option_parse_error(
210 a: Option<PEGParseError>,
211 b: Option<PEGParseError>,
212 ) -> Option<PEGParseError> {
213 match (a, b) {
214 (None, None) => None,
215 (None, Some(e)) => Some(e),
216 (Some(e), None) => Some(e),
217 (Some(e1), Some(e2)) => Some(e1.combine(e2)),
218 }
219 }
220}