1use crate::internal::Parser;
7use crate::lib::std::fmt;
8
9pub trait ParseError<I>: Sized {
17 fn from_error_kind(input: I, kind: ErrorKind) -> Self;
19
20 fn append(input: I, kind: ErrorKind, other: Self) -> Self;
24
25 fn from_char(input: I, _: char) -> Self {
27 Self::from_error_kind(input, ErrorKind::Char)
28 }
29
30 fn or(self, other: Self) -> Self {
33 other
34 }
35}
36
37pub trait ContextError<I>: Sized {
40 fn add_context(_input: I, _ctx: &'static str, other: Self) -> Self {
44 other
45 }
46}
47
48pub trait FromExternalError<I, E> {
51 fn from_external_error(input: I, kind: ErrorKind, e: E) -> Self;
54}
55
56#[derive(Debug, PartialEq)]
58pub struct Error<I> {
59 pub input: I,
61 pub code: ErrorKind,
63}
64
65impl<I> Error<I> {
66 pub fn new(input: I, code: ErrorKind) -> Error<I> {
68 Error { input, code }
69 }
70}
71
72impl<I> ParseError<I> for Error<I> {
73 fn from_error_kind(input: I, kind: ErrorKind) -> Self {
74 Error { input, code: kind }
75 }
76
77 fn append(_: I, _: ErrorKind, other: Self) -> Self {
78 other
79 }
80}
81
82impl<I> ContextError<I> for Error<I> {}
83
84impl<I, E> FromExternalError<I, E> for Error<I> {
85 fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self {
87 Error { input, code: kind }
88 }
89}
90
91impl<I: fmt::Display> fmt::Display for Error<I> {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 write!(f, "error {:?} at: {}", self.code, self.input)
95 }
96}
97
98#[cfg(feature = "std")]
99impl<I: fmt::Debug + fmt::Display> std::error::Error for Error<I> {}
100
101impl<I> ParseError<I> for (I, ErrorKind) {
104 fn from_error_kind(input: I, kind: ErrorKind) -> Self {
105 (input, kind)
106 }
107
108 fn append(_: I, _: ErrorKind, other: Self) -> Self {
109 other
110 }
111}
112
113impl<I> ContextError<I> for (I, ErrorKind) {}
114
115impl<I, E> FromExternalError<I, E> for (I, ErrorKind) {
116 fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self {
117 (input, kind)
118 }
119}
120
121impl<I> ParseError<I> for () {
122 fn from_error_kind(_: I, _: ErrorKind) -> Self {}
123
124 fn append(_: I, _: ErrorKind, _: Self) -> Self {}
125}
126
127impl<I> ContextError<I> for () {}
128
129impl<I, E> FromExternalError<I, E> for () {
130 fn from_external_error(_input: I, _kind: ErrorKind, _e: E) -> Self {}
131}
132
133pub fn make_error<I, E: ParseError<I>>(input: I, kind: ErrorKind) -> E {
135 E::from_error_kind(input, kind)
136}
137
138pub fn append_error<I, E: ParseError<I>>(input: I, kind: ErrorKind, other: E) -> E {
142 E::append(input, kind, other)
143}
144
145#[cfg(feature = "alloc")]
149#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
150#[derive(Clone, Debug, PartialEq)]
151pub struct VerboseError<I> {
152 pub errors: crate::lib::std::vec::Vec<(I, VerboseErrorKind)>,
155}
156
157#[cfg(feature = "alloc")]
158#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
159#[derive(Clone, Debug, PartialEq)]
160pub enum VerboseErrorKind {
162 Context(&'static str),
164 Char(char),
166 Nom(ErrorKind),
168}
169
170#[cfg(feature = "alloc")]
171#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
172impl<I> ParseError<I> for VerboseError<I> {
173 fn from_error_kind(input: I, kind: ErrorKind) -> Self {
174 VerboseError {
175 errors: vec![(input, VerboseErrorKind::Nom(kind))],
176 }
177 }
178
179 fn append(input: I, kind: ErrorKind, mut other: Self) -> Self {
180 other.errors.push((input, VerboseErrorKind::Nom(kind)));
181 other
182 }
183
184 fn from_char(input: I, c: char) -> Self {
185 VerboseError {
186 errors: vec![(input, VerboseErrorKind::Char(c))],
187 }
188 }
189}
190
191#[cfg(feature = "alloc")]
192#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
193impl<I> ContextError<I> for VerboseError<I> {
194 fn add_context(input: I, ctx: &'static str, mut other: Self) -> Self {
195 other.errors.push((input, VerboseErrorKind::Context(ctx)));
196 other
197 }
198}
199
200#[cfg(feature = "alloc")]
201#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
202impl<I, E> FromExternalError<I, E> for VerboseError<I> {
203 fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self {
205 Self::from_error_kind(input, kind)
206 }
207}
208
209#[cfg(feature = "alloc")]
210impl<I: fmt::Display> fmt::Display for VerboseError<I> {
211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212 writeln!(f, "Parse error:")?;
213 for (input, error) in &self.errors {
214 match error {
215 VerboseErrorKind::Nom(e) => writeln!(f, "{:?} at: {}", e, input)?,
216 VerboseErrorKind::Char(c) => writeln!(f, "expected '{}' at: {}", c, input)?,
217 VerboseErrorKind::Context(s) => writeln!(f, "in section '{}', at: {}", s, input)?,
218 }
219 }
220
221 Ok(())
222 }
223}
224
225#[cfg(feature = "std")]
226impl<I: fmt::Debug + fmt::Display> std::error::Error for VerboseError<I> {}
227
228use crate::internal::{Err, IResult};
229
230pub fn context<I: Clone, E: ContextError<I>, F, O>(
234 context: &'static str,
235 mut f: F,
236) -> impl FnMut(I) -> IResult<I, O, E>
237where
238 F: Parser<I, O, E>,
239{
240 move |i: I| match f.parse(i.clone()) {
241 Ok(o) => Ok(o),
242 Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)),
243 Err(Err::Error(e)) => Err(Err::Error(E::add_context(i, context, e))),
244 Err(Err::Failure(e)) => Err(Err::Failure(E::add_context(i, context, e))),
245 }
246}
247
248#[cfg(feature = "alloc")]
250#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
251pub fn convert_error<I: core::ops::Deref<Target = str>>(
252 input: I,
253 e: VerboseError<I>,
254) -> crate::lib::std::string::String {
255 use crate::lib::std::fmt::Write;
256 use crate::traits::Offset;
257
258 let mut result = crate::lib::std::string::String::new();
259
260 for (i, (substring, kind)) in e.errors.iter().enumerate() {
261 let offset = input.offset(substring);
262
263 if input.is_empty() {
264 match kind {
265 VerboseErrorKind::Char(c) => {
266 write!(&mut result, "{}: expected '{}', got empty input\n\n", i, c)
267 }
268 VerboseErrorKind::Context(s) => write!(&mut result, "{}: in {}, got empty input\n\n", i, s),
269 VerboseErrorKind::Nom(e) => write!(&mut result, "{}: in {:?}, got empty input\n\n", i, e),
270 }
271 } else {
272 let prefix = &input.as_bytes()[..offset];
273
274 let line_number = prefix.iter().filter(|&&b| b == b'\n').count() + 1;
276
277 let line_begin = prefix
280 .iter()
281 .rev()
282 .position(|&b| b == b'\n')
283 .map(|pos| offset - pos)
284 .unwrap_or(0);
285
286 let line = input[line_begin..]
288 .lines()
289 .next()
290 .unwrap_or(&input[line_begin..])
291 .trim_end();
292
293 let column_number = line.offset(substring) + 1;
295
296 match kind {
297 VerboseErrorKind::Char(c) => {
298 if let Some(actual) = substring.chars().next() {
299 write!(
300 &mut result,
301 "{i}: at line {line_number}:\n\
302 {line}\n\
303 {caret:>column$}\n\
304 expected '{expected}', found {actual}\n\n",
305 i = i,
306 line_number = line_number,
307 line = line,
308 caret = '^',
309 column = column_number,
310 expected = c,
311 actual = actual,
312 )
313 } else {
314 write!(
315 &mut result,
316 "{i}: at line {line_number}:\n\
317 {line}\n\
318 {caret:>column$}\n\
319 expected '{expected}', got end of input\n\n",
320 i = i,
321 line_number = line_number,
322 line = line,
323 caret = '^',
324 column = column_number,
325 expected = c,
326 )
327 }
328 }
329 VerboseErrorKind::Context(s) => write!(
330 &mut result,
331 "{i}: at line {line_number}, in {context}:\n\
332 {line}\n\
333 {caret:>column$}\n\n",
334 i = i,
335 line_number = line_number,
336 context = s,
337 line = line,
338 caret = '^',
339 column = column_number,
340 ),
341 VerboseErrorKind::Nom(e) => write!(
342 &mut result,
343 "{i}: at line {line_number}, in {nom_err:?}:\n\
344 {line}\n\
345 {caret:>column$}\n\n",
346 i = i,
347 line_number = line_number,
348 nom_err = e,
349 line = line,
350 caret = '^',
351 column = column_number,
352 ),
353 }
354 }
355 .unwrap();
357 }
358
359 result
360}
361
362#[rustfmt::skip]
364#[derive(Debug,PartialEq,Eq,Hash,Clone,Copy)]
365#[allow(deprecated,missing_docs)]
366pub enum ErrorKind {
367 Tag,
368 MapRes,
369 MapOpt,
370 Alt,
371 IsNot,
372 IsA,
373 SeparatedList,
374 SeparatedNonEmptyList,
375 Many0,
376 Many1,
377 ManyTill,
378 Count,
379 TakeUntil,
380 LengthValue,
381 TagClosure,
382 Alpha,
383 Digit,
384 HexDigit,
385 OctDigit,
386 AlphaNumeric,
387 Space,
388 MultiSpace,
389 LengthValueFn,
390 Eof,
391 Switch,
392 TagBits,
393 OneOf,
394 NoneOf,
395 Char,
396 CrLf,
397 RegexpMatch,
398 RegexpMatches,
399 RegexpFind,
400 RegexpCapture,
401 RegexpCaptures,
402 TakeWhile1,
403 Complete,
404 Fix,
405 Escaped,
406 EscapedTransform,
407 NonEmpty,
408 ManyMN,
409 Not,
410 Permutation,
411 Verify,
412 TakeTill1,
413 TakeWhileMN,
414 TooLarge,
415 Many0Count,
416 Many1Count,
417 Float,
418 Satisfy,
419 Fail,
420}
421
422#[rustfmt::skip]
423#[allow(deprecated)]
424pub fn error_to_u32(e: &ErrorKind) -> u32 {
426 match *e {
427 ErrorKind::Tag => 1,
428 ErrorKind::MapRes => 2,
429 ErrorKind::MapOpt => 3,
430 ErrorKind::Alt => 4,
431 ErrorKind::IsNot => 5,
432 ErrorKind::IsA => 6,
433 ErrorKind::SeparatedList => 7,
434 ErrorKind::SeparatedNonEmptyList => 8,
435 ErrorKind::Many1 => 9,
436 ErrorKind::Count => 10,
437 ErrorKind::TakeUntil => 12,
438 ErrorKind::LengthValue => 15,
439 ErrorKind::TagClosure => 16,
440 ErrorKind::Alpha => 17,
441 ErrorKind::Digit => 18,
442 ErrorKind::AlphaNumeric => 19,
443 ErrorKind::Space => 20,
444 ErrorKind::MultiSpace => 21,
445 ErrorKind::LengthValueFn => 22,
446 ErrorKind::Eof => 23,
447 ErrorKind::Switch => 27,
448 ErrorKind::TagBits => 28,
449 ErrorKind::OneOf => 29,
450 ErrorKind::NoneOf => 30,
451 ErrorKind::Char => 40,
452 ErrorKind::CrLf => 41,
453 ErrorKind::RegexpMatch => 42,
454 ErrorKind::RegexpMatches => 43,
455 ErrorKind::RegexpFind => 44,
456 ErrorKind::RegexpCapture => 45,
457 ErrorKind::RegexpCaptures => 46,
458 ErrorKind::TakeWhile1 => 47,
459 ErrorKind::Complete => 48,
460 ErrorKind::Fix => 49,
461 ErrorKind::Escaped => 50,
462 ErrorKind::EscapedTransform => 51,
463 ErrorKind::NonEmpty => 56,
464 ErrorKind::ManyMN => 57,
465 ErrorKind::HexDigit => 59,
466 ErrorKind::OctDigit => 61,
467 ErrorKind::Many0 => 62,
468 ErrorKind::Not => 63,
469 ErrorKind::Permutation => 64,
470 ErrorKind::ManyTill => 65,
471 ErrorKind::Verify => 66,
472 ErrorKind::TakeTill1 => 67,
473 ErrorKind::TakeWhileMN => 69,
474 ErrorKind::TooLarge => 70,
475 ErrorKind::Many0Count => 71,
476 ErrorKind::Many1Count => 72,
477 ErrorKind::Float => 73,
478 ErrorKind::Satisfy => 74,
479 ErrorKind::Fail => 75,
480 }
481}
482
483impl ErrorKind {
484 #[rustfmt::skip]
485 #[allow(deprecated)]
486 pub fn description(&self) -> &str {
488 match *self {
489 ErrorKind::Tag => "Tag",
490 ErrorKind::MapRes => "Map on Result",
491 ErrorKind::MapOpt => "Map on Option",
492 ErrorKind::Alt => "Alternative",
493 ErrorKind::IsNot => "IsNot",
494 ErrorKind::IsA => "IsA",
495 ErrorKind::SeparatedList => "Separated list",
496 ErrorKind::SeparatedNonEmptyList => "Separated non empty list",
497 ErrorKind::Many0 => "Many0",
498 ErrorKind::Many1 => "Many1",
499 ErrorKind::Count => "Count",
500 ErrorKind::TakeUntil => "Take until",
501 ErrorKind::LengthValue => "Length followed by value",
502 ErrorKind::TagClosure => "Tag closure",
503 ErrorKind::Alpha => "Alphabetic",
504 ErrorKind::Digit => "Digit",
505 ErrorKind::AlphaNumeric => "AlphaNumeric",
506 ErrorKind::Space => "Space",
507 ErrorKind::MultiSpace => "Multiple spaces",
508 ErrorKind::LengthValueFn => "LengthValueFn",
509 ErrorKind::Eof => "End of file",
510 ErrorKind::Switch => "Switch",
511 ErrorKind::TagBits => "Tag on bitstream",
512 ErrorKind::OneOf => "OneOf",
513 ErrorKind::NoneOf => "NoneOf",
514 ErrorKind::Char => "Char",
515 ErrorKind::CrLf => "CrLf",
516 ErrorKind::RegexpMatch => "RegexpMatch",
517 ErrorKind::RegexpMatches => "RegexpMatches",
518 ErrorKind::RegexpFind => "RegexpFind",
519 ErrorKind::RegexpCapture => "RegexpCapture",
520 ErrorKind::RegexpCaptures => "RegexpCaptures",
521 ErrorKind::TakeWhile1 => "TakeWhile1",
522 ErrorKind::Complete => "Complete",
523 ErrorKind::Fix => "Fix",
524 ErrorKind::Escaped => "Escaped",
525 ErrorKind::EscapedTransform => "EscapedTransform",
526 ErrorKind::NonEmpty => "NonEmpty",
527 ErrorKind::ManyMN => "Many(m, n)",
528 ErrorKind::HexDigit => "Hexadecimal Digit",
529 ErrorKind::OctDigit => "Octal digit",
530 ErrorKind::Not => "Negation",
531 ErrorKind::Permutation => "Permutation",
532 ErrorKind::ManyTill => "ManyTill",
533 ErrorKind::Verify => "predicate verification",
534 ErrorKind::TakeTill1 => "TakeTill1",
535 ErrorKind::TakeWhileMN => "TakeWhileMN",
536 ErrorKind::TooLarge => "Needed data size is too large",
537 ErrorKind::Many0Count => "Count occurrence of >=0 patterns",
538 ErrorKind::Many1Count => "Count occurrence of >=1 patterns",
539 ErrorKind::Float => "Float",
540 ErrorKind::Satisfy => "Satisfy",
541 ErrorKind::Fail => "Fail",
542 }
543 }
544}
545
546#[allow(unused_variables)]
549#[macro_export(local_inner_macros)]
550macro_rules! error_position(
551 ($input:expr, $code:expr) => ({
552 $crate::error::make_error($input, $code)
553 });
554);
555
556#[allow(unused_variables)]
560#[macro_export(local_inner_macros)]
561macro_rules! error_node_position(
562 ($input:expr, $code:expr, $next:expr) => ({
563 $crate::error::append_error($input, $code, $next)
564 });
565);
566
567#[cfg(feature = "std")]
589#[cfg_attr(feature = "docsrs", doc(cfg(feature = "std")))]
590pub fn dbg_dmp<'a, F, O, E: std::fmt::Debug>(
591 f: F,
592 context: &'static str,
593) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O, E>
594where
595 F: Fn(&'a [u8]) -> IResult<&'a [u8], O, E>,
596{
597 use crate::HexDisplay;
598 move |i: &'a [u8]| match f(i) {
599 Err(e) => {
600 println!("{}: Error({:?}) at:\n{}", context, e, i.to_hex(8));
601 Err(e)
602 }
603 a => a,
604 }
605}
606
607#[cfg(test)]
608#[cfg(feature = "alloc")]
609mod tests {
610 use super::*;
611 use crate::character::complete::char;
612
613 #[test]
614 fn convert_error_panic() {
615 let input = "";
616
617 let _result: IResult<_, _, VerboseError<&str>> = char('x')(input);
618 }
619}
620
621