use crate::{Error, InputToken, Mismatch, Parser};
pub fn is<IT>(token: IT::Token) -> impl Parser<IT, IT::Token>
where
IT: InputToken + 'static,
{
move |input| {
match input.peek() {
Some(input_token) => {
if token == *input_token.token() {
let matched_token = input.next_token().unwrap();
Ok(matched_token.token_owned())
} else {
let position = input_token.position();
let expected = token.clone();
let found = (*input_token.token()).clone();
let mismatch = Mismatch::new(expected, found);
Err(Error::UnexpectedToken(
input.source_name(),
position,
Some(mismatch),
))
}
}
None => Err(Error::EndOfInput(Some(Box::new(token.clone())))),
}
}
}
#[cfg(test)]
mod tests {
use crate::input::Position;
use crate::*;
#[test]
fn success() {
let parser = is('h');
let mut input = Input::new_from_chars("h".chars(), None);
assert_eq!(parser(&mut input), Ok('h'));
assert!(end_of_input()(&mut input).is_ok()); }
#[test]
fn fail() {
let parser = is('j');
let mut input = Input::new_from_chars("h".chars(), None);
let mismatch = Mismatch::new('j', 'h');
assert_eq!(
parser(&mut input),
Err(Error::UnexpectedToken(
None,
Position::new(1, 1),
Some(mismatch)
))
);
assert!(end_of_input()(&mut input).is_err()); }
}