1use std::{borrow::Cow, fmt};
2
3use crate::{InputLocation, InputRange, Span};
4
5pub type ParserResult<T> = ::std::result::Result<Span<T>, ParsingError>;
10
11#[derive(Debug)]
13pub struct ParsingError {
14 inner: ParsingErrorInner,
16
17 atomic_error: Option<&'static str>,
19
20 critical: Option<Cow<'static, str>>,
22}
23
24impl ParsingError {
25 pub const fn new(inner: ParsingErrorInner) -> Self {
27 Self {
28 inner,
29 atomic_error: None,
30 critical: None,
31 }
32 }
33
34 pub const fn inner(&self) -> &ParsingErrorInner {
36 &self.inner
37 }
38
39 pub fn into_inner(self) -> ParsingErrorInner {
41 self.inner
42 }
43
44 pub fn critical_message(&self) -> Option<&str> {
46 self.critical.as_deref()
47 }
48
49 pub const fn is_critical(&self) -> bool {
51 self.critical.is_some()
52 }
53
54 pub fn criticalize(mut self, critical: impl Into<Cow<'static, str>>) -> Self {
56 if self.critical.is_none() {
57 self.critical = Some(critical.into());
58 }
59
60 self
61 }
62
63 pub const fn atomic_error(&self) -> Option<&'static str> {
65 self.atomic_error
66 }
67
68 pub const fn with_atomic_error(mut self, atomic_err: &'static str) -> Self {
70 self.atomic_error = Some(atomic_err);
71 self
72 }
73
74 pub const fn expected_char(range: InputRange, expected: char) -> ParsingError {
76 ParsingError::new(ParsingErrorInner::new(
77 range,
78 ParserExpectation::Char(expected),
79 ))
80 }
81
82 pub const fn expected_str(range: InputRange, expected: &'static str) -> ParsingError {
84 ParsingError::new(ParsingErrorInner::new(
85 range,
86 ParserExpectation::Str(expected),
87 ))
88 }
89
90 pub const fn custom(range: InputRange, message: &'static str) -> ParsingError {
92 ParsingError::new(ParsingErrorInner::new(
93 range,
94 ParserExpectation::Custom(message),
95 ))
96 }
97
98 pub const fn just_break(loc: InputLocation) -> ParsingError {
102 ParsingError::new(ParsingErrorInner::new(
103 loc.range(0),
104 ParserExpectation::Break,
105 ))
106 }
107}
108
109#[derive(Debug)]
111#[must_use]
112pub struct ParsingErrorInner {
113 at: InputRange,
115
116 expected: ParserExpectation,
118}
119
120impl ParsingErrorInner {
121 pub const fn new(at: InputRange, expected: ParserExpectation) -> Self {
123 Self { at, expected }
124 }
125
126 pub const fn at(&self) -> InputRange {
128 self.at
129 }
130
131 pub const fn is_empty(&self) -> bool {
133 self.at.len == 0
134 }
135
136 pub const fn expected(&self) -> &ParserExpectation {
138 &self.expected
139 }
140}
141
142#[derive(Debug)]
144pub enum ParserExpectation {
145 Char(char),
147
148 Str(&'static str),
150
151 Custom(&'static str),
153
154 Break,
158}
159
160impl fmt::Display for ParserExpectation {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 match self {
163 Self::Char(c) => write!(f, "expected character '{c}'"),
164 Self::Str(str) => write!(f, "expected string '{str}'"),
165 Self::Custom(custom) => write!(f, "{custom}"),
166 Self::Break => {
167 write!(f, "parser returned a break instruction")
168 }
169 }
170 }
171}