summaryrefslogtreecommitdiffstats
path: root/vendor/pest/src/error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/pest/src/error.rs')
-rw-r--r--vendor/pest/src/error.rs172
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",