peresil/
lib.rs

1//! A simple and simplistic parsing library
2//!
3//! ### Example
4//!
5//! ```
6//! #[macro_use]
7//! extern crate peresil;
8//!
9//! use peresil::{ParseMaster,Progress,Recoverable,Status,StringPoint};
10//!
11//! type DemoMaster<'a> = ParseMaster<StringPoint<'a>, DemoError>;
12//! type DemoProgress<'a, T> = Progress<StringPoint<'a>, T, DemoError>;
13//! enum DemoError {
14//!     ExpectedGreeting,
15//!     ExpectedWhitespace,
16//!     ExpectedObject,
17//! }
18//!
19//! impl Recoverable for DemoError {
20//!     fn recoverable(&self) -> bool { true }
21//! }
22//!
23//! fn parse_basic<'a>(pm: &mut DemoMaster<'a>, pt: StringPoint<'a>)
24//!                   -> DemoProgress<'a, (&'a str, &'a str)>
25//! {
26//!     let tmp = pm.alternate()
27//!         .one(|_| pt.consume_literal("goodbye").map_err(|_| DemoError::ExpectedGreeting))
28//!         .one(|_| pt.consume_literal("hello").map_err(|_| DemoError::ExpectedGreeting))
29//!         .finish();
30//!     let (pt, greeting) = try_parse!(tmp);
31//!
32//!     let (pt, _) = try_parse!(pt.consume_literal(" ").map_err(|_| DemoError::ExpectedWhitespace));
33//!
34//!     let tmp = pm.alternate()
35//!         .one(|_| pt.consume_literal("world").map_err(|_| DemoError::ExpectedObject))
36//!         .one(|_| pt.consume_literal("moon").map_err(|_| DemoError::ExpectedObject))
37//!         .finish();
38//!     let (pt, object) = try_parse!(tmp);
39//!
40//!     Progress::success(pt, (greeting, object))
41//! }
42//!
43//! fn main() {
44//!     let mut pm = ParseMaster::new();
45//!     let pt = StringPoint::new("hello world");
46//!
47//!     let result = parse_basic(&mut pm, pt);
48//!     let (greeting, object) = match pm.finish(result) {
49//!         Progress { status: Status::Success(v), .. } => v,
50//!         Progress { status: Status::Failure(..), .. } => panic!("Did not parse"),
51//!     };
52//!
53//!     println!("Parsed [{}], [{}]", greeting, object);
54//! }
55//!
56
57/// A location in the parsed data
58pub trait Point: Ord + Copy {
59    /// The initial point
60    fn zero() -> Self;
61}
62
63impl Point for usize { fn zero() -> usize { 0 } }
64impl Point for i32 { fn zero() -> i32 { 0 } }
65
66/// Indicate if an error should terminate all parsing.
67///
68/// Non-recoverable errors will not allow for alternatives to be
69/// tried, basically unwinding the parsing stack all the way back to
70/// the beginning. Unrecoverable errors are useful for errors that
71/// indicate that the content was well-formed but not semantically
72/// correct.
73pub trait Recoverable {
74    fn recoverable(&self) -> bool;
75}
76
77#[derive(Debug,PartialEq)]
78struct Failures<P, E> {
79    point: P,
80    kinds: Vec<E>,
81}
82
83use std::cmp::Ordering;
84
85impl<P, E> Failures<P, E>
86    where P: Point,
87{
88    fn new() -> Failures<P, E> { Failures { point: P::zero(), kinds: Vec::new() } }
89
90    fn add(&mut self, point: P, failure: E) {
91        match point.cmp(&self.point) {
92            Ordering::Less => {
93                // Do nothing, our existing failures are better
94            },
95            Ordering::Greater => {
96                // The new failure is better, toss existing failures
97                self.replace(point, failure);
98            },
99            Ordering::Equal => {
100                // Multiple failures at the same point, tell the user all
101                // the ways they could do better.
102                self.kinds.push(failure);
103            },
104        }
105    }
106
107    fn replace(&mut self, point: P, failure: E) {
108        self.point = point;
109        self.kinds.clear();
110        self.kinds.push(failure);
111    }
112
113    fn into_progress<T>(self) -> Progress<P, T, Vec<E>> {
114        Progress { point: self.point, status: Status::Failure(self.kinds) }
115    }
116}
117
118/// An analog to `Result`, specialized for parsing.
119#[derive(Debug,PartialEq)]
120pub enum Status<T, E> {
121    Success(T),
122    Failure(E)
123}
124
125impl<T, E> Status<T, E> {
126    fn map<F, T2>(self, f: F) -> Status<T2, E>
127        where F: FnOnce(T) -> T2
128    {
129        match self {
130            Status::Success(x) => Status::Success(f(x)),
131            Status::Failure(x) => Status::Failure(x),
132        }
133    }
134
135    fn map_err<F, E2>(self, f: F) -> Status<T, E2>
136        where F: FnOnce(E) -> E2
137    {
138        match self {
139            Status::Success(x) => Status::Success(x),
140            Status::Failure(x) => Status::Failure(f(x)),
141        }
142    }
143}
144
145/// Tracks where the parser currently is and if it is successful.
146///
147/// On success, some value has been parsed. On failure, nothing has
148/// been parsed and the value indicates the reason for the failure.
149/// The returned point indicates where to next start parsing, often
150/// unchanged on failure.
151#[must_use]
152#[derive(Debug,PartialEq)]
153pub struct Progress<P, T, E> {
154    /// The current location.
155    pub point: P,
156    /// If the point indicates the location of a successful or failed parse.
157    pub status: Status<T, E>,
158}
159
160impl<P, T, E> Progress<P, T, E> {
161    pub fn success(point: P, val: T) -> Progress<P, T, E> {
162        Progress { point: point, status: Status::Success(val) }
163    }
164
165    pub fn failure(point: P, val: E) -> Progress<P, T, E> {
166        Progress { point: point, status: Status::Failure(val) }
167    }
168
169    /// Convert the success value, if there is one.
170    pub fn map<F, T2>(self, f: F) -> Progress<P, T2, E>
171        where F: FnOnce(T) -> T2
172    {
173        Progress { point: self.point, status: self.status.map(f) }
174    }
175
176    /// Convert the failure value, if there is one.
177    pub fn map_err<F, E2>(self, f: F) -> Progress<P, T, E2>
178        where F: FnOnce(E) -> E2
179    {
180        Progress { point: self.point, status: self.status.map_err(f) }
181    }
182
183    /// Returns the value on success, or rewinds the point and returns
184    /// `None` on failure.
185    pub fn optional(self, reset_to: P) -> (P, Option<T>) {
186        // If we fail N optionals and then a required, it'd be nice to
187        // report all the optional things. Might be difficult to do
188        // that and return the optional value.
189        match self {
190            Progress { status: Status::Success(val), point } => (point, Some(val)),
191            Progress { status: Status::Failure(..), .. } => (reset_to, None),
192        }
193    }
194}
195
196/// The main entrypoint to parsing.
197///
198/// This tracks the collection of outstanding errors and provides
199/// helper methods for parsing alternative paths and sequences of
200/// other parsers.
201#[derive(Debug,PartialEq)]
202pub struct ParseMaster<P, E> {
203    failures: Failures<P, E>,
204}
205
206impl<'a, P, E> ParseMaster<P, E>
207    where P: Point,
208          E: Recoverable,
209{
210    pub fn new() -> ParseMaster<P, E> {
211        ParseMaster {
212            failures: Failures::new(),
213        }
214    }
215
216    fn consume<T>(&mut self, progress: Progress<P, T, E>) -> Progress<P, T, ()> {
217        match progress {
218            Progress { status: Status::Success(..), .. } => progress.map_err(|_| ()),
219            Progress { status: Status::Failure(f), point } => {
220                if f.recoverable() {
221                    self.failures.add(point, f);
222                } else {
223                    self.failures.replace(point, f);
224                }
225                Progress { status: Status::Failure(()), point: point }
226            }
227        }
228    }
229
230    /// Returns the value on success, or rewinds the point and returns
231    /// `None` on a recoverable failure. Non-recoverable failures are
232    /// propagated.
233    pub fn optional<T, F>(&mut self, point: P, mut parser: F)
234                          -> Progress<P, Option<T>, E>
235        where F: FnMut(&mut ParseMaster<P, E>, P) -> Progress<P, T, E>,
236    {
237        let orig_point = point;
238        // If we fail N optionals and then a required, it'd be nice to
239        // report all the optional things. Might be difficult to do
240        // that and return the optional value.
241        match parser(self, point) {
242            Progress { status: Status::Success(val), point } => {
243                Progress::success(point, Some(val))
244            },
245            Progress { status: Status::Failure(f), point } => {
246                if f.recoverable() {
247                    Progress::success(orig_point, None)
248                } else {
249                    Progress::failure(point, f)
250                }
251            },
252        }
253    }
254
255    /// Run sub-parsers in order until one succeeds.
256    pub fn alternate<'pm, T>(&'pm mut self) -> Alternate<'pm, P, T, E> {
257        Alternate {
258            master: self,
259            current: None,
260        }
261    }
262
263    /// Runs the parser until it fails.
264    ///
265    /// If the parser fails due to a recoverable error, a collection
266    /// of values will be returned and the point will be at the end of
267    /// the last successful parse.  If the error is not recoverable,
268    /// the error will be passed through directly.
269    pub fn zero_or_more<F, T>(&mut self, point: P, mut parser: F) -> Progress<P, Vec<T>, E>
270        where F: FnMut(&mut ParseMaster<P, E>, P) -> Progress<P, T, E>
271    {
272        let mut current_point = point;
273        let mut values = Vec::new();
274
275        loop {
276            let progress = parser(self, current_point);
277            match progress {
278                Progress { status: Status::Success(v), point } => {
279                    values.push(v);
280                    current_point = point;
281                },
282                Progress { status: Status::Failure(f), point } => {
283                    if f.recoverable() {
284                        self.failures.add(point, f);
285                        break;
286                    } else {
287                        return Progress { status: Status::Failure(f), point: point };
288                    }
289                },
290            }
291        }
292
293        Progress { status: Status::Success(values), point: current_point }
294    }
295
296    /// When parsing is complete, provide the final result and gain
297    /// access to all failures. Will be recycled and may be used for
298    /// further parsing.
299    pub fn finish<T>(&mut self, progress: Progress<P, T, E>) -> Progress<P, T, Vec<E>> {
300        let progress = self.consume(progress);
301
302        match progress {
303            Progress { status: Status::Success(..), .. } => progress.map_err(|_| Vec::new()),
304            Progress { status: Status::Failure(..), .. } => {
305                use std::mem;
306                let f = mem::replace(&mut self.failures, Failures::new());
307                f.into_progress()
308            },
309        }
310    }
311}
312
313/// Follows the first successful parsing path.
314#[must_use]
315pub struct Alternate<'pm, P : 'pm, T, E : 'pm> {
316    master: &'pm mut ParseMaster<P, E>,
317    current: Option<Progress<P, T, E>>,
318}
319
320impl<'pm, P, T, E> Alternate<'pm, P, T, E>
321    where P: Point,
322          E: Recoverable,
323{
324    fn run_one<F>(&mut self, parser: F)
325        where F: FnOnce(&mut ParseMaster<P, E>) -> Progress<P, T, E>
326    {
327        let r = parser(self.master);
328        if let Some(prev) = self.current.take() {
329            // We don't care about the previous error, once we've consumed it
330            let _ = self.master.consume(prev);
331        }
332        self.current = Some(r);
333    }
334
335    /// Run one alternative parser.
336    pub fn one<F>(mut self, parser: F) -> Alternate<'pm, P, T, E>
337        where F: FnOnce(&mut ParseMaster<P, E>) -> Progress<P, T, E>
338    {
339        let recoverable =
340            if let Some(Progress { status: Status::Failure(ref f), .. }) = self.current {
341                f.recoverable()
342            } else {
343                false
344            };
345
346        match self.current {
347            None => self.run_one(parser),
348            Some(Progress { status: Status::Success(..), .. }) => {},
349            Some(Progress { status: Status::Failure(..), .. })
350                if recoverable => self.run_one(parser),
351            Some(Progress { status: Status::Failure(..), .. }) => {},
352        }
353
354        self
355    }
356
357    /// Complete the alternatives, returning the first successful branch.
358    pub fn finish(self) -> Progress<P, T, E> {
359        self.current.unwrap()
360    }
361}
362
363/// An analog to `try!`, but for `Progress`
364#[macro_export]
365macro_rules! try_parse(
366    ($e:expr) => ({
367        match $e {
368            $crate::Progress { status: $crate::Status::Success(val), point } => (point, val),
369            $crate::Progress { status: $crate::Status::Failure(val), point } => {
370                return $crate::Progress { point: point, status: $crate::Status::Failure(val) }
371            }
372        }
373    });
374);
375
376/// Matches a literal string to a specific type, usually an enum.
377pub type Identifier<'a, T> = (&'a str, T);
378
379/// Tracks the location of parsing in a string, the most common case.
380///
381/// Helper methods are provided to do basic parsing tasks, such as
382/// finding literal strings.
383#[derive(Debug,Copy,Clone,PartialEq,Eq)]
384pub struct StringPoint<'a> {
385    /// The portion of the input string to start parsing next
386    pub s: &'a str,
387    /// How far into the original string we are
388    pub offset: usize,
389}
390
391impl<'a> PartialOrd for StringPoint<'a> {
392    #[inline]
393    fn partial_cmp(&self, other: &StringPoint<'a>) -> Option<Ordering> {
394        Some(self.cmp(&other))
395    }
396}
397
398impl<'a> Ord for StringPoint<'a> {
399    #[inline]
400    fn cmp(&self, other: &StringPoint<'a>) -> Ordering {
401        self.offset.cmp(&other.offset)
402    }
403}
404
405impl<'a> Point for StringPoint<'a> {
406    fn zero() -> StringPoint<'a> { StringPoint { s: "", offset: 0} }
407}
408
409impl<'a> StringPoint<'a> {
410    #[inline]
411    pub fn new(s: &'a str) -> StringPoint<'a> {
412        StringPoint { s: s, offset: 0 }
413    }
414
415    #[inline]
416    pub fn is_empty(self) -> bool {
417        self.s.is_empty()
418    }
419
420    /// Slices the string.
421    #[inline]
422    pub fn to(self, other: StringPoint<'a>) -> &'a str {
423        let len = other.offset - self.offset;
424        &self.s[..len]
425    }
426
427    #[inline]
428    fn success(self, len: usize) -> Progress<StringPoint<'a>, &'a str, ()> {
429        let matched = &self.s[..len];
430        let rest = &self.s[len..];
431
432        Progress {
433            point: StringPoint { s: rest, offset: self.offset + len },
434            status: Status::Success(matched)
435        }
436    }
437
438    #[inline]
439    fn fail<T>(self) -> Progress<StringPoint<'a>, T, ()> {
440        Progress { point: self, status: Status::Failure(()) }
441    }
442
443    /// Advances the point by the number of bytes. If the value is
444    /// `None`, then no value was able to be consumed, and the result
445    /// is a failure.
446    #[inline]
447    pub fn consume_to(&self, l: Option<usize>) -> Progress<StringPoint<'a>, &'a str, ()> {
448        match l {
449            None => self.fail(),
450            Some(position) => self.success(position),
451        }
452    }
453
454    /// Advances the point if it starts with the literal.
455    #[inline]
456    pub fn consume_literal(self, val: &str) -> Progress<StringPoint<'a>, &'a str, ()> {
457        if self.s.starts_with(val) {
458            self.success(val.len())
459        } else {
460            self.fail()
461        }
462    }
463
464    /// Iterates through the identifiers and advances the point on the
465    /// first matching identifier.
466    #[inline]
467    pub fn consume_identifier<T>(self, identifiers: &[Identifier<T>])
468                                 -> Progress<StringPoint<'a>, T, ()>
469        where T: Clone
470    {
471        for &(identifier, ref item) in identifiers {
472            if self.s.starts_with(identifier) {
473                return self
474                    .consume_to(Some(identifier.len()))
475                    .map(|_| item.clone())
476                    .map_err(|_| unreachable!());
477            }
478        }
479
480        self.fail()
481    }
482}
483
484#[cfg(test)]
485mod test {
486    use super::{ParseMaster,Progress,Status,StringPoint,Recoverable};
487
488    #[derive(Debug,Copy,Clone,PartialEq,Eq,PartialOrd,Ord)]
489    struct AnError(u8);
490
491    impl Recoverable for AnError {
492        fn recoverable(&self) -> bool { self.0 < 0x80 }
493    }
494
495    type SimpleMaster = ParseMaster<usize, AnError>;
496    type SimpleProgress<T> = Progress<usize, T, AnError>;
497
498    #[test]
499    fn one_error() {
500        let mut d = ParseMaster::new();
501
502        let r = d.finish::<()>(Progress { point: 0, status: Status::Failure(AnError(1)) });
503
504        assert_eq!(r, Progress { point: 0, status: Status::Failure(vec![AnError(1)]) });
505    }
506
507    #[test]
508    fn two_error_at_same_point() {
509        let mut d = ParseMaster::new();
510
511        let r = d.alternate::<()>()
512            .one(|_| Progress { point: 0, status: Status::Failure(AnError(1)) })
513            .one(|_| Progress { point: 0, status: Status::Failure(AnError(2)) })
514            .finish();
515
516        let r = d.finish(r);
517
518        assert_eq!(r, Progress { point: 0, status: Status::Failure(vec![AnError(1), AnError(2)]) });
519    }
520
521    #[test]
522    fn first_error_is_better() {
523        let mut d = ParseMaster::new();
524
525        let r = d.alternate::<()>()
526            .one(|_| Progress { point: 1, status: Status::Failure(AnError(1)) })
527            .one(|_| Progress { point: 0, status: Status::Failure(AnError(2)) })
528            .finish();
529
530        let r = d.finish(r);
531
532        assert_eq!(r, Progress { point: 1, status: Status::Failure(vec![AnError(1)]) });
533    }
534
535    #[test]
536    fn second_error_is_better() {
537        let mut d = ParseMaster::new();
538
539        let r = d.alternate::<()>()
540            .one(|_| Progress { point: 0, status: Status::Failure(AnError(1)) })
541            .one(|_| Progress { point: 1, status: Status::Failure(AnError(2)) })
542            .finish();
543
544        let r = d.finish(r);
545
546        assert_eq!(r, Progress { point: 1, status: Status::Failure(vec![AnError(2)]) });
547    }
548
549    #[test]
550    fn one_success() {
551        let mut d = ParseMaster::<_, AnError>::new();
552
553        let r = d.finish(Progress { point: 0, status: Status::Success(42) });
554
555        assert_eq!(r, Progress { point: 0, status: Status::Success(42) });
556    }
557
558    #[test]
559    fn success_after_failure() {
560        let mut d = ParseMaster::new();
561
562        let r = d.alternate()
563            .one(|_| Progress { point: 0, status: Status::Failure(AnError(1)) })
564            .one(|_| Progress { point: 0, status: Status::Success(42) })
565            .finish();
566
567        let r = d.finish(r);
568        assert_eq!(r, Progress { point: 0, status: Status::Success(42) });
569    }
570
571    #[test]
572    fn success_before_failure() {
573        let mut d = ParseMaster::<_, AnError>::new();
574
575        let r = d.alternate()
576            .one(|_| Progress { point: 0, status: Status::Success(42) })
577            .one(|_| panic!("Should not even be called"))
578            .finish();
579
580        let r = d.finish(r);
581        assert_eq!(r, Progress { point: 0, status: Status::Success(42) });
582    }
583
584    #[test]
585    fn sequential_success() {
586        fn first(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
587            Progress { point: pt + 1, status: Status::Success(1) }
588        }
589
590        fn second(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
591            Progress { point: pt + 1, status: Status::Success(2) }
592        }
593
594        fn both(d: &mut SimpleMaster, pt: usize) -> SimpleProgress<(u8,u8)> {
595            let (pt, val1) = try_parse!(first(d, pt));
596            let (pt, val2) = try_parse!(second(d, pt));
597            Progress { point: pt, status: Status::Success((val1, val2)) }
598        }
599
600        let mut d = ParseMaster::new();
601        let r = both(&mut d, 0);
602        let r = d.finish(r);
603
604        assert_eq!(r, Progress { point: 2, status: Status::Success((1,2)) });
605    }
606
607    #[test]
608    fn child_parse_succeeds() {
609        fn parent(d: &mut SimpleMaster, pt: usize) -> SimpleProgress<(u8,u8)> {
610            let (pt, val1) = try_parse!(child(d, pt));
611            Progress { point: pt + 1, status: Status::Success((val1, 2)) }
612        }
613
614        fn child(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
615            Progress { point: pt + 1, status: Status::Success(1) }
616        }
617
618        let mut d = ParseMaster::new();
619        let r = parent(&mut d, 0);
620        let r = d.finish(r);
621
622        assert_eq!(r, Progress { point: 2, status: Status::Success((1, 2)) });
623    }
624
625    #[test]
626    fn child_parse_fails_child_step() {
627        fn parent(d: &mut SimpleMaster, pt: usize) -> SimpleProgress<(u8,u8)> {
628            let (pt, val1) = try_parse!(child(d, pt));
629            Progress { point: pt + 1, status: Status::Success((val1, 2)) }
630        }
631
632        fn child(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
633            Progress { point: pt + 1, status: Status::Failure(AnError(1)) }
634        }
635
636        let mut d = ParseMaster::new();
637        let r = parent(&mut d, 0);
638        let r = d.finish(r);
639
640        assert_eq!(r, Progress { point: 1, status: Status::Failure(vec![AnError(1)]) });
641    }
642
643    #[test]
644    fn child_parse_fails_parent_step() {
645        fn parent(d: &mut SimpleMaster, pt: usize) -> SimpleProgress<(u8,u8)> {
646            let (pt, _) = try_parse!(child(d, pt));
647            Progress { point: pt + 1, status: Status::Failure(AnError(2)) }
648        }
649
650        fn child(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
651            Progress { point: pt + 1, status: Status::Success(1) }
652        }
653
654        let mut d = ParseMaster::new();
655        let r = parent(&mut d, 0);
656        let r = d.finish(r);
657
658        assert_eq!(r, Progress { point: 2, status: Status::Failure(vec![AnError(2)]) });
659    }
660
661    #[test]
662    fn alternate_with_children_parses() {
663        fn first(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
664            Progress { point: pt + 1, status: Status::Failure(AnError(1)) }
665        }
666
667        fn second(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
668            Progress { point: pt + 1, status: Status::Success(1) }
669        }
670
671        fn both(d: &mut SimpleMaster, pt: usize) -> Progress<usize, u8, AnError> {
672            d.alternate()
673                .one(|d| first(d, pt))
674                .one(|d| second(d, pt))
675                .finish()
676        }
677
678        let mut d = ParseMaster::new();
679        let r = both(&mut d, 0);
680        let r = d.finish(r);
681
682        assert_eq!(r, Progress { point: 1, status: Status::Success(1) });
683    }
684
685    #[test]
686    fn alternate_stops_parsing_after_unrecoverable_failure() {
687        let mut d = ParseMaster::new();
688        let r = d.alternate()
689            .one(|_| Progress { point: 0, status: Status::Failure(AnError(255)) })
690            .one(|_| Progress { point: 0, status: Status::Success(()) })
691            .finish();
692        let r = d.finish(r);
693
694        assert_eq!(r, Progress { point: 0, status: Status::Failure(vec![AnError(255)]) });
695    }
696
697    #[test]
698    fn optional_present() {
699        fn optional(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
700            Progress { point: pt + 1, status: Status::Success(1) }
701        }
702
703        let mut d = ParseMaster::new();
704        let (pt, val) = optional(&mut d, 0).optional(0);
705
706        assert_eq!(pt, 1);
707        assert_eq!(val, Some(1));
708    }
709
710    #[test]
711    fn optional_missing() {
712        fn optional(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
713            Progress { point: pt + 1, status: Status::Failure(AnError(1)) }
714        }
715
716        let mut d = ParseMaster::new();
717        let (pt, val) = optional(&mut d, 0).optional(0);
718
719        assert_eq!(pt, 0);
720        assert_eq!(val, None);
721    }
722
723    #[test]
724    fn optional_with_recoverable() {
725        fn optional(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
726            Progress { point: pt + 1, status: Status::Failure(AnError(1)) }
727        }
728
729        let mut d = ParseMaster::new();
730        let r = d.optional(0, |pm, pt| optional(pm, pt));
731        let r = d.finish(r);
732
733        assert_eq!(r, Progress { point: 0, status: Status::Success(None) });
734    }
735
736    #[test]
737    fn optional_with_unrecoverable() {
738        fn optional(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
739            Progress { point: pt + 1, status: Status::Failure(AnError(255)) }
740        }
741
742        let mut d = ParseMaster::new();
743        let r = d.optional(0, |pm, pt| optional(pm, pt));
744        let r = d.finish(r);
745
746        assert_eq!(r, Progress { point: 1, status: Status::Failure(vec![AnError(255)]) });
747    }
748
749    #[test]
750    fn zero_or_more() {
751        let mut remaining: u8 = 2;
752
753        let mut body = |_: &mut SimpleMaster, pt: usize| -> SimpleProgress<u8> {
754            if remaining > 0 {
755                remaining -= 1;
756                Progress { point: pt + 1, status: Status::Success(remaining) }
757            } else {
758                Progress { point: pt + 1, status: Status::Failure(AnError(1)) }
759            }
760        };
761
762        let mut d = ParseMaster::new();
763        let r = d.zero_or_more(0, |d, pt| body(d, pt));
764        let r = d.finish(r);
765
766        assert_eq!(r, Progress { point: 2, status: Status::Success(vec![1, 0]) });
767    }
768
769    #[test]
770    fn zero_or_more_failure_returns_to_beginning_of_line() {
771        fn body(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
772            Progress { point: pt + 1, status: Status::Failure(AnError(1)) }
773        }
774
775        let mut d = ParseMaster::new();
776        let r = d.zero_or_more(0, |d, pt| body(d, pt));
777        let r = d.finish(r);
778
779        assert_eq!(r, Progress { point: 0, status: Status::Success(vec![]) });
780    }
781
782    #[test]
783    fn zero_or_more_fails_on_unrecoverable_failure() {
784        fn body(_: &mut SimpleMaster, pt: usize) -> SimpleProgress<u8> {
785            Progress { point: pt, status: Status::Failure(AnError(255)) }
786        }
787
788        let mut d = ParseMaster::new();
789        let r = d.zero_or_more(0, |d, pt| body(d, pt));
790        let r = d.finish(r);
791
792        assert_eq!(r, Progress { point: 0, status: Status::Failure(vec![AnError(255)]) });
793    }
794
795    type StringMaster<'a> = ParseMaster<StringPoint<'a>, AnError>;
796    type StringProgress<'a, T> = Progress<StringPoint<'a>, T, AnError>;
797
798    #[test]
799    fn string_sequential() {
800        fn all<'a>(pt: StringPoint<'a>) -> StringProgress<'a, (&'a str, &'a str, &'a str)> {
801            let (pt, a) = try_parse!(pt.consume_literal("a").map_err(|_| AnError(1)));
802            let (pt, b) = try_parse!(pt.consume_literal("b").map_err(|_| AnError(2)));
803            let (pt, c) = try_parse!(pt.consume_literal("c").map_err(|_| AnError(3)));
804
805            Progress { point: pt, status: Status::Success((a,b,c)) }
806        }
807
808        let mut d = ParseMaster::new();
809        let pt = StringPoint::new("abc");
810
811        let r = all(pt);
812        let r = d.finish(r);
813
814        assert_eq!(r, Progress { point: StringPoint { s: "", offset: 3 }, status: Status::Success(("a", "b", "c")) });
815    }
816
817    #[test]
818    fn string_alternate() {
819        fn any<'a>(d: &mut StringMaster<'a>, pt: StringPoint<'a>) -> StringProgress<'a, &'a str> {
820            d.alternate()
821                .one(|_| pt.consume_literal("a").map_err(|_| AnError(1)))
822                .one(|_| pt.consume_literal("b").map_err(|_| AnError(2)))
823                .one(|_| pt.consume_literal("c").map_err(|_| AnError(3)))
824                .finish()
825        }
826
827        let mut d = ParseMaster::new();
828        let pt = StringPoint::new("c");
829
830        let r = any(&mut d, pt);
831        let r = d.finish(r);
832
833        assert_eq!(r, Progress { point: StringPoint { s: "", offset: 1 }, status: Status::Success("c") });
834    }
835
836    #[test]
837    fn string_zero_or_more() {
838        fn any<'a>(d: &mut StringMaster<'a>, pt: StringPoint<'a>) -> StringProgress<'a, Vec<&'a str>> {
839            d.zero_or_more(pt, |_, pt| pt.consume_literal("a").map_err(|_| AnError(1)))
840        }
841
842        let mut d = ParseMaster::new();
843        let pt = StringPoint::new("aaa");
844
845        let r = any(&mut d, pt);
846        let r = d.finish(r);
847
848        assert_eq!(r, Progress { point: StringPoint { s: "", offset: 3 }, status: Status::Success(vec!["a", "a", "a"]) });
849    }
850
851    #[test]
852    fn string_to() {
853        let pt1 = StringPoint::new("hello world");
854        let pt2 = StringPoint { offset: pt1.offset + 5, s: &pt1.s[5..] };
855        assert_eq!("hello", pt1.to(pt2));
856    }
857
858    #[test]
859    fn string_consume_literal() {
860        let pt = StringPoint::new("hello world");
861
862        let r = pt.consume_literal("hello");
863        assert_eq!(r, Progress { point: StringPoint { s: " world", offset: 5 },
864                                 status: Status::Success("hello") });
865
866        let r = pt.consume_literal("goodbye");
867        assert_eq!(r, Progress { point: StringPoint { s: "hello world", offset: 0 },
868                                 status: Status::Failure(()) });
869    }
870
871    #[test]
872    fn string_consume_identifier() {
873        let pt = StringPoint::new("hello world");
874
875        let r = pt.consume_identifier(&[("goodbye", 1), ("hello", 2)]);
876        assert_eq!(r, Progress { point: StringPoint { s: " world", offset: 5 },
877                                 status: Status::Success(2) });
878
879        let r = pt.consume_identifier(&[("red", 3), ("blue", 4)]);
880        assert_eq!(r, Progress { point: StringPoint { s: "hello world", offset: 0 },
881                                 status: Status::Failure(()) });
882    }
883}