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 /// { 300 /// let (c, committed) = satisfy(|c| c != '"').parse_stream(input).into_result()?; 301 /// match c { 302 /// //Since the `char` parser has already committed some of the input `combine` is used 303 /// //propagate the committed state to the next part of the parser 304 /// '\\' => committed.combine(|_| { 305 /// satisfy(|c| c == '"' || c == '\\') 306 /// .map(|c| { 307 /// match c { 308 /// '"' => '"', 309 /// '\\' => '\\', 310 /// c => c 311 /// } 312 /// }) 313 /// .parse_stream(input) 314 /// .into_result() 315 /// }), 316 /// _ => Ok((c, committed)) 317 /// } 318 /// } 319 /// let result = many(parser(char)) 320 /// .easy_parse(r#"abc\"\\"#); 321 /// assert_eq!(result, Ok((r#"abc"\"#.to_string(), ""))); 322 /// } 323 /// ``` combine<F, U, E>(self, f: F) -> StdParseResult2<U, E> where F: FnOnce(T) -> StdParseResult2<U, E>,324 pub fn combine<F, U, E>(self, f: F) -> StdParseResult2<U, E> 325 where 326 F: FnOnce(T) -> StdParseResult2<U, E>, 327 { 328 match self { 329 Commit::Commit(x) => match f(x) { 330 Ok((v, Commit::Peek(()))) => Ok((v, Commit::Commit(()))), 331 Err(Commit::Peek(err)) => Err(Commit::Commit(err)), 332 y => y, 333 }, 334 Commit::Peek(x) => f(x), 335 } 336 } combine_commit<F, U, E>(self, f: F) -> ParseResult<U, E> where F: FnOnce(T) -> ParseResult<U, E>,337 pub fn combine_commit<F, U, E>(self, f: F) -> ParseResult<U, E> 338 where 339 F: FnOnce(T) -> ParseResult<U, E>, 340 { 341 use self::ParseResult::*; 342 343 match self { 344 Commit::Commit(x) => match f(x) { 345 PeekOk(v) => CommitOk(v), 346 PeekErr(err) => CommitErr(err.error), 347 y => y, 348 }, 349 Commit::Peek(x) => f(x), 350 } 351 } 352 } 353 354 /// A type alias over the specific `Result` type used by parsers to indicate whether they were 355 /// successful or not. 356 /// `O` is the type that is output on success. 357 /// `Input` is the specific stream type used in the parser. 358 pub type StdParseResult<O, Input> = 359 Result<(O, Commit<()>), Commit<Tracked<<Input as StreamOnce>::Error>>>; 360 pub type StdParseResult2<O, E> = Result<(O, Commit<()>), Commit<Tracked<E>>>; 361 362 /// `StreamError` represents a single error returned from a `Stream` or a `Parser`. 363 /// 364 /// Usually multiple instances of `StreamError` is composed into a `ParseError` to build the final 365 /// error value. 366 pub trait StreamError<Item, Range>: Sized { unexpected_token(token: Item) -> Self367 fn unexpected_token(token: Item) -> Self; unexpected_range(token: Range) -> Self368 fn unexpected_range(token: Range) -> Self; unexpected_format<T>(msg: T) -> Self where T: fmt::Display369 fn unexpected_format<T>(msg: T) -> Self 370 where 371 T: fmt::Display; unexpected<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,372 fn unexpected<E>(info: E) -> Self 373 where 374 E: for<'s> ErrorInfo<'s, Item, Range>, 375 { 376 match info.into_info() { 377 Info::Token(b) => Self::unexpected_token(b), 378 Info::Range(b) => Self::unexpected_range(b), 379 Info::Static(b) => Self::unexpected_static_message(b), 380 Info::Format(b) => Self::unexpected_format(b), 381 } 382 } unexpected_static_message(msg: &'static str) -> Self383 fn unexpected_static_message(msg: &'static str) -> Self { 384 Self::unexpected_format(msg) 385 } 386 expected_token(token: Item) -> Self387 fn expected_token(token: Item) -> Self; expected_range(token: Range) -> Self388 fn expected_range(token: Range) -> Self; expected_format<T>(msg: T) -> Self where T: fmt::Display389 fn expected_format<T>(msg: T) -> Self 390 where 391 T: fmt::Display; expected<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,392 fn expected<E>(info: E) -> Self 393 where 394 E: for<'s> ErrorInfo<'s, Item, Range>, 395 { 396 match info.into_info() { 397 Info::Token(b) => Self::expected_token(b), 398 Info::Range(b) => Self::expected_range(b), 399 Info::Static(b) => Self::expected_static_message(b), 400 Info::Format(b) => Self::expected_format(b), 401 } 402 } expected_static_message(msg: &'static str) -> Self403 fn expected_static_message(msg: &'static str) -> Self { 404 Self::expected_format(msg) 405 } 406 message_token(token: Item) -> Self407 fn message_token(token: Item) -> Self; message_range(token: Range) -> Self408 fn message_range(token: Range) -> Self; message_format<T>(msg: T) -> Self where T: fmt::Display409 fn message_format<T>(msg: T) -> Self 410 where 411 T: fmt::Display; message_static_message(msg: &'static str) -> Self412 fn message_static_message(msg: &'static str) -> Self { 413 Self::message_format(msg) 414 } message<E>(info: E) -> Self where E: for<'s> ErrorInfo<'s, Item, Range>,415 fn message<E>(info: E) -> Self 416 where 417 E: for<'s> ErrorInfo<'s, Item, Range>, 418 { 419 match info.into_info() { 420 Info::Token(b) => Self::message_token(b), 421 Info::Range(b) => Self::message_range(b), 422 Info::Static(b) => Self::message_static_message(b), 423 Info::Format(b) => Self::message_format(b), 424 } 425 } 426 427 #[cfg(feature = "std")] other<E>(err: E) -> Self where E: StdError + Send + Sync + 'static,428 fn other<E>(err: E) -> Self 429 where 430 E: StdError + Send + Sync + 'static, 431 { 432 Self::message_format(err) 433 } 434 end_of_input() -> Self435 fn end_of_input() -> Self { 436 Self::unexpected_static_message("end of input") 437 } 438 is_unexpected_end_of_input(&self) -> bool439 fn is_unexpected_end_of_input(&self) -> bool; 440 441 /// Converts `self` into a different `StreamError` type. 442 /// 443 /// This should aim to preserve as much information as possible into the returned `T` value but 444 /// if `Self` ignores some information passed to it using one of the constructors that 445 /// information is naturally lost. into_other<T>(self) -> T where T: StreamError<Item, Range>446 fn into_other<T>(self) -> T 447 where 448 T: StreamError<Item, Range>; 449 } 450 451 /// Trait which defines a combine parse error. 452 /// 453 /// A parse error is composed of zero or more `StreamError` instances which gets added to it as 454 /// errors are encountered during parsing. 455 pub trait ParseError<Item, Range, Position>: Sized + PartialEq { 456 type StreamError: StreamError<Item, Range>; 457 458 /// Constructs an empty error. 459 /// 460 /// An empty error is expected to be cheap to create as it is frequently created and discarded. empty(position: Position) -> Self461 fn empty(position: Position) -> Self; 462 463 /// Creates a `ParseError` from a single `Self::StreamError` from_error(position: Position, err: Self::StreamError) -> Self464 fn from_error(position: Position, err: Self::StreamError) -> Self { 465 let mut errors = Self::empty(position); 466 errors.add(err); 467 errors 468 } 469 position(&self) -> Position470 fn position(&self) -> Position { 471 // TODO Remove the default implementation in a breaking release 472 unimplemented!() 473 } 474 475 /// Sets the position of this `ParseError` set_position(&mut self, position: Position)476 fn set_position(&mut self, position: Position); 477 478 /// Merges two errors. If they exist at the same position the errors of `other` are 479 /// added to `self` (using the semantics of `add`). If they are not at the same 480 /// position the error furthest ahead are returned, ignoring the other `ParseError`. merge(self, other: Self) -> Self481 fn merge(self, other: Self) -> Self { 482 other 483 } 484 485 /// Adds a `StreamError` to `self`. 486 /// 487 /// It is up to each individual error type to define what adding an error does, some may push 488 /// it to a vector while others may only keep `self` or `err` to avoid allocation add(&mut self, err: Self::StreamError)489 fn add(&mut self, err: Self::StreamError); 490 add_expected<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,491 fn add_expected<E>(&mut self, info: E) 492 where 493 E: for<'s> ErrorInfo<'s, Item, Range>, 494 { 495 self.add(Self::StreamError::expected(info)) 496 } 497 add_unexpected<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,498 fn add_unexpected<E>(&mut self, info: E) 499 where 500 E: for<'s> ErrorInfo<'s, Item, Range>, 501 { 502 self.add(Self::StreamError::unexpected(info)) 503 } 504 add_message<E>(&mut self, info: E) where E: for<'s> ErrorInfo<'s, Item, Range>,505 fn add_message<E>(&mut self, info: E) 506 where 507 E: for<'s> ErrorInfo<'s, Item, Range>, 508 { 509 self.add(Self::StreamError::message(info)) 510 } 511 512 /// 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>)513 fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) 514 where 515 F: FnOnce(&mut Tracked<Self>); 516 517 /// Removes any expected errors currently in `self` clear_expected(&mut self)518 fn clear_expected(&mut self) {} 519 is_unexpected_end_of_input(&self) -> bool520 fn is_unexpected_end_of_input(&self) -> bool; 521 522 /// Does a best-effort conversion of `self` into another `ParseError` into_other<T>(self) -> T where T: ParseError<Item, Range, Position>523 fn into_other<T>(self) -> T 524 where 525 T: ParseError<Item, Range, Position>; 526 } 527 528 /// Defines a conversion between two parse error types. 529 /// 530 /// Like `ParseError::into_other` but with a more general signature 531 /// (This will take the place of `into_other` on breaking release of combine) 532 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>533 fn into_other_error<T, Item2, Range2, Position2>(self) -> T 534 where 535 T: ParseError<Item2, Range2, Position2>, 536 Item2: From<Item>, 537 Range2: From<Range>, 538 Position2: From<Position>; 539 } 540 541 /// Defines a conversion between two stream error types. 542 /// 543 /// Like `StreamError::into_other` but with a more general signature 544 /// (This will take the place of `into_other` on breaking release of combine) 545 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>546 fn into_other_error<T, Item2, Range2>(self) -> T 547 where 548 T: StreamError<Item2, Range2>, 549 Item2: From<Item>, 550 Range2: From<Range>; 551 } 552 553 #[derive(Clone, Copy, Debug, PartialEq)] 554 pub enum UnexpectedParse { 555 Eoi, 556 Unexpected, 557 } 558 559 impl fmt::Display for UnexpectedParse { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result560 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 561 write!(f, "{}", self.as_str()) 562 } 563 } 564 565 #[cfg(feature = "std")] 566 impl StdError for UnexpectedParse { description(&self) -> &str567 fn description(&self) -> &str { 568 self.as_str() 569 } 570 } 571 572 impl UnexpectedParse { as_str(&self) -> &str573 fn as_str(&self) -> &str { 574 use self::UnexpectedParse::*; 575 match *self { 576 Unexpected => "unexpected parse", 577 Eoi => "unexpected end of input", 578 } 579 } 580 } 581 582 impl<Item, Range> StreamError<Item, Range> for UnexpectedParse { 583 #[inline] unexpected_token(_: Item) -> Self584 fn unexpected_token(_: Item) -> Self { 585 UnexpectedParse::Unexpected 586 } 587 #[inline] unexpected_range(_: Range) -> Self588 fn unexpected_range(_: Range) -> Self { 589 UnexpectedParse::Unexpected 590 } 591 #[inline] unexpected_format<T>(_: T) -> Self where T: fmt::Display,592 fn unexpected_format<T>(_: T) -> Self 593 where 594 T: fmt::Display, 595 { 596 UnexpectedParse::Unexpected 597 } 598 599 #[inline] expected_token(_: Item) -> Self600 fn expected_token(_: Item) -> Self { 601 UnexpectedParse::Unexpected 602 } 603 #[inline] expected_range(_: Range) -> Self604 fn expected_range(_: Range) -> Self { 605 UnexpectedParse::Unexpected 606 } 607 #[inline] expected_format<T>(_: T) -> Self where T: fmt::Display,608 fn expected_format<T>(_: T) -> Self 609 where 610 T: fmt::Display, 611 { 612 UnexpectedParse::Unexpected 613 } 614 #[inline] message_format<T>(_: T) -> Self where T: fmt::Display,615 fn message_format<T>(_: T) -> Self 616 where 617 T: fmt::Display, 618 { 619 UnexpectedParse::Unexpected 620 } 621 #[inline] message_token(_: Item) -> Self622 fn message_token(_: Item) -> Self { 623 UnexpectedParse::Unexpected 624 } 625 #[inline] message_range(_: Range) -> Self626 fn message_range(_: Range) -> Self { 627 UnexpectedParse::Unexpected 628 } 629 630 #[inline] end_of_input() -> Self631 fn end_of_input() -> Self { 632 UnexpectedParse::Eoi 633 } 634 635 #[inline] is_unexpected_end_of_input(&self) -> bool636 fn is_unexpected_end_of_input(&self) -> bool { 637 *self == UnexpectedParse::Eoi 638 } 639 640 #[inline] into_other<T>(self) -> T where T: StreamError<Item, Range>,641 fn into_other<T>(self) -> T 642 where 643 T: StreamError<Item, Range>, 644 { 645 match self { 646 UnexpectedParse::Unexpected => T::unexpected_static_message("parse"), 647 UnexpectedParse::Eoi => T::end_of_input(), 648 } 649 } 650 } 651 652 impl<Item, Range, Position> ParseError<Item, Range, Position> for UnexpectedParse 653 where 654 Position: Default, 655 { 656 type StreamError = Self; 657 #[inline] empty(_position: Position) -> Self658 fn empty(_position: Position) -> Self { 659 UnexpectedParse::Unexpected 660 } 661 662 #[inline] from_error(_: Position, err: Self::StreamError) -> Self663 fn from_error(_: Position, err: Self::StreamError) -> Self { 664 err 665 } 666 position(&self) -> Position667 fn position(&self) -> Position { 668 Position::default() 669 } 670 671 #[inline] set_position(&mut self, _position: Position)672 fn set_position(&mut self, _position: Position) {} 673 674 #[inline] add(&mut self, err: Self::StreamError)675 fn add(&mut self, err: Self::StreamError) { 676 *self = match (*self, err) { 677 (UnexpectedParse::Eoi, _) => UnexpectedParse::Eoi, 678 (_, err) => err, 679 }; 680 } 681 682 #[inline] set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) where F: FnOnce(&mut Tracked<Self>),683 fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) 684 where 685 F: FnOnce(&mut Tracked<Self>), 686 { 687 f(self_); 688 self_.error = info; 689 } 690 is_unexpected_end_of_input(&self) -> bool691 fn is_unexpected_end_of_input(&self) -> bool { 692 *self == UnexpectedParse::Eoi 693 } 694 695 #[inline] into_other<T>(self) -> T where T: ParseError<Item, Range, Position>,696 fn into_other<T>(self) -> T 697 where 698 T: ParseError<Item, Range, Position>, 699 { 700 T::from_error(Position::default(), StreamError::into_other(self)) 701 } 702 } 703 704 impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for UnexpectedParse 705 where 706 Position: Default, 707 { into_other_error<T, Item2, Range2, Position2>(self) -> T where T: ParseError<Item2, Range2, Position2>, Item2: From<Item>, Range2: From<Range>, Position2: From<Position>,708 fn into_other_error<T, Item2, Range2, Position2>(self) -> T 709 where 710 T: ParseError<Item2, Range2, Position2>, 711 Item2: From<Item>, 712 Range2: From<Range>, 713 Position2: From<Position>, 714 { 715 T::from_error( 716 Position::default().into(), 717 StreamErrorInto::<Item, Range>::into_other_error(self), 718 ) 719 } 720 } 721 722 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>,723 fn into_other_error<T, Item2, Range2>(self) -> T 724 where 725 T: StreamError<Item2, Range2>, 726 Item2: From<Item>, 727 Range2: From<Range>, 728 { 729 StreamError::into_other(self) 730 } 731 } 732 733 #[derive(Clone, Copy, Debug, PartialEq)] 734 pub enum StringStreamError { 735 UnexpectedParse, 736 Eoi, 737 CharacterBoundary, 738 } 739 740 pub(crate) const CHAR_BOUNDARY_ERROR_MESSAGE: &str = "unexpected slice on character boundary"; 741 742 impl fmt::Display for StringStreamError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result743 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 744 write!(f, "{}", self.as_str()) 745 } 746 } 747 748 #[cfg(feature = "std")] 749 impl StdError for StringStreamError { description(&self) -> &str750 fn description(&self) -> &str { 751 self.as_str() 752 } 753 } 754 755 impl StringStreamError { as_str(&self) -> &str756 fn as_str(&self) -> &str { 757 use self::StringStreamError::*; 758 match *self { 759 UnexpectedParse => "unexpected parse", 760 Eoi => "unexpected end of input", 761 CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE, 762 } 763 } 764 } 765 766 impl<Item, Range> StreamError<Item, Range> for StringStreamError { 767 #[inline] unexpected_token(_: Item) -> Self768 fn unexpected_token(_: Item) -> Self { 769 StringStreamError::UnexpectedParse 770 } 771 #[inline] unexpected_range(_: Range) -> Self772 fn unexpected_range(_: Range) -> Self { 773 StringStreamError::UnexpectedParse 774 } 775 #[inline] unexpected_format<T>(_msg: T) -> Self where T: fmt::Display,776 fn unexpected_format<T>(_msg: T) -> Self 777 where 778 T: fmt::Display, 779 { 780 StringStreamError::UnexpectedParse 781 } 782 783 #[inline] expected_token(_: Item) -> Self784 fn expected_token(_: Item) -> Self { 785 StringStreamError::UnexpectedParse 786 } 787 #[inline] expected_range(_: Range) -> Self788 fn expected_range(_: Range) -> Self { 789 StringStreamError::UnexpectedParse 790 } 791 #[inline] expected_format<T>(_: T) -> Self where T: fmt::Display,792 fn expected_format<T>(_: T) -> Self 793 where 794 T: fmt::Display, 795 { 796 StringStreamError::UnexpectedParse 797 } 798 #[inline] message_format<T>(_: T) -> Self where T: fmt::Display,799 fn message_format<T>(_: T) -> Self 800 where 801 T: fmt::Display, 802 { 803 StringStreamError::UnexpectedParse 804 } 805 #[inline] message_token(_: Item) -> Self806 fn message_token(_: Item) -> Self { 807 StringStreamError::UnexpectedParse 808 } 809 #[inline] message_range(_: Range) -> Self810 fn message_range(_: Range) -> Self { 811 StringStreamError::UnexpectedParse 812 } message_static_message(msg: &'static str) -> Self813 fn message_static_message(msg: &'static str) -> Self { 814 if msg == CHAR_BOUNDARY_ERROR_MESSAGE { 815 StringStreamError::CharacterBoundary 816 } else { 817 StringStreamError::UnexpectedParse 818 } 819 } 820 #[inline] end_of_input() -> Self821 fn end_of_input() -> Self { 822 StringStreamError::Eoi 823 } 824 #[inline] is_unexpected_end_of_input(&self) -> bool825 fn is_unexpected_end_of_input(&self) -> bool { 826 *self == StringStreamError::Eoi 827 } 828 #[inline] into_other<T>(self) -> T where T: StreamError<Item, Range>,829 fn into_other<T>(self) -> T 830 where 831 T: StreamError<Item, Range>, 832 { 833 let msg = match self { 834 StringStreamError::CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE, 835 StringStreamError::UnexpectedParse => "parse", 836 StringStreamError::Eoi => return T::end_of_input(), 837 }; 838 T::unexpected_static_message(msg) 839 } 840 } 841 impl<Item, Range, Position> ParseError<Item, Range, Position> for StringStreamError 842 where 843 Position: Default, 844 { 845 type StreamError = Self; 846 #[inline] empty(_position: Position) -> Self847 fn empty(_position: Position) -> Self { 848 StringStreamError::UnexpectedParse 849 } 850 #[inline] from_error(_: Position, err: Self::StreamError) -> Self851 fn from_error(_: Position, err: Self::StreamError) -> Self { 852 err 853 } 854 position(&self) -> Position855 fn position(&self) -> Position { 856 Position::default() 857 } 858 859 #[inline] set_position(&mut self, _position: Position)860 fn set_position(&mut self, _position: Position) {} 861 862 #[inline] add(&mut self, err: Self::StreamError)863 fn add(&mut self, err: Self::StreamError) { 864 *self = match (*self, err) { 865 (StringStreamError::Eoi, _) => StringStreamError::Eoi, 866 (_, err) => err, 867 }; 868 } 869 870 #[inline] set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) where F: FnOnce(&mut Tracked<Self>),871 fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F) 872 where 873 F: FnOnce(&mut Tracked<Self>), 874 { 875 f(self_); 876 self_.error = info; 877 } 878 is_unexpected_end_of_input(&self) -> bool879 fn is_unexpected_end_of_input(&self) -> bool { 880 *self == StringStreamError::Eoi 881 } 882 883 #[inline] into_other<T>(self) -> T where T: ParseError<Item, Range, Position>,884 fn into_other<T>(self) -> T 885 where 886 T: ParseError<Item, Range, Position>, 887 { 888 T::from_error(Position::default(), StreamError::into_other(self)) 889 } 890 } 891 892 impl<Item, Range, Position> ParseErrorInto<Item, Range, Position> for StringStreamError 893 where 894 Position: Default, 895 { into_other_error<T, Item2, Range2, Position2>(self) -> T where T: ParseError<Item2, Range2, Position2>, Item2: From<Item>, Range2: From<Range>, Position2: From<Position>,896 fn into_other_error<T, Item2, Range2, Position2>(self) -> T 897 where 898 T: ParseError<Item2, Range2, Position2>, 899 Item2: From<Item>, 900 Range2: From<Range>, 901 Position2: From<Position>, 902 { 903 T::from_error( 904 Position::default().into(), 905 StreamErrorInto::<Item, Range>::into_other_error(self), 906 ) 907 } 908 } 909 910 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>,911 fn into_other_error<T, Item2, Range2>(self) -> T 912 where 913 T: StreamError<Item2, Range2>, 914 Item2: From<Item>, 915 Range2: From<Range>, 916 { 917 StreamError::into_other(self) 918 } 919 } 920 921 /// Error wrapper which lets parsers track which parser in a sequence of sub-parsers has emitted 922 /// the error. `Tracked::from` can be used to construct this and it should otherwise be 923 /// ignored outside of combine. 924 #[derive(Clone, PartialEq, Debug, Copy)] 925 pub struct Tracked<E> { 926 /// The error returned 927 pub error: E, 928 #[doc(hidden)] 929 pub offset: ErrorOffset, 930 } 931 932 impl<E> From<E> for Tracked<E> { from(error: E) -> Self933 fn from(error: E) -> Self { 934 Tracked { 935 error, 936 offset: ErrorOffset(1), 937 } 938 } 939 } 940 941 /// A `Result` type which has the committed status flattened into the result. 942 /// Conversions to and from `std::result::Result` can be done using `result.into()` or 943 /// `From::from(result)` 944 #[derive(Clone, PartialEq, Debug, Copy)] 945 pub enum ParseResult<T, E> { 946 /// The parser has succeeded and has committed to this parse. If a parser after this fails, 947 /// other parser alternatives will not be attempted (`CommitErr` will be returned) 948 CommitOk(T), 949 /// The parser has succeeded and has not committed to this parse. If a parser after this fails, 950 /// other parser alternatives will be attempted (`PeekErr` will be returned) 951 PeekOk(T), 952 /// The parser failed other parse alternatives will not be attempted. 953 CommitErr(E), 954 /// The parser failed but other parse alternatives may be attempted. 955 PeekErr(Tracked<E>), 956 } 957 958 impl<T, E> ParseResult<T, E> { 959 #[inline] is_ok(&self) -> bool960 pub fn is_ok(&self) -> bool { 961 match *self { 962 CommitOk(_) | PeekOk(_) => true, 963 CommitErr(_) | PeekErr(_) => false, 964 } 965 } 966 967 #[inline] is_err(&self) -> bool968 pub fn is_err(&self) -> bool { 969 !self.is_ok() 970 } 971 as_ref(&self) -> ParseResult<&T, &E>972 pub fn as_ref(&self) -> ParseResult<&T, &E> { 973 match *self { 974 CommitOk(ref t) => CommitOk(t), 975 PeekOk(ref t) => PeekOk(t), 976 CommitErr(ref e) => CommitErr(e), 977 PeekErr(ref e) => PeekErr(Tracked { 978 error: &e.error, 979 offset: e.offset, 980 }), 981 } 982 } 983 and_then<F, T2>(self, f: F) -> F::Output where F: FnOnce(T) -> ParseResult<T2, E>,984 pub fn and_then<F, T2>(self, f: F) -> F::Output 985 where 986 F: FnOnce(T) -> ParseResult<T2, E>, 987 { 988 match self { 989 CommitOk(t) => match f(t) { 990 CommitOk(t2) | PeekOk(t2) => CommitOk(t2), 991 PeekErr(e) => CommitErr(e.error), 992 CommitErr(e) => CommitErr(e), 993 }, 994 PeekOk(t) => f(t), 995 CommitErr(e) => CommitErr(e), 996 PeekErr(e) => PeekErr(e), 997 } 998 } 999 map_err<F, E2>(self, f: F) -> ParseResult<T, F::Output> where F: FnOnce(E) -> E2,1000 pub fn map_err<F, E2>(self, f: F) -> ParseResult<T, F::Output> 1001 where 1002 F: FnOnce(E) -> E2, 1003 { 1004 match self { 1005 CommitOk(t) => CommitOk(t), 1006 PeekOk(t) => PeekOk(t), 1007 CommitErr(e) => CommitErr(f(e)), 1008 PeekErr(e) => PeekErr(Tracked { 1009 error: f(e.error), 1010 offset: e.offset, 1011 }), 1012 } 1013 } 1014 map<F, T2>(self, f: F) -> ParseResult<F::Output, E> where F: FnOnce(T) -> T2,1015 pub fn map<F, T2>(self, f: F) -> ParseResult<F::Output, E> 1016 where 1017 F: FnOnce(T) -> T2, 1018 { 1019 match self { 1020 CommitOk(t) => CommitOk(f(t)), 1021 PeekOk(t) => PeekOk(f(t)), 1022 CommitErr(e) => CommitErr(e), 1023 PeekErr(e) => PeekErr(e), 1024 } 1025 } 1026 } 1027 1028 impl<O, E> ParseResult<O, E> { into_result(self) -> StdParseResult2<O, E>1029 pub fn into_result(self) -> StdParseResult2<O, E> { 1030 self.into() 1031 } 1032 } 1033 1034 impl<T, E> Into<Result<Commit<T>, Commit<Tracked<E>>>> for ParseResult<T, E> { 1035 #[inline] into(self) -> Result<Commit<T>, Commit<Tracked<E>>>1036 fn into(self) -> Result<Commit<T>, Commit<Tracked<E>>> { 1037 match self { 1038 CommitOk(t) => Ok(Commit::Commit(t)), 1039 PeekOk(t) => Ok(Commit::Peek(t)), 1040 CommitErr(e) => Err(Commit::Commit(e.into())), 1041 PeekErr(e) => Err(Commit::Peek(e)), 1042 } 1043 } 1044 } 1045 1046 impl<O, E> Into<StdParseResult2<O, E>> for ParseResult<O, E> { 1047 #[inline] into(self) -> StdParseResult2<O, E>1048 fn into(self) -> StdParseResult2<O, E> { 1049 use self::ParseResult::*; 1050 1051 match self { 1052 CommitOk(t) => Ok((t, Commit::Commit(()))), 1053 PeekOk(t) => Ok((t, Commit::Peek(()))), 1054 CommitErr(e) => Err(Commit::Commit(e.into())), 1055 PeekErr(e) => Err(Commit::Peek(e)), 1056 } 1057 } 1058 } 1059 1060 impl<O, E> From<StdParseResult2<O, E>> for ParseResult<O, E> { 1061 #[inline] from(result: StdParseResult2<O, E>) -> ParseResult<O, E>1062 fn from(result: StdParseResult2<O, E>) -> ParseResult<O, E> { 1063 use self::ParseResult::*; 1064 1065 match result { 1066 Ok((t, Commit::Commit(()))) => CommitOk(t), 1067 Ok((t, Commit::Peek(()))) => PeekOk(t), 1068 Err(Commit::Commit(e)) => CommitErr(e.error), 1069 Err(Commit::Peek(e)) => PeekErr(e), 1070 } 1071 } 1072 } 1073 1074 #[cfg(all(feature = "std", test))] 1075 mod tests_std { 1076 1077 use crate::Parser; 1078 1079 #[derive(Clone, PartialEq, Debug)] 1080 struct CloneOnly { 1081 s: String, 1082 } 1083 1084 #[test] parse_clone_but_not_copy()1085 fn parse_clone_but_not_copy() { 1086 // This verifies we can parse slice references with an token type that is Clone but not Copy. 1087 let input = &[ 1088 CloneOnly { s: "x".to_string() }, 1089 CloneOnly { s: "y".to_string() }, 1090 ][..]; 1091 let result = crate::parser::range::take_while(|c: CloneOnly| c.s == "x").parse(input); 1092 assert_eq!( 1093 result, 1094 Ok(( 1095 &[CloneOnly { s: "x".to_string() }][..], 1096 &[CloneOnly { s: "y".to_string() }][..] 1097 )) 1098 ); 1099 } 1100 } 1101