/rust/registry/src/index.crates.io-1949cf8c6b5b557f/combine-4.6.7/src/parser/function.rs
Line | Count | Source |
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] |
17 | 0 | fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error> { |
18 | 0 | self(input).into() |
19 | 0 | } |
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 | | /// ``` |
61 | 0 | pub fn parser<Input, O, F>(f: F) -> FnParser<Input, F> |
62 | 0 | where |
63 | 0 | Input: Stream, |
64 | 0 | F: FnMut(&mut Input) -> StdParseResult<O, Input>, |
65 | | { |
66 | 0 | FnParser(f, PhantomData) |
67 | 0 | } |
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] |
78 | 0 | fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error> { |
79 | 0 | (self.0)(input).into() |
80 | 0 | } |
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] |
91 | 0 | fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error> { |
92 | 0 | self(input).into() |
93 | 0 | } |
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 | | { |
110 | 0 | fn clone(&self) -> Self { |
111 | 0 | EnvParser { |
112 | 0 | env: self.env.clone(), |
113 | 0 | parser: self.parser, |
114 | 0 | } |
115 | 0 | } |
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] |
127 | 0 | fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<O, Input::Error> { |
128 | 0 | (self.parser)(self.env.clone(), input).into() |
129 | 0 | } |
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 | | /// ``` |
169 | 0 | pub fn env_parser<E, Input, O>( |
170 | 0 | env: E, |
171 | 0 | parser: fn(E, &mut Input) -> StdParseResult<O, Input>, |
172 | 0 | ) -> EnvParser<E, Input, O> |
173 | 0 | where |
174 | 0 | E: Clone, |
175 | 0 | Input: Stream, |
176 | | { |
177 | 0 | EnvParser { env, parser } |
178 | 0 | } |