Coverage Report

Created: 2025-11-24 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}