diff options
Diffstat (limited to 'vendor/pest/src/error.rs')
-rw-r--r-- | vendor/pest/src/error.rs | 172 |
1 files changed, 130 insertions, 42 deletions
diff --git a/vendor/pest/src/error.rs b/vendor/pest/src/error.rs index d6b76a82a..a83e23a49 100644 --- a/vendor/pest/src/error.rs +++ b/vendor/pest/src/error.rs @@ -9,17 +9,23 @@ //! Types for different kinds of parsing failures. -use std::cmp; -use std::error; -use std::fmt; -use std::mem; - -use position::Position; -use span::Span; -use RuleType; +use alloc::borrow::Cow; +use alloc::borrow::ToOwned; +use alloc::format; +use alloc::string::String; +use alloc::string::ToString; +use alloc::vec::Vec; +use core::cmp; +use core::fmt; +use core::mem; + +use crate::position::Position; +use crate::span::Span; +use crate::RuleType; /// Parse-related error type. #[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "std", derive(thiserror::Error))] pub struct Error<R> { /// Variant of the error pub variant: ErrorVariant<R>, @@ -34,6 +40,7 @@ pub struct Error<R> { /// Different kinds of parsing errors. #[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "std", derive(thiserror::Error))] pub enum ErrorVariant<R> { /// Generated parsing error with expected and unexpected `Rule`s ParsingError { @@ -94,13 +101,19 @@ impl<R: RuleType> Error<R> { /// /// println!("{}", error); /// ``` - #[allow(clippy::needless_pass_by_value)] pub fn new_from_pos(variant: ErrorVariant<R>, pos: Position) -> Error<R> { + let visualize_ws = pos.match_char('\n') || pos.match_char('\r'); + let line_of = pos.line_of(); + let line = if visualize_ws { + visualize_whitespace(line_of) + } else { + line_of.replace(&['\r', '\n'][..], "") + }; Error { variant, location: InputLocation::Pos(pos.pos()), path: None, - line: visualize_whitespace(pos.line_of()), + line, continued_line: None, line_col: LineColLocation::Pos(pos.line_col()), } @@ -134,22 +147,33 @@ impl<R: RuleType> Error<R> { /// /// println!("{}", error); /// ``` - #[allow(clippy::needless_pass_by_value)] pub fn new_from_span(variant: ErrorVariant<R>, span: Span) -> Error<R> { let end = span.end_pos(); - let mut end_line_col = end.line_col(); // end position is after a \n, so we want to point to the visual lf symbol if end_line_col.1 == 1 { - let mut visual_end = end.clone(); + let mut visual_end = end; visual_end.skip_back(1); let lc = visual_end.line_col(); end_line_col = (lc.0, lc.1 + 1); }; let mut line_iter = span.lines(); - let start_line = visualize_whitespace(line_iter.next().unwrap_or("")); - let continued_line = line_iter.last().map(visualize_whitespace); + let sl = line_iter.next().unwrap_or(""); + let mut chars = span.as_str().chars(); + let visualize_ws = matches!(chars.next(), Some('\n') | Some('\r')) + || matches!(chars.last(), Some('\n') | Some('\r')); + let start_line = if visualize_ws { + visualize_whitespace(sl) + } else { + sl.to_owned().replace(&['\r', '\n'][..], "") + }; + let ll = line_iter.last(); + let continued_line = if visualize_ws { + ll.map(&str::to_owned) + } else { + ll.map(visualize_whitespace) + }; Error { variant, @@ -191,6 +215,40 @@ impl<R: RuleType> Error<R> { self } + /// Returns the path set using [`Error::with_path()`]. + /// + /// # Examples + /// + /// ``` + /// # use pest::error::{Error, ErrorVariant}; + /// # use pest::Position; + /// # #[allow(non_camel_case_types)] + /// # #[allow(dead_code)] + /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] + /// # enum Rule { + /// # open_paren, + /// # closed_paren + /// # } + /// # let input = ""; + /// # let pos = Position::from_start(input); + /// # let error = Error::new_from_pos( + /// # ErrorVariant::ParsingError { + /// # positives: vec![Rule::open_paren], + /// # negatives: vec![Rule::closed_paren] + /// # }, + /// # pos); + /// let error = error.with_path("file.rs"); + /// assert_eq!(Some("file.rs"), error.path()); + /// ``` + pub fn path(&self) -> Option<&str> { + self.path.as_deref() + } + + /// Returns the line that the error is on. + pub fn line(&self) -> &str { + self.line.as_str() + } + /// Renames all `Rule`s if this is a [`ParsingError`]. It does nothing when called on a /// [`CustomError`]. /// @@ -297,14 +355,12 @@ impl<R: RuleType> Error<R> { } if let Some(end) = end { + underline.push('^'); if end - start > 1 { - underline.push('^'); for _ in 2..(end - start) { underline.push('-'); } underline.push('^'); - } else { - underline.push('^'); } } else { underline.push_str("^---") @@ -314,13 +370,7 @@ impl<R: RuleType> Error<R> { } fn message(&self) -> String { - match self.variant { - ErrorVariant::ParsingError { - ref positives, - ref negatives, - } => Error::parsing_error_message(positives, negatives, |r| format!("{:?}", r)), - ErrorVariant::CustomError { ref message } => message.clone(), - } + self.variant.message().to_string() } fn parsing_error_message<F>(positives: &[R], negatives: &[R], mut f: F) -> String @@ -347,13 +397,14 @@ impl<R: RuleType> Error<R> { 1 => f(&rules[0]), 2 => format!("{} or {}", f(&rules[0]), f(&rules[1])), l => { + let non_separated = f(&rules[l - 1]); let separated = rules .iter() .take(l - 1) - .map(|r| f(r)) + .map(f) .collect::<Vec<_>>() .join(", "); - format!("{}, or {}", separated, f(&rules[l - 1])) + format!("{}, or {}", separated, non_separated) } } } @@ -431,17 +482,53 @@ impl<R: RuleType> Error<R> { } } +impl<R: RuleType> ErrorVariant<R> { + /// + /// Returns the error message for [`ErrorVariant`] + /// + /// If [`ErrorVariant`] is [`CustomError`], it returns a + /// [`Cow::Borrowed`] reference to [`message`]. If [`ErrorVariant`] is [`ParsingError`], a + /// [`Cow::Owned`] containing "expected [ErrorVariant::ParsingError::positives] [ErrorVariant::ParsingError::negatives]" is returned. + /// + /// [`ErrorVariant`]: enum.ErrorVariant.html + /// [`CustomError`]: enum.ErrorVariant.html#variant.CustomError + /// [`ParsingError`]: enum.ErrorVariant.html#variant.ParsingError + /// [`Cow::Owned`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html#variant.Owned + /// [`Cow::Borrowed`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html#variant.Borrowed + /// [`message`]: enum.ErrorVariant.html#variant.CustomError.field.message + /// # Examples + /// + /// ``` + /// # use pest::error::ErrorVariant; + /// let variant = ErrorVariant::<()>::CustomError { + /// message: String::from("unexpected error") + /// }; + /// + /// println!("{}", variant.message()); + pub fn message(&self) -> Cow<str> { + match self { + ErrorVariant::ParsingError { + ref positives, + ref negatives, + } => Cow::Owned(Error::parsing_error_message(positives, negatives, |r| { + format!("{:?}", r) + })), + ErrorVariant::CustomError { ref message } => Cow::Borrowed(message), + } + } +} + impl<R: RuleType> fmt::Display for Error<R> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.format()) } } -impl<'i, R: RuleType> error::Error for Error<R> { - fn description(&self) -> &str { - match self.variant { - ErrorVariant::ParsingError { .. } => "parsing error", - ErrorVariant::CustomError { ref message } => message, +impl<R: RuleType> fmt::Display for ErrorVariant<R> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ErrorVariant::ParsingError { .. } => write!(f, "parsing error: {}", self.message()), + ErrorVariant::CustomError { .. } => write!(f, "{}", self.message()), } } } @@ -454,6 +541,7 @@ fn visualize_whitespace(input: &str) -> String { mod tests { use super::super::position; use super::*; + use alloc::vec; #[test] fn display_parsing_error_mixed() { @@ -472,7 +560,7 @@ mod tests { vec![ " --> 2:2", " |", - "2 | cd␊", + "2 | cd", " | ^---", " |", " = unexpected 4, 5, or 6; expected 1, 2, or 3", @@ -498,7 +586,7 @@ mod tests { vec![ " --> 2:2", " |", - "2 | cd␊", + "2 | cd", " | ^---", " |", " = expected 1 or 2", @@ -524,7 +612,7 @@ mod tests { vec![ " --> 2:2", " |", - "2 | cd␊", + "2 | cd", " | ^---", " |", " = unexpected 4, 5, or 6", @@ -550,7 +638,7 @@ mod tests { vec![ " --> 2:2", " |", - "2 | cd␊", + "2 | cd", " | ^---", " |", " = unknown parsing error", @@ -575,7 +663,7 @@ mod tests { vec![ " --> 2:2", " |", - "2 | cd␊", + "2 | cd", " | ^---", " |", " = error: big one", @@ -601,7 +689,7 @@ mod tests { vec![ " --> 2:2", " |", - "2 | cd␊", + "2 | cd", "3 | efgh", " | ^^", " |", @@ -628,7 +716,7 @@ mod tests { vec![ " --> 1:2", " |", - "1 | ab␊", + "1 | ab", " | ...", "3 | efgh", " | ^^", @@ -656,7 +744,7 @@ mod tests { vec![ " --> 1:6", " |", - "1 | abcdef␊", + "1 | abcdef", "2 | gh", " | ^----^", " |", @@ -742,7 +830,7 @@ mod tests { vec![ " --> 2:2", " |", - "2 | cd␊", + "2 | cd", " | ^---", " |", " = unexpected 5, 6, or 7; expected 2, 3, or 4", @@ -769,7 +857,7 @@ mod tests { vec![ " --> file.rs:2:2", " |", - "2 | cd␊", + "2 | cd", " | ^---", " |", " = unexpected 4, 5, or 6; expected 1, 2, or 3", |