1use crate::{
2 name::Name,
3 parse::{
4 base,
5 span::Span,
6 },
7 term::{
8 LitType,
9 Literal,
10 },
11};
12
13use nom::{
14 error::ErrorKind,
15 AsBytes,
16 Err,
17 IResult,
18 InputLength,
19};
20
21#[cfg(not(feature = "std"))]
22use sp_std::{
23 cmp::Ordering,
24 fmt,
25 fmt::Write,
26 num::ParseIntError,
27 vec::Vec,
28};
29#[cfg(feature = "std")]
30use std::{
31 cmp::Ordering,
32 fmt,
33 fmt::Write,
34 num::ParseIntError,
35 vec::Vec,
36};
37
38use sp_im::conslist::ConsList;
39
40use alloc::string::String;
41
42#[derive(PartialEq, Debug, Clone)]
43pub enum ParseErrorKind {
44 UndefinedReference(Name, ConsList<Name>),
45 TopLevelRedefinition(Name),
46 UnknownLiteralType(String),
47 InvalidBaseEncoding(base::LitBase),
48 UnknownBaseCode,
49 ExpectedSingleChar(Vec<char>),
50 InvalidBase16EscapeSequence(String),
51 MultibaseError(multibase::Error),
52 CidError,
53 ParseIntErr(ParseIntError),
54 ReservedKeyword(String),
55 NumericSyntax(String),
56 ReservedSyntax(String),
57 LiteralLacksWhitespaceTermination(Literal),
58 LitTypeLacksWhitespaceTermination(LitType),
59 UnknownNatOp(Name),
60 UnknownIntOp(Name),
61 UnknownBitsOp(Name),
62 UnknownBytesOp(Name),
63 UnknownBoolOp(Name),
64 UnknownTextOp(Name),
65 UnknownCharOp(Name),
66 UnknownU8Op(Name),
67 UnknownU16Op(Name),
68 UnknownU32Op(Name),
69 UnknownU64Op(Name),
70 UnknownU128Op(Name),
71 UnknownI8Op(Name),
72 UnknownI16Op(Name),
73 UnknownI32Op(Name),
74 UnknownI64Op(Name),
75 UnknownI128Op(Name),
76 TypeDefConstructorMustReturnItsType,
77 InvalidSymbol(String),
78 Nom(ErrorKind),
79}
80
81impl<'a> fmt::Display for ParseErrorKind {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 match self {
84 Self::UndefinedReference(name, _) => {
85 write!(f, "Undefined reference {}", name)
86 }
87 Self::TopLevelRedefinition(name) => {
88 write!(
89 f,
90 "Overlapping definition names, \"{}\" already defined or imported",
91 name
92 )
93 }
94 Self::ExpectedSingleChar(chrs) => {
95 write!(
96 f,
97 "Character literal syntax must contain one and only one character, \
98 but parsed {:?}",
99 chrs
100 )
101 }
102 Self::InvalidBase16EscapeSequence(seq) => {
103 write!(f, "Unknown base 16 string escape sequence {}.", seq)
104 }
105 Self::ParseIntErr(e) => {
106 write!(f, "Error parsing number: {}", e)
107 }
108 Self::ReservedKeyword(name) => {
109 write!(f, "{}` is a reserved language keyword", name)
110 }
111 Self::ReservedSyntax(_) => {
112 write!(f, "Symbols beginning with '#' are reserved")
113 }
114 Self::NumericSyntax(_) => {
115 write!(f, "Symbols beginning with digits are reserved")
116 }
117 Self::InvalidSymbol(name) => {
118 write!(
119 f,
120 "The symbol {} contains a reserved character ':', '(', ')', ',', or \
121 whitespace or control character.",
122 name
123 )
124 }
125 Self::LiteralLacksWhitespaceTermination(x) => {
126 write!(f, "Literal {} must be terminated by whitespace or eof", x)
127 }
128 Self::LitTypeLacksWhitespaceTermination(x) => {
129 write!(f, "Literal type {} must be terminated by whitespace or eof", x)
130 }
131 Self::UnknownNatOp(x) => {
132 write!(f, "Unknown primitive Nat operation #Nat.{}", x)
133 }
134 Self::UnknownIntOp(x) => {
135 write!(f, "Unknown primitive Int operation #Int.{}", x)
136 }
137 Self::UnknownBytesOp(x) => {
138 write!(f, "Unknown primitive Bytes operation #Bytes.{}", x)
139 }
140 Self::UnknownTextOp(x) => {
141 write!(f, "Unknown primitive Nat operation #Text.{}", x)
142 }
143 _ => write!(f, "internal parser error"),
144 }
145 }
146}
147
148impl ParseErrorKind {
149 pub fn is_nom_err(&self) -> bool { matches!(self, Self::Nom(_)) }
150}
151
152#[derive(PartialEq, Debug, Clone)]
153pub struct ParseError<I: AsBytes> {
154 pub input: I,
155 pub expected: Option<&'static str>,
156 pub errors: Vec<ParseErrorKind>,
157}
158
159impl<I: AsBytes> ParseError<I> {
160 pub fn new(input: I, error: ParseErrorKind) -> Self {
161 ParseError { input, expected: None, errors: vec![error] }
162 }
163}
164
165impl<'a> fmt::Display for ParseError<Span<'a>> {
166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167 let mut res = String::new();
168
169 writeln!(
170 &mut res,
171 "at line {}:{}",
172 self.input.location_line(),
173 self.input.get_column()
174 )?;
175 let line = String::from_utf8_lossy(self.input.get_line_beginning());
176
177 writeln!(&mut res, "{} | {}", self.input.location_line(), line)?;
178
179 let cols = format!("{} | ", self.input.location_line()).len()
180 + self.input.get_column();
181 for _ in 0..(cols - 1) {
182 write!(&mut res, " ")?;
183 }
184 writeln!(&mut res, "^")?;
185
186 if let Some(exp) = self.expected {
187 writeln!(&mut res, "Expected {}", exp)?;
188 }
189
190 let mut errs = self.errors.iter().filter(|x| !x.is_nom_err()).peekable();
191 if errs.peek() == None {
192 writeln!(&mut res, "Internal parser error")?;
194 }
195 else {
196 writeln!(&mut res, "Reported errors:")?;
197 for kind in errs {
198 writeln!(&mut res, "- {}", kind)?;
199 }
200 }
201
202 write!(f, "{}", res)
203 }
204}
205
206impl<I: AsBytes> nom::error::ParseError<I> for ParseError<I>
207where
208 I: InputLength,
209 I: Clone,
210{
211 fn from_error_kind(input: I, kind: ErrorKind) -> Self {
212 ParseError::new(input, ParseErrorKind::Nom(kind))
213 }
214
215 fn append(input: I, kind: ErrorKind, mut other: Self) -> Self {
216 match input.input_len().cmp(&other.input.input_len()) {
217 Ordering::Less => ParseError::new(input, ParseErrorKind::Nom(kind)),
218 Ordering::Equal => {
219 other.errors.push(ParseErrorKind::Nom(kind));
220 other
221 }
222 Ordering::Greater => other,
223 }
224 }
225
226 fn or(self, mut other: Self) -> Self {
227 match self.input.input_len().cmp(&other.input.input_len()) {
228 Ordering::Less => self,
229 Ordering::Equal => {
230 for x in self.errors {
231 other.errors.push(x);
232 }
233 other
234 }
235 Ordering::Greater => other,
236 }
237 }
238}
239
240impl<I: AsBytes> nom::error::ContextError<I> for ParseError<I>
241where
242 I: InputLength,
243 I: Clone,
244{
245 fn add_context(input: I, ctx: &'static str, other: Self) -> Self {
246 match input.input_len().cmp(&other.input.input_len()) {
247 Ordering::Less => {
248 ParseError { input, expected: Some(ctx), errors: vec![] }
249 }
250 Ordering::Equal => match other.expected {
251 None => ParseError { input, expected: Some(ctx), errors: other.errors },
252 _ => other,
253 },
254 Ordering::Greater => other,
255 }
256 }
257}
258
259pub fn throw_err<I: AsBytes, A, F: Fn(ParseError<I>) -> ParseError<I>>(
260 x: IResult<I, A, ParseError<I>>,
261 f: F,
262) -> IResult<I, A, ParseError<I>> {
263 match x {
264 Ok(res) => Ok(res),
265 Err(Err::Incomplete(n)) => Err(Err::Incomplete(n)),
266 Err(Err::Error(e)) => Err(Err::Error(f(e))),
267 Err(Err::Failure(e)) => Err(Err::Failure(f(e))),
268 }
269}