combine/parser/function.rs
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 180
//! Parsers constructor from regular functions
use lib::marker::PhantomData;
use error::{ConsumedResult, ParseResult};
use stream::Stream;
use Parser;
impl<'a, I: Stream, O> Parser for FnMut(&mut I) -> ParseResult<O, I> + 'a {
type Input = I;
type Output = O;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
self(input).into()
}
}
#[derive(Copy, Clone)]
pub struct FnParser<I, F>(F, PhantomData<fn(I) -> I>);
/// 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::{Consumed, 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, consumed) = try!(digit().parse_stream(input));
/// let d = (char_digit as i32) - ('0' as i32);
/// if d % 2 == 0 {
/// Ok((d, consumed))
/// }
/// else {
/// //Return an empty error since we only tested the first token of the stream
/// let errors = easy::Errors::new(
/// position,
/// StreamError::expected(From::from("even number"))
/// );
/// Err(Consumed::Empty(errors.into()))
/// }
/// });
/// let result = even_digit
/// .easy_parse("8")
/// .map(|x| x.0);
/// assert_eq!(result, Ok(8));
/// # }
/// ```
#[inline(always)]
pub fn parser<I, O, F>(f: F) -> FnParser<I, F>
where
I: Stream,
F: FnMut(&mut I) -> ParseResult<O, I>,
{
FnParser(f, PhantomData)
}
impl<I, O, F> Parser for FnParser<I, F>
where
I: Stream,
F: FnMut(&mut I) -> ParseResult<O, I>,
{
type Input = I;
type Output = O;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
(self.0)(input).into()
}
}
impl<I, O> Parser for fn(&mut I) -> ParseResult<O, I>
where
I: Stream,
{
type Input = I;
type Output = O;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
self(input).into()
}
}
#[derive(Copy)]
pub struct EnvParser<E, I, T>
where
I: Stream,
{
env: E,
parser: fn(E, &mut I) -> ParseResult<T, I>,
}
impl<E, I, T> Clone for EnvParser<E, I, T>
where
I: Stream,
E: Clone,
{
fn clone(&self) -> Self {
EnvParser {
env: self.env.clone(),
parser: self.parser,
}
}
}
impl<E, I, O> Parser for EnvParser<E, I, O>
where
E: Clone,
I: Stream,
{
type Input = I;
type Output = O;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
(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::char::letter;
/// # fn main() {
/// struct Interner(HashMap<String, u32>);
/// impl Interner {
/// fn string<I>(&self, input: &mut I) -> ParseResult<u32, I>
/// where I: Stream<Item=char>,
/// I::Error: ParseError<I::Item, I::Range, I::Position>,
/// {
/// many(letter())
/// .map(|s: String| self.0.get(&s).cloned().unwrap_or(0))
/// .parse_stream(input)
/// }
/// }
///
/// 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, "")));
/// # }
/// ```
#[inline(always)]
pub fn env_parser<E, I, O>(env: E, parser: fn(E, &mut I) -> ParseResult<O, I>) -> EnvParser<E, I, O>
where
E: Clone,
I: Stream,
{
EnvParser {
env: env,
parser: parser,
}
}