combine/parser/
function.rs

1//! Parsers constructor from regular functions
2
3use crate::{
4    error::{ParseResult, StdParseResult},
5    lib::marker::PhantomData,
6    stream::Stream,
7    Parser,
8};
9
10impl<'a, Input: Stream, O> Parser<Input>
11    for dyn FnMut(&mut Input) -> StdParseResult<O, Input> + 'a
12{
13    type Output = O;
14    type PartialState = ();
15
16    #[inline]
17    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error> {
18        self(input).into()
19    }
20}
21
22#[derive(Copy, Clone)]
23pub struct FnParser<Input, F>(F, PhantomData<fn(Input) -> Input>);
24
25/// Wraps a function, turning it into a parser.
26///
27/// Mainly needed to turn closures into parsers as function types can be casted to function pointers
28/// to make them usable as a parser.
29///
30/// ```
31/// extern crate combine;
32/// # use combine::*;
33/// # use combine::parser::char::digit;
34/// # use combine::error::{Commit, StreamError};
35/// # use combine::stream::easy;
36/// # fn main() {
37/// let mut even_digit = parser(|input| {
38///     // Help type inference out
39///     let _: &mut easy::Stream<&str> = input;
40///     let position = input.position();
41///     let (char_digit, committed) = digit().parse_stream(input).into_result()?;
42///     let d = (char_digit as i32) - ('0' as i32);
43///     if d % 2 == 0 {
44///         Ok((d, committed))
45///     }
46///     else {
47///         //Return an empty error since we only tested the first token of the stream
48///         let errors = easy::Errors::new(
49///             position,
50///             StreamError::expected("even number")
51///         );
52///         Err(Commit::Peek(errors.into()))
53///     }
54/// });
55/// let result = even_digit
56///     .easy_parse("8")
57///     .map(|x| x.0);
58/// assert_eq!(result, Ok(8));
59/// # }
60/// ```
61pub fn parser<Input, O, F>(f: F) -> FnParser<Input, F>
62where
63    Input: Stream,
64    F: FnMut(&mut Input) -> StdParseResult<O, Input>,
65{
66    FnParser(f, PhantomData)
67}
68
69impl<Input, O, F> Parser<Input> for FnParser<Input, F>
70where
71    Input: Stream,
72    F: FnMut(&mut Input) -> StdParseResult<O, Input>,
73{
74    type Output = O;
75    type PartialState = ();
76
77    #[inline]
78    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error> {
79        (self.0)(input).into()
80    }
81}
82
83impl<Input, O> Parser<Input> for fn(&mut Input) -> StdParseResult<O, Input>
84where
85    Input: Stream,
86{
87    type Output = O;
88    type PartialState = ();
89
90    #[inline]
91    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error> {
92        self(input).into()
93    }
94}
95
96#[derive(Copy)]
97pub struct EnvParser<E, Input, T>
98where
99    Input: Stream,
100{
101    env: E,
102    parser: fn(E, &mut Input) -> StdParseResult<T, Input>,
103}
104
105impl<E, Input, T> Clone for EnvParser<E, Input, T>
106where
107    Input: Stream,
108    E: Clone,
109{
110    fn clone(&self) -> Self {
111        EnvParser {
112            env: self.env.clone(),
113            parser: self.parser,
114        }
115    }
116}
117
118impl<Input, E, O> Parser<Input> for EnvParser<E, Input, O>
119where
120    E: Clone,
121    Input: Stream,
122{
123    type Output = O;
124    type PartialState = ();
125
126    #[inline]
127    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error> {
128        (self.parser)(self.env.clone(), input).into()
129    }
130}
131
132/// Constructs a parser out of an environment and a function which needs the given environment to
133/// do the parsing. This is commonly useful to allow multiple parsers to share some environment
134/// while still allowing the parsers to be written in separate functions.
135///
136/// ```
137/// # extern crate combine;
138/// # use std::collections::HashMap;
139/// # use combine::*;
140/// # use combine::parser::function::env_parser;
141/// # use combine::parser::char::letter;
142/// # fn main() {
143/// struct Interner(HashMap<String, u32>);
144/// impl Interner {
145///     fn string<Input>(&self, input: &mut Input) -> StdParseResult<u32, Input>
146///         where Input: Stream<Token = char>,
147///     {
148///         many(letter())
149///             .map(|s: String| self.0.get(&s).cloned().unwrap_or(0))
150///             .parse_stream(input)
151///             .into_result()
152///     }
153/// }
154///
155/// let mut map = HashMap::new();
156/// map.insert("hello".into(), 1);
157/// map.insert("test".into(), 2);
158///
159/// let env = Interner(map);
160/// let mut parser = env_parser(&env, Interner::string);
161///
162/// let result = parser.parse("hello");
163/// assert_eq!(result, Ok((1, "")));
164///
165/// let result = parser.parse("world");
166/// assert_eq!(result, Ok((0, "")));
167/// # }
168/// ```
169pub fn env_parser<E, Input, O>(
170    env: E,
171    parser: fn(E, &mut Input) -> StdParseResult<O, Input>,
172) -> EnvParser<E, Input, O>
173where
174    E: Clone,
175    Input: Stream,
176{
177    EnvParser { env, parser }
178}