//! Parsers constructor from regular functions use crate::{ error::{ParseResult, StdParseResult}, lib::marker::PhantomData, stream::Stream, Parser, }; impl<'a, Input: Stream, O> Parser for dyn FnMut(&mut Input) -> StdParseResult + 'a { type Output = O; type PartialState = (); #[inline] fn parse_lazy(&mut self, input: &mut Input) -> ParseResult { self(input).into() } } #[derive(Copy, Clone)] pub struct FnParser(F, PhantomData 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(f: F) -> FnParser where Input: Stream, F: FnMut(&mut Input) -> StdParseResult, { FnParser(f, PhantomData) } impl Parser for FnParser where Input: Stream, F: FnMut(&mut Input) -> StdParseResult, { type Output = O; type PartialState = (); #[inline] fn parse_lazy(&mut self, input: &mut Input) -> ParseResult { (self.0)(input).into() } } impl Parser for fn(&mut Input) -> StdParseResult where Input: Stream, { type Output = O; type PartialState = (); #[inline] fn parse_lazy(&mut self, input: &mut Input) -> ParseResult { self(input).into() } } #[derive(Copy)] pub struct EnvParser where Input: Stream, { env: E, parser: fn(E, &mut Input) -> StdParseResult, } impl Clone for EnvParser where Input: Stream, E: Clone, { fn clone(&self) -> Self { EnvParser { env: self.env.clone(), parser: self.parser, } } } impl Parser for EnvParser where E: Clone, Input: Stream, { type Output = O; type PartialState = (); #[inline] fn parse_lazy(&mut self, input: &mut Input) -> ParseResult { (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); /// impl Interner { /// fn string(&self, input: &mut Input) -> StdParseResult /// where Input: Stream, /// { /// 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( env: E, parser: fn(E, &mut Input) -> StdParseResult, ) -> EnvParser where E: Clone, Input: Stream, { EnvParser { env, parser } }