| //! 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 } |
| } |