1 use crate::lib::fmt; 2 3 #[cfg(feature = "std")] 4 use std::error::Error as StdError; 5 6 use crate::{stream::StreamOnce, ErrorOffset}; 7 8 use self::ParseResult::*; 9 10 pub(crate) trait ResultExt<E, T> { committed(self) -> ParseResult<E, T>11 fn committed(self) -> ParseResult<E, T>; 12 } 13 14 impl<E, T> ResultExt<E, T> for Result<E, T> { committed(self) -> ParseResult<E, T>15 fn committed(self) -> ParseResult<E, T> { 16 match self { 17 Ok(x) => CommitOk(x), 18 Err(x) => CommitErr(x), 19 } 20 } 21 } 22 23 #[macro_export] 24 #[doc(hidden)] 25 macro_rules! ctry { 26 ($result:expr) => { 27 match $result { 28 $crate::error::ParseResult::CommitOk(x) => (x, $crate::error::Commit::Commit(())), 29 $crate::error::ParseResult::PeekOk(x) => (x, $crate::error::Commit::Peek(())), 30 $crate::error::ParseResult::CommitErr(err) => { 31 return $crate::error::ParseResult::CommitErr(err.into()) 32 } 33 $crate::error::ParseResult::PeekErr(err) => { 34 return $crate::error::ParseResult::PeekErr(err.into()) 35 } 36 } 37 }; 38 } 39 40 /// Trait for types which can be used to construct error information. 41 /// 42 /// To call functions expecting this trait, use the wrapper types defined in this module 43 /// `Token`, `Range`, `Format` or `Static`/`&'static str` 44 pub trait ErrorInfo<'s, T, R> { 45 type Format: fmt::Display; 46 47 #[allow(clippy::wrong_self_convention)] into_info(&'s self) -> Info<T, R, Self::Format>48 fn into_info(&'s self) -> Info<T, R, Self::Format>; 49 } 50 51 impl<'s, 'a, T, R, F> ErrorInfo<'s, T, R> for &'a F 52 where 53 F: ErrorInfo<'s, T, R>, 54 { 55 type Format = F::Format; into_info(&'s self) -> Info<T, R, Self::Format>56 fn into_info(&'s self) -> Info<T, R, Self::Format> { 57 (**self).into_info() 58 } 59 } 60 61 #[derive(Clone, Debug)] 62 pub enum Info<T, R, F = &'static str> { 63 Token(T), 64 Range(R), 65 Static(&'static str), 66 Format(F), 67 } 68 69 impl<'s, T, R, F> ErrorInfo<'s, T, R> for Info<T, R, F> 70 where 71 T: Clone, 72 R: Clone, 73 F: fmt::Display + 's, 74 { 75 type Format = &'s F; into_info(&'s self) -> Info<T, R, <Self as ErrorInfo<'_, T, R>>::Format>76 fn into_info(&'s self) -> Info<T, R, <Self as ErrorInfo<'_, T, R>>::Format> { 77 match self { 78 Info::Token(b) => Info::Token(b.clone()), 79 Info::Range(b) => Info::Range(b.clone()), 80 Info::Static(b) => Info::Static(*b), 81 Info::Format(b) => Info::Format(b), 82 } 83 } 84 } 85 86 impl<R, F> From<char> for Info<char, R, F> { from(s: char) -> Self87 fn from(s: char) -> Self { 88 Info::Token(s) 89 } 90 } 91 92 impl<'s, R> ErrorInfo<'s, char, R> for char { 93 type Format = &'static str; into_info(&self) -> Info<char, R, Self::Format>94 fn into_info(&self) -> Info<char, R, Self::Format> { 95 Info::Token(*self) 96 } 97 } 98 99 impl<T, R, F> From<&'static str> for Info<T, R, F> { from(s: &'static str) -> Self100 fn from(s: &'static str) -> Self { 101 Info::Static(s) 102 } 103 } 104 105 impl<'s, T, R> ErrorInfo<'s, T, R> for &'static str { 106 type Format = &'static str; into_info(&self) -> Info<T, R, Self::Format>107 fn into_info(&self) -> Info<T, R, Self::Format> { 108 Info::Static(*self) 109 } 110 } 111 112 impl<R, F> From<u8> for Info<u8, R, F> { from(s: u8) -> Self113 fn from(s: u8) -> Self { 114 Info::Token(s) 115 } 116 } 117 118 impl<R> ErrorInfo<'_, Self, R> for u8 { 119 type Format = &'static str; into_info(&self) -> Info<Self, R, Self::Format>120 fn into_info(&self) -> Info<Self, R, Self::Format> { 121 Info::Token(*self) 122 } 123 } 124 125 /// Newtype which constructs an `Info::Token` through `ErrorInfo` 126 pub struct Token<T>(pub T); 127 128 impl<T, R> From<Token<T>> for Info<T, R, &'static str> { from(s: Token<T>) -> Self129 fn from(s: Token<T>) -> Self { 130 Info::Token(s.0) 131 } 132 } 133 134 impl<'s, T, R> ErrorInfo<'s, T, R> for Token<T> 135 where 136 T: Clone, 137 { 138 type Format = &'static str; into_info(&'s self) -> Info<T, R, Self::Format>139 fn into_info(&'s self) -> Info<T, R, Self::Format> { 140 Info::Token(self.0.clone()) 141 } 142 } 143 144 /// Newtype which constructs an `Info::Range` through `ErrorInfo` 145 pub struct Range<R>(pub R); 146 147 impl<T, R> From<Range<R>> for Info<T, R, &'static str> { from(s: Range<R>) -> Self148 fn from(s: Range<R>) -> Self { 149 Info::Range(s.0) 150 } 151 } 152 153 impl<'s, T, R> ErrorInfo<'s, T, R> for Range<R> 154 where 155 R: Clone, 156 { 157 type Format = &'static str; into_info(&'s self) -> Info<T, R, Self::Format>158 fn into_info(&'s self) -> Info<T, R, Self::Format> { 159 Info::Range(self.0.clone()) 160 } 161 } 162 163 /// Newtype which constructs an `Info::Static` through `ErrorInfo` 164 /// A plain `&'static str` can also be used, this exists for consistency. 165 pub struct Static(&'static str); 166 167 impl<T, R, F> From<Static> for Info<T, R, F> 168 where 169 F: fmt::Display, 170 { from(s: Static) -> Self171 fn from(s: Static) -> Self { 172 Info::Static(s.0) 173 } 174 } 175 176 impl<'s, T, R> ErrorInfo<'s, T, R> for Static { 177 type Format = &'static str; into_info(&'s self) -> Info<T, R, Self::Format>178 fn into_info(&'s self) -> Info<T, R, Self::Format> { 179 Info::Static(self.0) 180 } 181 } 182 183 /// Newtype which constructs an `Info::Format` through `ErrorInfo` 184 pub struct Format<F>(pub F) 185 where 186 F: fmt::Display; 187 188 impl<T, R, F> From<Format<F>> for Info<T, R, F> 189 where 190 F: fmt::Display, 191 { from(s: Format<F>) -> Self192 fn from(s: Format<F>) -> Self { 193 Info::Format(s.0) 194 } 195 } 196 197 impl<'s, T, R, F> ErrorInfo<'s, T, R> for Format<F> 198 where 199 F: fmt::Display + 's, 200 { 201 type Format = &'s F; into_info(&'s self) -> Info<T, R, Self::Format>202 fn into_info(&'s self) -> Info<T, R, Self::Format> { 203 Info::Format(&self.0) 204 } 205 } 206 207 /// Enum used to indicate if a parser committed any items of the stream it was given as an input. 208 /// 209 /// This is used by parsers such as `or` and `choice` to determine if they should try to parse 210 /// with another parser as they will only be able to provide good error reporting if the preceding 211 /// parser did not commit to the parse. 212 #[derive(Clone, PartialEq, Debug, Copy)] 213 pub enum Commit<T> { 214 /// Constructor indicating that the parser has committed to this parse. If a parser after this fails, 215 /// other parser alternatives will not be attempted (`CommitErr` will be returned) 216 Commit(T), 217 /// Constructor indicating that the parser has not committed to this parse. If a parser after this fails, 218 /// other parser alternatives will be attempted (`EmptyErr` will be returned) 219 Peek(T), 220 } 221 222 impl<T> AsMut<T> for Commit<T> { as_mut(&mut self) -> &mut T223 fn as_mut(&mut self) -> &mut T { 224 match *self { 225 Commit::Peek(ref mut t) | Commit::Commit(ref mut t) => t, 226 } 227 } 228 } 229 230 impl<T> AsRef<T> for Commit<T> { as_ref(&self) -> &T231 fn as_ref(&self) -> &T { 232 match *self { 233 Commit::Peek(ref t) | Commit::Commit(ref t) => t, 234 } 235 } 236 } 237 238 impl<T> Commit<T> { 239 /// Returns true if `self` is peek. is_peek(&self) -> bool240 pub fn is_peek(&self) -> bool { 241 match *self { 242 Commit::Peek(_) => true, 243 Commit::Commit(_) => false, 244 } 245 } 246 247 /// Extracts the contained value. into_inner(self) -> T248 pub fn into_inner(self) -> T { 249 match self { 250 Commit::Peek(x) | Commit::Commit(x) => x, 251 } 252 } 253 254 /// Converts `self` into the `Commit` state. into_commit(self) -> Commit<T>255 pub fn into_commit(self) -> Commit<T> { 256 Commit::Commit(self.into_inner()) 257 } 258 259 /// Converts `self` into the `Peek` state. into_peek(self) -> Commit<T>260 pub fn into_peek(self) -> Commit<T> { 261 Commit::Peek(self.into_inner()) 262 } 263 264 /// Maps over the contained value without changing the committed state. map<F, U>(self, f: F) -> Commit<U> where F: FnOnce(T) -> U,265 pub fn map<F, U>(self, f: F) -> Commit<U> 266 where 267 F: FnOnce(T) -> U, 268 { 269 match self { 270 Commit::Peek(x) => Commit::Peek(f(x)), 271 Commit::Commit(x) => Commit::Commit(f(x)), 272 } 273 } 274 merge(&self, current: Commit<T>) -> Commit<T>275 pub fn merge(&self, current: Commit<T>) -> Commit<T> { 276 match *self { 277 Commit::Peek(_) => current, 278 Commit::Commit(_) => current.into_commit(), 279 } 280 } 281 282 /// Combines the `Commit` flags from `self` and the result of `f`. 283 /// 284 /// ```text 285 /// Peek <> Peek -> Peek 286 /// Commit <> Peek -> Commit 287 /// Peek <> Commit -> Commit 288 /// Commit <> Commit -> Commit 289 /// ``` 290 /// 291 /// ``` 292 /// # extern crate combine as pc; 293 /// # use pc::*; 294 /// # fn main() { 295 /// //Parses a character of string literal and handles the escaped characters \\ and \" as \ 296 /// //and " respectively 297 /// fn char<Input>(input: &mut Input) -> StdParseResult<char, Input> 298 /// where Input: Stream<Token = char>, 299 /// Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, 300 /// { 301 /// let (c, committed) = satisfy(|c| c != '"').parse_stream(input).into_result()?; 302 /// match c { 303 /// //Since the `char` parser has already committed some of the input `combine` is used 304 /// //propagate the committed state to the next part of the parser 305 /// '\\' => committed.combine(|_| { 306 /// satisfy(|c| c == '"' || c == '\\') 307 /// .map(|c| { 308 /// match c { 309 /// '"' => '"', 310 /// '\\' => '\\', 311 /// c => c 312 /// } 313 /// }) 314 /// .parse_stream(input) 315 /// .into_result() 316 /// }), 317 /// _ => Ok((c, committed)) 318 /// } 319 /// } 320 /// let result = many(parser(char)) 321 /// .easy_parse(r#"abc\"\\"#); 322 /// assert_eq!(result, Ok((r#"abc"\"#.to_string(), ""))); 323 /// } 324 /// ``` combine<F, U, E>(self, f: F) -> StdParseResult2<U, E> where F: FnOnce(T) -> StdParseResult2<U, E>,325 pub fn combine<F, U, E>(self, f: F) -> StdParseResult2<U, E> 326 where 327 F: FnOnce(T) -> StdParseResult2<U, E>, 328 { 329 match self { 330 Commit::Commit(x) => match f(x) { 331 Ok((v, Commit::Peek(()))) => Ok((v, Commit::Commit(()))), 332 Err(Commit::Peek(err)) => Err(Commit::Commit(err)), 333 y => y, 334 }, 335 Commit::Peek(x) => f(x), 336 } 337 } combine_commit<F, U, E>(self, f: F) -> ParseResult<U, E> where F: FnOnce(T) -> ParseResult<U, E>,338 pub fn combine_commit<F, U, E>(self, f: F) -> ParseResult<U, E> 339 where 340 F: FnOnce(T) -> ParseResult<U, E>, 341 { 342 use self::ParseResult::*; 343 344 match self { 345 Commit::Commit(x) => match f(x) { 346 PeekOk(v) => CommitOk(v), 347 PeekErr(err) => CommitErr(err.error), 348 y => y, 349 }, 350 Commit::Peek(x) => f(x), 351 } 352 } 353 } 354 355 /// A type alias over the specific `Result` type used by parsers to indicate whether they were 356 /// successful or not. 357 /// `O` is the type that is output on success. 358 /// `Input` is the specific stream type used in the parser. 359 pub type StdParseResult<O, Input> = 360 Result<(O, Commit<()>), Commit<Tracked<<Input as StreamOnce>::Error>>>; 361 pub type StdParseResult2<O, E> = Result<(O, Commit<()>), Commit<Tracked<E>>>; 362 363 /// `StreamError` represents a single error returned from a `Stream` or a `Parser`. 364 /// 365 /// Usually multiple instances of `StreamError` is composed into a `ParseError` to build the final 366 /// error value. 367 pub trait StreamError<Item, Range>: Sized { unexpected_token(token: Item) -> Self368 fn unexpected_token(token: Item) -> Self; unexpected_range(token: Range) -> Self369 fn unexpected_range(token: Range) -> Self; unexpected_format<T>(msg: T) -> Self where T: fmt::Display370 fn unexpected_format<T>(msg: T) -> Self 371 where 372 T: fmt::Display; unexpected<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,373 fn unexpected<E>(info: E) -> Self 374 where 375 E: for<'s> ErrorInfo<'s, Item, Range>, 376 { 377 match info.into_info() { 378 Info::Token(b) => Self::unexpected_token(b), 379 Info::Range(b) => Self::unexpected_range(b), 380 Info::Static(b) => Self::unexpected_static_message(b), 381 Info::Format(b) => Self::unexpected_format(b), 382 } 383 } unexpected_static_message(msg: &'static str) -> Self384 fn unexpected_static_message(msg: &'static str) -> Self { 385 Self::unexpected_format(msg) 386 } 387 expected_token(token: Item) -> Self388 fn expected_token(token: Item) -> Self; expected_range(token: Range) -> Self389 fn expected_range(token: Range) -> Self; expected_format<T>(msg: T) -> Self where T: fmt::Display390 fn expected_format<T>(msg: T) -> Self 391 where 392 T: fmt::Display; expected<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,393 fn expected<E>(info: E) -> Self 394 where 395 E: for<'s> ErrorInfo<'s, Item, Range>, 396 { 397 match info.into_info() { 398 Info::Token(b) => Self::expected_token(b), 399 Info::Range(b) => Self::expected_range(b), 400 Info::Static(b) => Self::expected_static_message(b), 401 Info::Format(b) => Self::expected_format(b), 402 } 403 } expected_static_message(msg: &'static str) -> Self404 fn expected_static_message(msg: &'static str) -> Self { 405 Self::expected_format(msg) 406 } 407 message_token(token: Item) -> Self408 fn message_token(token: Item) -> Self; message_range(token: Range) -> Self409 fn message_range(token: Range) -> Self; message_format<T>(msg: T) -> Self where T: fmt::Display410 fn message_format<T>(msg: T) -> Self 411 where 412 T: fmt::Display; message_static_message(msg: &'static str) -> Self413 fn message_static_message(msg: &'static str) -> Self { 414 Self::message_format(msg) 415 } message<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,416 fn message<E>(info: E) -> Self 417 where 418 E: for<'s> ErrorInfo<'s, Item, Range>, 419 { 420 match info.into_info() { 421 Info::Token(b) => Self::message_token(b), 422 Info::Range(b) => Self::message_range(b), 423 Info::Static(b) => Self::message_static_message(b), 424 Info::Format(b) => Self::message_format(b), 425 } 426 } 427 428 #[cfg(feature = "std")] other<E>(err: E) -> Self where E: StdError + Send + Sync + 'static,429 fn other<E>(err: E) -> Self 430 where 431 E: StdError + Send + Sync + 'static, 432 { 433 Self::message_format(err) 434 } 435 end_of_input() -> Self436 fn end_of_input() -> Self { 437 Self::unexpected_static_message("end of input") 438 } 439 is_unexpected_end_of_input(&self) -> bool440 fn is_unexpected_end_of_input(&self) -> bool; 441 442 /// Converts `self` into a different `StreamError` type. 443 /// 444 /// This should aim to preserve as much information as possible into the returned `T` value but 445 /// if `Self` ignores some information passed to it using one of the constructors that 446 /// information is naturally lost. into_other<T>(self) -> T where T: StreamError<Item, Range>447 fn into_other<T>(self) -> T 448 where 449 T: StreamError<Item, Range>; 450 } 451 452 /// Trait which defines a combine parse error. 453 /// 454 /// A parse error is composed of zero or more `StreamError` instances which gets added to it as 455 /// errors are encountered during parsing. 456 pub trait ParseError<Item, Range, Position>: Sized + PartialEq { 457 type StreamError: StreamError<Item, Range>; 458 459 /// Constructs an empty error. 460 /// 461 /// An empty error is expected to be cheap to create as it is frequently created and discarded. empty(position: Position) -> Self462 fn empty(position: Position) -> Self; 463 464 /// Creates a `ParseError` from a single `Self::StreamError` from_error(position: Position, err: Self::StreamError) -> Self465 fn from_error(position: Position, err: Self::StreamError) -> Self { 466 let mut errors = Self::empty(position); 467 errors.add(err); 468 errors 469 } 470 position(&self) -> Position471 fn position(&self) -> Position { 472 // TODO Remove the default implementation in a breaking release 473 unimplemented!() 474 } 475 476 /// Sets the position of this `ParseError` set_position(&mut self, position: Position)477 fn set_position(&mut self, position: Position); 478 479 /// Merges two errors. If they exist at the same position the errors of `other` are 480 /// added to `self` (using the semantics of `add`). If they are not at the same 481 /// position the error furthest ahead are returned, ignoring the other `ParseError`. merge(self, other: Self) -> Self482 fn merge(self, other: Self) -> Self { 483 other 484 } 485 486 /// Adds a `StreamError` to `self`. 487 /// 488 /// It is up to each individual error type to define what adding an error does, some may push 489 /// it to a vector while others may only keep `self` or `err` to avoid allocation add(&mut self, err: Self::StreamError)490 fn add(&mut self, err: Self::StreamError); 491 add_expected<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,492 fn add_expected<E>(&mut self, info: E) 493 where 494 E: for<'s> ErrorInfo<'s, Item, Range>, 495 { 496 self.add(Self::StreamError::expected(info)) 497 } 498 add_unexpected<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,499 fn add_unexpected<E>(&mut self, info: E) 500 where 501 E: for<'s> ErrorInfo<'s, Item, Range>, 502 { 503 self.add(Self::StreamError::unexpected(info)) 504 } 505 add_message<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,506 fn add_message<E>(&mut self, info: E) 507 where 508 E: for<'s> ErrorInfo<'s, Item, Range>, 509 { 510 self.add(Self::StreamError::message(info)) 511 } 512 513 /// Sets `info` as the *only* `Expected` error of `self` set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) where F: FnOnce(&mut Tracked<Self>)514 fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) 515 where 516 F: FnOnce(&mut Tracked<Self>); 517 518 /// Removes any expected errors currently in `self` clear_expected(&mut self)519 fn clear_expected(&mut self) {} 520 is_unexpected_end_of_input(&self) -> bool521 fn is_unexpected_end_of_input(&self) -> bool; 522 523 /// Does a best-effort conversion of `self` into another `ParseError` into_other<T>(self) -> T where T: ParseError<Item, Range, Position>524 fn into_other<T>(self) -> T 525 where 526 T: ParseError<Item, Range, Position>; 527 } 528 529 /// Defines a conversion between two parse error types. 530 /// 531 /// Like `ParseError::into_other` but with a more general signature 532 /// (This will take the place of `into_other` on breaking release of combine) 533 pub trait ParseErrorInto<Item, Range, Position>: Sized { into_other_error<T, Item2, Range2, Position2>(self) -> T where T: ParseError<Item2, Range2, Position2>, Item2: From<Item>, Range2: From<Range>, Position2: From<Position>534 fn into_other_error<T, Item2, Range2, Position2>(self) -> T 535 where 536 T: ParseError<Item2, Range2, Position2>, 537 Item2: From<Item>, 538 Range2: From<Range>, 539 Position2: From<Position>; 540 } 541 542 /// Defines a conversion between two stream error types. 543 /// 544 /// Like `StreamError::into_other` but with a more general signature 545 /// (This will take the place of `into_other` on breaking release of combine) 546 pub trait StreamErrorInto<Item, Range>: Sized { into_other_error<T, Item2, Range2>(self) -> T where T: StreamError<Item2, Range2>, Item2: From<Item>, Range2: From<Range>547 fn into_other_error<T, Item2, Range2>(self) -> T 548 where 549 T: StreamError<Item2, Range2>, 550 Item2: From<Item>, 551 Range2: From<Range>; 552 } 553 554 #[derive(Clone, Copy, Debug, PartialEq)] 555 pub enum UnexpectedParse { 556 Eoi, 557 Unexpected, 558 } 559 560 impl fmt::Display for UnexpectedParse { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result561 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 562 write!(f, "{}", self.as_str()) 563 } 564 } 565 566 #[cfg(feature = "std")] 567 impl StdError for UnexpectedParse { description(&self) -> &str568 fn description(&self) -> &str { 569 self.as_str() 570 } 571 } 572 573 impl UnexpectedParse { as_str(&self) -> &str574 fn as_str(&self) -> &str { 575 use self::UnexpectedParse::*; 576 match *self { 577 Unexpected => "unexpected parse", 578 Eoi => "unexpected end of input", 579 } 580 } 581 } 582 583 impl<Item, Range> StreamError<Item, Range> for UnexpectedParse { 584 #[inline] unexpected_token(_: Item) -> Self585 fn unexpected_token(_: Item) -> Self { 586 UnexpectedParse::Unexpected 587 } 588 #[inline] unexpected_range(_: Range) -> Self589 fn unexpected_range(_: Range) -> Self { 590 UnexpectedParse::Unexpected 591 } 592 #[inline] unexpected_format<T>(_: T) -> Self where T: fmt::Display,593 fn unexpected_format<T>(_: T) -> Self 594 where 595 T: fmt::Display, 596 { 597 UnexpectedParse::Unexpected 598 } 599 600 #[inline] expected_token(_: Item) -> Self601 fn expected_token(_: Item) -> Self { 602 UnexpectedParse::Unexpected 603 } 604 #[inline] expected_range(_: Range) -> Self605 fn expected_range(_: Range) -> Self { 606 UnexpectedParse::Unexpected 607 } 608 #[inline] expected_format<T>(_: T) -> Self where T: fmt::Display,609 fn expected_format<T>(_: T) -> Self 610 where 611 T: fmt::Display, 612 { 613 UnexpectedParse::Unexpected 614 } 615 #[inline] message_format<T>(_: T) -> Self where T: fmt::Display,616 fn message_format<T>(_: T) -> Self 617 where 618 T: fmt::Display, 619 { 620 UnexpectedParse::Unexpected 621 } 622 #[inline] message_token(_: Item) -> Self623 fn message_token(_: Item) -> Self { 624 UnexpectedParse::Unexpected 625 } 626 #[inline] message_range(_: Range) -> Self627 fn message_range(_: Range) -> Self { 628 UnexpectedParse::Unexpected 629 } 630 631 #[inline] end_of_input() -> Self632 fn end_of_input() -> Self { 633 UnexpectedParse::Eoi 634 } 635 636 #[inline] is_unexpected_end_of_input(&self) -> bool637 fn is_unexpected_end_of_input(&self) -> bool { 638 *self == UnexpectedParse::Eoi 639 } 640 641 #[inline] into_other<T>(self) -> T where T: StreamError<Item, Range>,642 fn into_other<T>(self) -> T 643 where 644 T: StreamError<Item, Range>, 645 { 646 match self { 647 UnexpectedParse::Unexpected => T::unexpected_static_message("parse"), 648 UnexpectedParse::Eoi => T::end_of_input(), 649 } 650 } 651 } 652 653 impl<Item, Range, Position> ParseError<Item, Range, Position> for UnexpectedParse 654 where 655 Position: Default, 656 { 657 type StreamError = Self; 658 #[inline] empty(_position: Position) -> Self659 fn empty(_position: Position) -> Self { 660 UnexpectedParse::Unexpected 661 } 662 663 #[inline] from_error(_: Position, err: Self::StreamError) -> Self664 fn from_error(_: Position, err: Self::StreamError) -> Self { 665 err 666 } 667 position(&self) -> Position668 fn position(&self) -> Position { 669 Position::default() 670 } 671 672 #[inline] set_position(&mut self, _position: Position)673 fn set_position(&mut self, _position: Position) {} 674 675 #[inline] add(&mut self, err: Self::StreamError)676 fn add(&mut self, err: Self::StreamError) { 677 *self = match (*self, err) { 678 (UnexpectedParse::Eoi, _) => UnexpectedParse::Eoi, 679 (_, err) => err, 680 }; 681 } 682 683 #[inline] set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) where F: FnOnce(&mut Tracked<Self>),684 fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) 685 where 686 F: FnOnce(&mut Tracked<Self>), 687 { 688 f(self_); 689 self_.error = info; 690 } 691 is_unexpected_end_of_input(&self) -> bool692 fn is_unexpected_end_of_input(&self) -> bool { 693 *self == UnexpectedParse::Eoi 694 } 695 696 #[inline] into_other<T>(self) -> T where T: ParseError<Item, Range, Position>,697 fn into_other<T>(self) -> T 698 where 699 T: ParseError<Item, Range, Position>, 700 { 701 T::from_error(Position::default(), StreamError::into_other(self)) 702 } 703 } 704 705 impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for UnexpectedParse 706 where 707 Position: Default, 708 { into_other_error<T, Item2, Range2, Position2>(self) -> T where T: ParseError<Item2, Range2, Position2>, Item2: From<Item>, Range2: From<Range>, Position2: From<Position>,709 fn into_other_error<T, Item2, Range2, Position2>(self) -> T 710 where 711 T: ParseError<Item2, Range2, Position2>, 712 Item2: From<Item>, 713 Range2: From<Range>, 714 Position2: From<Position>, 715 { 716 T::from_error( 717 Position::default().into(), 718 StreamErrorInto::<Item, Range>::into_other_error(self), 719 ) 720 } 721 } 722 723 impl<Item, Range> StreamErrorInto<Item, Range> for UnexpectedParse { into_other_error<T, Item2, Range2>(self) -> T where T: StreamError<Item2, Range2>, Item2: From<Item>, Range2: From<Range>,724 fn into_other_error<T, Item2, Range2>(self) -> T 725 where 726 T: StreamError<Item2, Range2>, 727 Item2: From<Item>, 728 Range2: From<Range>, 729 { 730 StreamError::into_other(self) 731 } 732 } 733 734 #[derive(Clone, Copy, Debug, PartialEq)] 735 pub enum StringStreamError { 736 UnexpectedParse, 737 Eoi, 738 CharacterBoundary, 739 } 740 741 pub(crate) const CHAR_BOUNDARY_ERROR_MESSAGE: &str = "unexpected slice on character boundary"; 742 743 impl fmt::Display for StringStreamError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result744 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 745 write!(f, "{}", self.as_str()) 746 } 747 } 748 749 #[cfg(feature = "std")] 750 impl StdError for StringStreamError { description(&self) -> &str751 fn description(&self) -> &str { 752 self.as_str() 753 } 754 } 755 756 impl StringStreamError { as_str(&self) -> &str757 fn as_str(&self) -> &str { 758 use self::StringStreamError::*; 759 match *self { 760 UnexpectedParse => "unexpected parse", 761 Eoi => "unexpected end of input", 762 CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE, 763 } 764 } 765 } 766 767 impl<Item, Range> StreamError<Item, Range> for StringStreamError { 768 #[inline] unexpected_token(_: Item) -> Self769 fn unexpected_token(_: Item) -> Self { 770 StringStreamError::UnexpectedParse 771 } 772 #[inline] unexpected_range(_: Range) -> Self773 fn unexpected_range(_: Range) -> Self { 774 StringStreamError::UnexpectedParse 775 } 776 #[inline] unexpected_format<T>(_msg: T) -> Self where T: fmt::Display,777 fn unexpected_format<T>(_msg: T) -> Self 778 where 779 T: fmt::Display, 780 { 781 StringStreamError::UnexpectedParse 782 } 783 784 #[inline] expected_token(_: Item) -> Self785 fn expected_token(_: Item) -> Self { 786 StringStreamError::UnexpectedParse 787 } 788 #[inline] expected_range(_: Range) -> Self789 fn expected_range(_: Range) -> Self { 790 StringStreamError::UnexpectedParse 791 } 792 #[inline] expected_format<T>(_: T) -> Self where T: fmt::Display,793 fn expected_format<T>(_: T) -> Self 794 where 795 T: fmt::Display, 796 { 797 StringStreamError::UnexpectedParse 798 } 799 #[inline] message_format<T>(_: T) -> Self where T: fmt::Display,800 fn message_format<T>(_: T) -> Self 801 where 802 T: fmt::Display, 803 { 804 StringStreamError::UnexpectedParse 805 } 806 #[inline] message_token(_: Item) -> Self807 fn message_token(_: Item) -> Self { 808 StringStreamError::UnexpectedParse 809 } 810 #[inline] message_range(_: Range) -> Self811 fn message_range(_: Range) -> Self { 812 StringStreamError::UnexpectedParse 813 } message_static_message(msg: &'static str) -> Self814 fn message_static_message(msg: &'static str) -> Self { 815 if msg == CHAR_BOUNDARY_ERROR_MESSAGE { 816 StringStreamError::CharacterBoundary 817 } else { 818 StringStreamError::UnexpectedParse 819 } 820 } 821 #[inline] end_of_input() -> Self822 fn end_of_input() -> Self { 823 StringStreamError::Eoi 824 } 825 #[inline] is_unexpected_end_of_input(&self) -> bool826 fn is_unexpected_end_of_input(&self) -> bool { 827 *self == StringStreamError::Eoi 828 } 829 #[inline] into_other<T>(self) -> T where T: StreamError<Item, Range>,830 fn into_other<T>(self) -> T 831 where 832 T: StreamError<Item, Range>, 833 { 834 let msg = match self { 835 StringStreamError::CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE, 836 StringStreamError::UnexpectedParse => "parse", 837 StringStreamError::Eoi => return T::end_of_input(), 838 }; 839 T::unexpected_static_message(msg) 840 } 841 } 842 impl<Item, Range, Position> ParseError<Item, Range, Position> for StringStreamError 843 where 844 Position: Default, 845 { 846 type StreamError = Self; 847 #[inline] empty(_position: Position) -> Self848 fn empty(_position: Position) -> Self { 849 StringStreamError::UnexpectedParse 850 } 851 #[inline] from_error(_: Position, err: Self::StreamError) -> Self852 fn from_error(_: Position, err: Self::StreamError) -> Self { 853 err 854 } 855 position(&self) -> Position856 fn position(&self) -> Position { 857 Position::default() 858 } 859 860 #[inline] set_position(&mut self, _position: Position)861 fn set_position(&mut self, _position: Position) {} 862 863 #[inline] add(&mut self, err: Self::StreamError)864 fn add(&mut self, err: Self::StreamError) { 865 *self = match (*self, err) { 866 (StringStreamError::Eoi, _) => StringStreamError::Eoi, 867 (_, err) => err, 868 }; 869 } 870 871 #[inline] set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) where F: FnOnce(&mut Tracked<Self>),872 fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) 873 where 874 F: FnOnce(&mut Tracked<Self>), 875 { 876 f(self_); 877 self_.error = info; 878 } 879 is_unexpected_end_of_input(&self) -> bool880 fn is_unexpected_end_of_input(&self) -> bool { 881 *self == StringStreamError::Eoi 882 } 883 884 #[inline] into_other<T>(self) -> T where T: ParseError<Item, Range, Position>,885 fn into_other<T>(self) -> T 886 where 887 T: ParseError<Item, Range, Position>, 888 { 889 T::from_error(Position::default(), StreamError::into_other(self)) 890 } 891 } 892 893 impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for StringStreamError 894 where 895 Position: Default, 896 { into_other_error<T, Item2, Range2, Position2>(self) -> T where T: ParseError<Item2, Range2, Position2>, Item2: From<Item>, Range2: From<Range>, Position2: From<Position>,897 fn into_other_error<T, Item2, Range2, Position2>(self) -> T 898 where 899 T: ParseError<Item2, Range2, Position2>, 900 Item2: From<Item>, 901 Range2: From<Range>, 902 Position2: From<Position>, 903 { 904 T::from_error( 905 Position::default().into(), 906 StreamErrorInto::<Item, Range>::into_other_error(self), 907 ) 908 } 909 } 910 911 impl<Item, Range> StreamErrorInto<Item, Range> for StringStreamError { into_other_error<T, Item2, Range2>(self) -> T where T: StreamError<Item2, Range2>, Item2: From<Item>, Range2: From<Range>,912 fn into_other_error<T, Item2, Range2>(self) -> T 913 where 914 T: StreamError<Item2, Range2>, 915 Item2: From<Item>, 916 Range2: From<Range>, 917 { 918 StreamError::into_other(self) 919 } 920 } 921 922 /// Error wrapper which lets parsers track which parser in a sequence of sub-parsers has emitted 923 /// the error. `Tracked::from` can be used to construct this and it should otherwise be 924 /// ignored outside of combine. 925 #[derive(Clone, PartialEq, Debug, Copy)] 926 pub struct Tracked<E> { 927 /// The error returned 928 pub error: E, 929 #[doc(hidden)] 930 pub offset: ErrorOffset, 931 } 932 933 impl<E> From<E> for Tracked<E> { from(error: E) -> Self934 fn from(error: E) -> Self { 935 Tracked { 936 error, 937 offset: ErrorOffset(1), 938 } 939 } 940 } 941 942 /// A `Result` type which has the committed status flattened into the result. 943 /// Conversions to and from `std::result::Result` can be done using `result.into()` or 944 /// `From::from(result)` 945 #[derive(Clone, PartialEq, Debug, Copy)] 946 pub enum ParseResult<T, E> { 947 /// The parser has succeeded and has committed to this parse. If a parser after this fails, 948 /// other parser alternatives will not be attempted (`CommitErr` will be returned) 949 CommitOk(T), 950 /// The parser has succeeded and has not committed to this parse. If a parser after this fails, 951 /// other parser alternatives will be attempted (`PeekErr` will be returned) 952 PeekOk(T), 953 /// The parser failed other parse alternatives will not be attempted. 954 CommitErr(E), 955 /// The parser failed but other parse alternatives may be attempted. 956 PeekErr(Tracked<E>), 957 } 958 959 impl<T, E> ParseResult<T, E> { 960 #[inline] is_ok(&self) -> bool961 pub fn is_ok(&self) -> bool { 962 match *self { 963 CommitOk(_) | PeekOk(_) => true, 964 CommitErr(_) | PeekErr(_) => false, 965 } 966 } 967 968 #[inline] is_err(&self) -> bool969 pub fn is_err(&self) -> bool { 970 !self.is_ok() 971 } 972 as_ref(&self) -> ParseResult<&T, &E>973 pub fn as_ref(&self) -> ParseResult<&T, &E> { 974 match *self { 975 CommitOk(ref t) => CommitOk(t), 976 PeekOk(ref t) => PeekOk(t), 977 CommitErr(ref e) => CommitErr(e), 978 PeekErr(ref e) => PeekErr(Tracked { 979 error: &e.error, 980 offset: e.offset, 981 }), 982 } 983 } 984 and_then<F, T2>(self, f: F) -> F::Output where F: FnOnce(T) -> ParseResult<T2, E>,985 pub fn and_then<F, T2>(self, f: F) -> F::Output 986 where 987 F: FnOnce(T) -> ParseResult<T2, E>, 988 { 989 match self { 990 CommitOk(t) => match f(t) { 991 CommitOk(t2) | PeekOk(t2) => CommitOk(t2), 992 PeekErr(e) => CommitErr(e.error), 993 CommitErr(e) => CommitErr(e), 994 }, 995 PeekOk(t) => f(t), 996 CommitErr(e) => CommitErr(e), 997 PeekErr(e) => PeekErr(e), 998 } 999 } 1000 map_err<F, E2>(self, f: F) -> ParseResult<T, F::Output> where F: FnOnce(E) -> E2,1001 pub fn map_err<F, E2>(self, f: F) -> ParseResult<T, F::Output> 1002 where 1003 F: FnOnce(E) -> E2, 1004 { 1005 match self { 1006 CommitOk(t) => CommitOk(t), 1007 PeekOk(t) => PeekOk(t), 1008 CommitErr(e) => CommitErr(f(e)), 1009 PeekErr(e) => PeekErr(Tracked { 1010 error: f(e.error), 1011 offset: e.offset, 1012 }), 1013 } 1014 } 1015 map<F, T2>(self, f: F) -> ParseResult<F::Output, E> where F: FnOnce(T) -> T2,1016 pub fn map<F, T2>(self, f: F) -> ParseResult<F::Output, E> 1017 where 1018 F: FnOnce(T) -> T2, 1019 { 1020 match self { 1021 CommitOk(t) => CommitOk(f(t)), 1022 PeekOk(t) => PeekOk(f(t)), 1023 CommitErr(e) => CommitErr(e), 1024 PeekErr(e) => PeekErr(e), 1025 } 1026 } 1027 } 1028 1029 impl<O, E> ParseResult<O, E> { into_result(self) -> StdParseResult2<O, E>1030 pub fn into_result(self) -> StdParseResult2<O, E> { 1031 self.into() 1032 } 1033 } 1034 1035 impl<T, E> Into<Result<Commit<T>, Commit<Tracked<E>>>> for ParseResult<T, E> { 1036 #[inline] into(self) -> Result<Commit<T>, Commit<Tracked<E>>>1037 fn into(self) -> Result<Commit<T>, Commit<Tracked<E>>> { 1038 match self { 1039 CommitOk(t) => Ok(Commit::Commit(t)), 1040 PeekOk(t) => Ok(Commit::Peek(t)), 1041 CommitErr(e) => Err(Commit::Commit(e.into())), 1042 PeekErr(e) => Err(Commit::Peek(e)), 1043 } 1044 } 1045 } 1046 1047 impl<O, E> Into<StdParseResult2<O, E>> for ParseResult<O, E> { 1048 #[inline] into(self) -> StdParseResult2<O, E>1049 fn into(self) -> StdParseResult2<O, E> { 1050 use self::ParseResult::*; 1051 1052 match self { 1053 CommitOk(t) => Ok((t, Commit::Commit(()))), 1054 PeekOk(t) => Ok((t, Commit::Peek(()))), 1055 CommitErr(e) => Err(Commit::Commit(e.into())), 1056 PeekErr(e) => Err(Commit::Peek(e)), 1057 } 1058 } 1059 } 1060 1061 impl<O, E> From<StdParseResult2<O, E>> for ParseResult<O, E> { 1062 #[inline] from(result: StdParseResult2<O, E>) -> ParseResult<O, E>1063 fn from(result: StdParseResult2<O, E>) -> ParseResult<O, E> { 1064 use self::ParseResult::*; 1065 1066 match result { 1067 Ok((t, Commit::Commit(()))) => CommitOk(t), 1068 Ok((t, Commit::Peek(()))) => PeekOk(t), 1069 Err(Commit::Commit(e)) => CommitErr(e.error), 1070 Err(Commit::Peek(e)) => PeekErr(e), 1071 } 1072 } 1073 } 1074 1075 #[cfg(all(feature = "std", test))] 1076 mod tests_std { 1077 1078 use crate::Parser; 1079 1080 #[derive(Clone, PartialEq, Debug)] 1081 struct CloneOnly { 1082 s: String, 1083 } 1084 1085 #[test] parse_clone_but_not_copy()1086 fn parse_clone_but_not_copy() { 1087 // This verifies we can parse slice references with an token type that is Clone but not Copy. 1088 let input = &[ 1089 CloneOnly { s: "x".to_string() }, 1090 CloneOnly { s: "y".to_string() }, 1091 ][..]; 1092 let result = crate::parser::range::take_while(|c: CloneOnly| c.s == "x").parse(input); 1093 assert_eq!( 1094 result, 1095 Ok(( 1096 &[CloneOnly { s: "x".to_string() }][..], 1097 &[CloneOnly { s: "y".to_string() }][..] 1098 )) 1099 ); 1100 } 1101 } 1102