combine/parser/
token.rs

1//! Parsers working with single stream items.
2
3use crate::{
4    error::{
5        self, ErrorInfo, ParseError,
6        ParseResult::{self, *},
7        ResultExt, StreamError, Tracked,
8    },
9    lib::marker::PhantomData,
10    stream::{uncons, Stream, StreamOnce},
11    Parser,
12};
13
14#[derive(Copy, Clone)]
15pub struct Any<Input>(PhantomData<fn(Input) -> Input>);
16
17impl<Input> Parser<Input> for Any<Input>
18where
19    Input: Stream,
20{
21    type Output = Input::Token;
22    type PartialState = ();
23
24    #[inline]
25    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Input::Token, Input::Error> {
26        uncons(input)
27    }
28}
29
30/// Parses any token.
31///
32/// ```
33/// # extern crate combine;
34/// # use combine::*;
35/// # fn main() {
36/// let mut char_parser = any();
37/// assert_eq!(char_parser.parse("!").map(|x| x.0), Ok('!'));
38/// assert!(char_parser.parse("").is_err());
39/// let mut byte_parser = any();
40/// assert_eq!(byte_parser.parse(&b"!"[..]).map(|x| x.0), Ok(b'!'));
41/// assert!(byte_parser.parse(&b""[..]).is_err());
42/// # }
43/// ```
44pub fn any<Input>() -> Any<Input>
45where
46    Input: Stream,
47{
48    Any(PhantomData)
49}
50
51#[derive(Copy, Clone)]
52pub struct Satisfy<Input, P> {
53    predicate: P,
54    _marker: PhantomData<Input>,
55}
56
57fn satisfy_impl<Input, P, R>(input: &mut Input, mut predicate: P) -> ParseResult<R, Input::Error>
58where
59    Input: Stream,
60    P: FnMut(Input::Token) -> Option<R>,
61{
62    let position = input.position();
63    match uncons(input) {
64        PeekOk(c) | CommitOk(c) => match predicate(c) {
65            Some(c) => CommitOk(c),
66            None => PeekErr(Input::Error::empty(position).into()),
67        },
68        PeekErr(err) => PeekErr(err),
69        CommitErr(err) => CommitErr(err),
70    }
71}
72
73impl<Input, P> Parser<Input> for Satisfy<Input, P>
74where
75    Input: Stream,
76    P: FnMut(Input::Token) -> bool,
77{
78    type Output = Input::Token;
79    type PartialState = ();
80
81    #[inline]
82    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Self::Output, Input::Error> {
83        satisfy_impl(input, |c| {
84            if (self.predicate)(c.clone()) {
85                Some(c)
86            } else {
87                None
88            }
89        })
90    }
91}
92
93/// Parses a token and succeeds depending on the result of `predicate`.
94///
95/// ```
96/// # extern crate combine;
97/// # use combine::*;
98/// # fn main() {
99/// let mut parser = satisfy(|c| c == '!' || c == '?');
100/// assert_eq!(parser.parse("!").map(|x| x.0), Ok('!'));
101/// assert_eq!(parser.parse("?").map(|x| x.0), Ok('?'));
102/// # }
103/// ```
104pub fn satisfy<Input, P>(predicate: P) -> Satisfy<Input, P>
105where
106    Input: Stream,
107    P: FnMut(Input::Token) -> bool,
108{
109    Satisfy {
110        predicate,
111        _marker: PhantomData,
112    }
113}
114
115#[derive(Copy, Clone)]
116pub struct SatisfyMap<Input, P> {
117    predicate: P,
118    _marker: PhantomData<Input>,
119}
120
121impl<Input, P, R> Parser<Input> for SatisfyMap<Input, P>
122where
123    Input: Stream,
124    P: FnMut(Input::Token) -> Option<R>,
125{
126    type Output = R;
127    type PartialState = ();
128    #[inline]
129    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Self::Output, Input::Error> {
130        satisfy_impl(input, &mut self.predicate)
131    }
132}
133
134/// Parses a token and passes it to `predicate`. If `predicate` returns `Some` the parser succeeds
135/// and returns the value inside the `Option`. If `predicate` returns `None` the parser fails
136/// without consuming any input.
137///
138/// ```
139/// # extern crate combine;
140/// # use combine::*;
141/// # fn main() {
142/// #[derive(Debug, PartialEq)]
143/// enum YesNo {
144///     Yes,
145///     No,
146/// }
147/// let mut parser = satisfy_map(|c| {
148///     match c {
149///         'Y' => Some(YesNo::Yes),
150///         'N' => Some(YesNo::No),
151///         _ => None,
152///     }
153/// });
154/// assert_eq!(parser.parse("Y").map(|x| x.0), Ok(YesNo::Yes));
155/// assert!(parser.parse("A").map(|x| x.0).is_err());
156/// # }
157/// ```
158pub fn satisfy_map<Input, P, R>(predicate: P) -> SatisfyMap<Input, P>
159where
160    Input: Stream,
161    P: FnMut(Input::Token) -> Option<R>,
162{
163    SatisfyMap {
164        predicate,
165        _marker: PhantomData,
166    }
167}
168
169#[derive(Copy, Clone)]
170pub struct Token<Input>
171where
172    Input: Stream,
173    Input::Token: PartialEq,
174{
175    c: Input::Token,
176    _marker: PhantomData<Input>,
177}
178
179impl<Input> Parser<Input> for Token<Input>
180where
181    Input: Stream,
182    Input::Token: PartialEq + Clone,
183{
184    type Output = Input::Token;
185    type PartialState = ();
186
187    #[inline]
188    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Input::Token, Input::Error> {
189        satisfy_impl(input, |c| if c == self.c { Some(c) } else { None })
190    }
191    fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
192        errors.error.add_expected(error::Token(self.c.clone()));
193    }
194}
195
196/// Parses a character and succeeds if the character is equal to `c`.
197///
198/// ```
199/// # extern crate combine;
200/// # use combine::*;
201/// # fn main() {
202/// let result = token('!')
203///     .parse("!")
204///     .map(|x| x.0);
205/// assert_eq!(result, Ok('!'));
206/// # }
207/// ```
208pub fn token<Input>(c: Input::Token) -> Token<Input>
209where
210    Input: Stream,
211    Input::Token: PartialEq,
212{
213    Token {
214        c,
215        _marker: PhantomData,
216    }
217}
218
219#[derive(Clone)]
220pub struct Tokens<C, E, T, Input>
221where
222    Input: Stream,
223{
224    cmp: C,
225    expected: E,
226    tokens: T,
227    _marker: PhantomData<Input>,
228}
229
230impl<Input, C, E, T> Parser<Input> for Tokens<C, E, T, Input>
231where
232    C: FnMut(T::Item, Input::Token) -> bool,
233    E: for<'s> ErrorInfo<'s, Input::Token, Input::Range>,
234    T: Clone + IntoIterator,
235    Input: Stream,
236{
237    type Output = T;
238    type PartialState = ();
239    #[inline]
240    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<T, Input::Error> {
241        let start = input.position();
242        let mut committed = false;
243        for c in self.tokens.clone() {
244            match crate::stream::uncons(input) {
245                CommitOk(other) | PeekOk(other) => {
246                    if !(self.cmp)(c, other.clone()) {
247                        return if committed {
248                            let mut errors = <Input as StreamOnce>::Error::from_error(
249                                start,
250                                StreamError::unexpected_token(other),
251                            );
252                            errors.add_expected(&self.expected);
253                            CommitErr(errors)
254                        } else {
255                            PeekErr(<Input as StreamOnce>::Error::empty(start).into())
256                        };
257                    }
258                    committed = true;
259                }
260                PeekErr(mut error) => {
261                    error.error.set_position(start);
262                    return if committed {
263                        CommitErr(error.error)
264                    } else {
265                        PeekErr(error)
266                    };
267                }
268                CommitErr(mut error) => {
269                    error.set_position(start);
270                    return CommitErr(error);
271                }
272            }
273        }
274        if committed {
275            CommitOk(self.tokens.clone())
276        } else {
277            PeekOk(self.tokens.clone())
278        }
279    }
280    fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
281        errors.error.add_expected(&self.expected);
282    }
283}
284
285/// Parses multiple tokens.
286///
287/// Consumes items from the input and compares them to the values from `tokens` using the
288/// comparison function `cmp`. Succeeds if all the items from `tokens` are matched in the input
289/// stream and fails otherwise with `expected` used as part of the error.
290///
291/// ```
292/// # extern crate combine;
293/// # use combine::*;
294/// # use combine::error;
295/// # fn main() {
296/// let result = tokens(|l, r| l.eq_ignore_ascii_case(&r), "abc", "abc".chars())
297///     .parse("AbC")
298///     .map(|x| x.0.as_str());
299/// assert_eq!(result, Ok("abc"));
300/// let result = tokens(
301///     |&l, r| (if l < r { r - l } else { l - r }) <= 2,
302///     error::Range(&b"025"[..]),
303///     &b"025"[..]
304/// )
305///     .parse(&b"123"[..])
306///     .map(|x| x.0);
307/// assert_eq!(result, Ok(&b"025"[..]));
308/// # }
309/// ```
310pub fn tokens<C, E, T, Input>(cmp: C, expected: E, tokens: T) -> Tokens<C, E, T, Input>
311where
312    C: FnMut(T::Item, Input::Token) -> bool,
313    T: Clone + IntoIterator,
314    Input: Stream,
315{
316    Tokens {
317        cmp,
318        expected,
319        tokens,
320        _marker: PhantomData,
321    }
322}
323
324#[derive(Clone)]
325pub struct TokensCmp<C, T, Input>
326where
327    Input: Stream,
328{
329    cmp: C,
330    tokens: T,
331    _marker: PhantomData<Input>,
332}
333
334impl<Input, C, T> Parser<Input> for TokensCmp<C, T, Input>
335where
336    C: FnMut(T::Item, Input::Token) -> bool,
337    T: Clone + IntoIterator,
338    Input: Stream,
339{
340    type Output = T;
341    type PartialState = ();
342
343    #[inline]
344    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<T, Input::Error> {
345        let start = input.position();
346        let mut committed = false;
347        for c in self.tokens.clone() {
348            match crate::stream::uncons(input) {
349                CommitOk(other) | PeekOk(other) => {
350                    if !(self.cmp)(c, other.clone()) {
351                        return if committed {
352                            let errors = <Input as StreamOnce>::Error::from_error(
353                                start,
354                                StreamError::unexpected_token(other),
355                            );
356                            CommitErr(errors)
357                        } else {
358                            PeekErr(<Input as StreamOnce>::Error::empty(start).into())
359                        };
360                    }
361                    committed = true;
362                }
363                PeekErr(mut error) => {
364                    error.error.set_position(start);
365                    return if committed {
366                        CommitErr(error.error)
367                    } else {
368                        PeekErr(error)
369                    };
370                }
371                CommitErr(mut error) => {
372                    error.set_position(start);
373                    return CommitErr(error);
374                }
375            }
376        }
377        if committed {
378            CommitOk(self.tokens.clone())
379        } else {
380            PeekOk(self.tokens.clone())
381        }
382    }
383}
384
385/// Parses multiple tokens.
386///
387/// Consumes items from the input and compares them to the values from `tokens` using the
388/// comparison function `cmp`. Succeeds if all the items from `tokens` are matched in the input
389/// stream and fails otherwise.
390///
391/// ```
392/// # extern crate combine;
393/// # use combine::*;
394/// # fn main() {
395/// # #[allow(deprecated)]
396/// # use std::ascii::AsciiExt;
397/// let result = tokens_cmp("abc".chars(), |l, r| l.eq_ignore_ascii_case(&r))
398///     .parse("AbC")
399///     .map(|x| x.0.as_str());
400/// assert_eq!(result, Ok("abc"));
401/// let result = tokens_cmp(
402///     &b"025"[..],
403///     |&l, r| (if l < r { r - l } else { l - r }) <= 2,
404/// )
405///     .parse(&b"123"[..])
406///     .map(|x| x.0);
407/// assert_eq!(result, Ok(&b"025"[..]));
408/// # }
409/// ```
410pub fn tokens_cmp<C, T, I>(tokens: T, cmp: C) -> TokensCmp<C, T, I>
411where
412    C: FnMut(T::Item, I::Token) -> bool,
413    T: Clone + IntoIterator,
414    I: Stream,
415{
416    TokensCmp {
417        cmp,
418        tokens,
419        _marker: PhantomData,
420    }
421}
422
423#[derive(Copy, Clone)]
424pub struct Position<Input>
425where
426    Input: Stream,
427{
428    _marker: PhantomData<Input>,
429}
430
431impl<Input> Parser<Input> for Position<Input>
432where
433    Input: Stream,
434{
435    type Output = Input::Position;
436    type PartialState = ();
437
438    #[inline]
439    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Input::Position, Input::Error> {
440        PeekOk(input.position())
441    }
442}
443
444/// Parser which just returns the current position in the stream.
445///
446/// ```
447/// # extern crate combine;
448/// # use combine::*;
449/// # use combine::stream::position::{self, SourcePosition};
450/// # fn main() {
451/// let result = (position(), token('!'), position())
452///     .parse(position::Stream::new("!"))
453///     .map(|x| x.0);
454/// assert_eq!(result, Ok((SourcePosition { line: 1, column: 1 },
455///                        '!',
456///                        SourcePosition { line: 1, column: 2 })));
457/// # }
458/// ```
459pub fn position<Input>() -> Position<Input>
460where
461    Input: Stream,
462{
463    Position {
464        _marker: PhantomData,
465    }
466}
467
468#[derive(Copy, Clone)]
469pub struct OneOf<T, Input>
470where
471    Input: Stream,
472{
473    tokens: T,
474    _marker: PhantomData<Input>,
475}
476
477impl<Input, T> Parser<Input> for OneOf<T, Input>
478where
479    T: Clone + IntoIterator<Item = Input::Token>,
480    Input: Stream,
481    Input::Token: PartialEq,
482{
483    type Output = Input::Token;
484    type PartialState = ();
485
486    #[inline]
487    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Input::Token, Input::Error> {
488        satisfy(|c| self.tokens.clone().into_iter().any(|t| t == c)).parse_lazy(input)
489    }
490
491    fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
492        for expected in self.tokens.clone() {
493            errors.error.add_expected(error::Token(expected));
494        }
495    }
496}
497
498/// Extract one token and succeeds if it is part of `tokens`.
499///
500/// ```
501/// # extern crate combine;
502/// # use combine::*;
503/// # fn main() {
504/// let result = many(one_of("abc".chars()))
505///     .parse("abd");
506/// assert_eq!(result, Ok((String::from("ab"), "d")));
507/// # }
508/// ```
509pub fn one_of<T, Input>(tokens: T) -> OneOf<T, Input>
510where
511    T: Clone + IntoIterator,
512    Input: Stream,
513    Input::Token: PartialEq<T::Item>,
514{
515    OneOf {
516        tokens,
517        _marker: PhantomData,
518    }
519}
520
521#[derive(Copy, Clone)]
522pub struct NoneOf<T, Input>
523where
524    Input: Stream,
525{
526    tokens: T,
527    _marker: PhantomData<Input>,
528}
529
530impl<Input, T> Parser<Input> for NoneOf<T, Input>
531where
532    T: Clone + IntoIterator<Item = Input::Token>,
533    Input: Stream,
534    Input::Token: PartialEq,
535{
536    type Output = Input::Token;
537    type PartialState = ();
538
539    #[inline]
540    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Input::Token, Input::Error> {
541        satisfy(|c| self.tokens.clone().into_iter().all(|t| t != c)).parse_lazy(input)
542    }
543}
544
545/// Extract one token and succeeds if it is not part of `tokens`.
546///
547/// ```
548/// # extern crate combine;
549/// # use combine::*;
550/// # use combine::stream::easy;
551/// # use combine::stream::position;
552/// # fn main() {
553/// let mut parser = many1(none_of(b"abc".iter().cloned()));
554/// let result = parser.easy_parse(position::Stream::new(&b"xyb"[..]))
555///     .map(|(output, input)| (output, input.input));
556/// assert_eq!(result, Ok((b"xy"[..].to_owned(), &b"b"[..])));
557///
558/// let result = parser.easy_parse(position::Stream::new(&b"ab"[..]));
559/// assert_eq!(result, Err(easy::Errors {
560///     position: 0,
561///     errors: vec![
562///         easy::Error::Unexpected(easy::Info::Token(b'a')),
563///     ]
564/// }));
565/// # }
566/// ```
567pub fn none_of<T, Input>(tokens: T) -> NoneOf<T, Input>
568where
569    T: Clone + IntoIterator,
570    Input: Stream,
571    Input::Token: PartialEq<T::Item>,
572{
573    NoneOf {
574        tokens,
575        _marker: PhantomData,
576    }
577}
578
579#[derive(Copy, Clone)]
580pub struct Value<Input, T>(T, PhantomData<fn(Input) -> Input>);
581impl<Input, T> Parser<Input> for Value<Input, T>
582where
583    Input: Stream,
584    T: Clone,
585{
586    type Output = T;
587    type PartialState = ();
588    #[inline]
589    fn parse_lazy(&mut self, _: &mut Input) -> ParseResult<T, Input::Error> {
590        PeekOk(self.0.clone())
591    }
592}
593
594/// Always returns the value `v` without consuming any input.
595///
596/// ```
597/// # extern crate combine;
598/// # use combine::*;
599/// # fn main() {
600/// let result = value(42)
601///     .parse("hello world")
602///     .map(|x| x.0);
603/// assert_eq!(result, Ok(42));
604/// # }
605/// ```
606pub fn value<Input, T>(v: T) -> Value<Input, T>
607where
608    Input: Stream,
609    T: Clone,
610{
611    Value(v, PhantomData)
612}
613
614#[derive(Copy, Clone)]
615pub struct Produce<Input, F>(F, PhantomData<fn(Input) -> Input>);
616impl<Input, F, R> Parser<Input> for Produce<Input, F>
617where
618    Input: Stream,
619    F: FnMut() -> R,
620{
621    type Output = R;
622    type PartialState = ();
623    #[inline]
624    fn parse_lazy(&mut self, _: &mut Input) -> ParseResult<R, Input::Error> {
625        PeekOk((self.0)())
626    }
627}
628
629/// Always returns the value produced by calling `f`.
630///
631/// Can be used when `value` is unable to be used for lack of `Clone` implementation on the value.
632///
633/// ```
634/// # use combine::*;
635/// #[derive(Debug, PartialEq)]
636/// struct NoClone;
637/// let result = produce(|| vec![NoClone])
638///     .parse("hello world")
639///     .map(|x| x.0);
640/// assert_eq!(result, Ok(vec![NoClone]));
641/// ```
642pub fn produce<Input, F, R>(f: F) -> Produce<Input, F>
643where
644    Input: Stream,
645    F: FnMut() -> R,
646{
647    Produce(f, PhantomData)
648}
649
650#[derive(Copy, Clone)]
651pub struct Eof<Input>(PhantomData<Input>);
652impl<Input> Parser<Input> for Eof<Input>
653where
654    Input: Stream,
655{
656    type Output = ();
657    type PartialState = ();
658
659    #[inline]
660    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<(), Input::Error> {
661        let before = input.checkpoint();
662        match input.uncons() {
663            Err(ref err) if err.is_unexpected_end_of_input() => PeekOk(()),
664            _ => {
665                ctry!(input.reset(before).committed());
666                PeekErr(<Input as StreamOnce>::Error::empty(input.position()).into())
667            }
668        }
669    }
670
671    fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
672        errors.error.add_expected("end of input");
673    }
674}
675
676/// Succeeds only if the stream is at end of input, fails otherwise.
677///
678/// ```
679/// # extern crate combine;
680/// # use combine::*;
681/// # use combine::stream::easy;
682/// # use combine::stream::position::{self, SourcePosition};
683/// # fn main() {
684/// let mut parser = eof();
685/// assert_eq!(parser.easy_parse(position::Stream::new("")), Ok(((), position::Stream::new(""))));
686/// assert_eq!(parser.easy_parse(position::Stream::new("x")), Err(easy::Errors {
687///     position: SourcePosition::default(),
688///     errors: vec![
689///         easy::Error::Unexpected('x'.into()),
690///         easy::Error::Expected("end of input".into())
691///     ]
692/// }));
693/// # }
694/// ```
695pub fn eof<Input>() -> Eof<Input>
696where
697    Input: Stream,
698{
699    Eof(PhantomData)
700}