use crate::{InputToken, Parser};
pub fn between<PO, PC, P, IT, O, OO, OC>(open: &PO, parser: &P, close: &PC) -> impl Parser<IT, O>
where
PO: Parser<IT, OO>,
PC: Parser<IT, OC>,
P: Parser<IT, O>,
IT: InputToken,
{
move |input| {
open(input)?;
let output = parser(input)?;
close(input)?;
Ok(output)
}
}
#[cfg(test)]
mod tests {
use crate::input::Position;
use crate::*;
#[test]
fn empty() {
let mut input = Input::new_from_chars("".chars(), None);
let output = between(&is('('), &is('h'), &is(')'))(&mut input);
assert_eq!(output, Err(Error::EndOfInput(Some(Box::new('(')))));
}
#[test]
fn empty_shortcut() {
let mut input = Input::new_from_chars("".chars(), None);
let output = is('h').between(&is('('), &is(')'))(&mut input);
assert_eq!(output, Err(Error::EndOfInput(Some(Box::new('(')))));
}
#[test]
fn success() {
let mut input = Input::new_from_chars("(x)".chars(), None);
let output = between(&is('('), &is('x'), &is(')'))(&mut input);
assert_eq!(output, Ok('x'));
assert_eq!(any()(&mut input), Err(Error::EndOfInput(None)));
}
#[test]
fn success_shortcut() {
let mut input = Input::new_from_chars("(x)".chars(), None);
let output = is('x').between(&is('('), &is(')'))(&mut input);
assert_eq!(output, Ok('x'));
assert_eq!(any()(&mut input), Err(Error::EndOfInput(None)));
}
#[test]
fn fail_repeated() {
let mut input = Input::new_from_chars("(xx)".chars(), None);
let output = between(&is('('), &is('x'), &is(')'))(&mut input);
let mismatch = Mismatch::new(')', 'x');
assert_eq!(
output,
Err(Error::UnexpectedToken(
None,
Position::new(1, 3),
Some(mismatch)
))
);
}
#[test]
fn fail_no_middle() {
let mut input = Input::new_from_chars("()".chars(), None);
let output = between(&is('('), &is('x'), &is(')'))(&mut input);
let mismatch = Mismatch::new('x', ')');
assert_eq!(
output,
Err(Error::UnexpectedToken(
None,
Position::new(1, 2),
Some(mismatch)
))
);
}
#[test]
fn fail_swap() {
let mut input = Input::new_from_chars(")xx(".chars(), None);
let output = between(&is('('), &is('x'), &is(')'))(&mut input);
let mismatch = Mismatch::new('(', ')');
assert_eq!(
output,
Err(Error::UnexpectedToken(
None,
Position::new(1, 1),
Some(mismatch)
))
);
}
}