1 //! Parsers constructor from regular functions
2
3 use crate::{
4 error::{ParseResult, StdParseResult},
5 lib::marker::PhantomData,
6 stream::Stream,
7 Parser,
8 };
9
10 impl<'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]
parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error>17 fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error> {
18 self(input).into()
19 }
20 }
21
22 #[derive(Copy, Clone)]
23 pub 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 /// ```
parser<Input, O, F>(f: F) -> FnParser<Input, F> where Input: Stream, F: FnMut(&mut Input) -> StdParseResult<O, Input>,61 pub fn parser<Input, O, F>(f: F) -> FnParser<Input, F>
62 where
63 Input: Stream,
64 F: FnMut(&mut Input) -> StdParseResult<O, Input>,
65 {
66 FnParser(f, PhantomData)
67 }
68
69 impl<Input, O, F> Parser<Input> for FnParser<Input, F>
70 where
71 Input: Stream,
72 F: FnMut(&mut Input) -> StdParseResult<O, Input>,
73 {
74 type Output = O;
75 type PartialState = ();
76
77 #[inline]
parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error>78 fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error> {
79 (self.0)(input).into()
80 }
81 }
82
83 impl<Input, O> Parser<Input> for fn(&mut Input) -> StdParseResult<O, Input>
84 where
85 Input: Stream,
86 {
87 type Output = O;
88 type PartialState = ();
89
90 #[inline]
parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error>91 fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error> {
92 self(input).into()
93 }
94 }
95
96 #[derive(Copy)]
97 pub struct EnvParser<E, Input, T>
98 where
99 Input: Stream,
100 {
101 env: E,
102 parser: fn(E, &mut Input) -> StdParseResult<T, Input>,
103 }
104
105 impl<E, Input, T> Clone for EnvParser<E, Input, T>
106 where
107 Input: Stream,
108 E: Clone,
109 {
clone(&self) -> Self110 fn clone(&self) -> Self {
111 EnvParser {
112 env: self.env.clone(),
113 parser: self.parser,
114 }
115 }
116 }
117
118 impl<Input, E, O> Parser<Input> for EnvParser<E, Input, O>
119 where
120 E: Clone,
121 Input: Stream,
122 {
123 type Output = O;
124 type PartialState = ();
125
126 #[inline]
parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error>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 /// ```
env_parser<E, Input, O>( env: E, parser: fn(E, &mut Input) -> StdParseResult<O, Input>, ) -> EnvParser<E, Input, O> where E: Clone, Input: Stream,169 pub fn env_parser<E, Input, O>(
170 env: E,
171 parser: fn(E, &mut Input) -> StdParseResult<O, Input>,
172 ) -> EnvParser<E, Input, O>
173 where
174 E: Clone,
175 Input: Stream,
176 {
177 EnvParser { env, parser }
178 }
179