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