use crate::{
error::{Error, ErrorKind},
parser::*,
};
use std::sync::Arc;
#[derive(Clone)]
pub struct PSat<'a, K: PartialEq + Clone> {
test: Arc<dyn Fn(&K) -> bool>,
expected: Vec<TokenPattern<'a, K>>,
}
pub fn psat<'a, K, F>(test: F, expected: Vec<TokenPattern<'a, K>>) -> PSat<'a, K>
where
K: PartialEq + Clone,
F: Fn(&K) -> bool + 'static,
{
let func = move |input: &K| test(input);
PSat {
test: Arc::new(func),
expected,
}
}
impl<'a, K> ParserCore<'a, K, K> for PSat<'a, K>
where
K: PartialEq + Clone + 'a,
{
fn parse(&self, i: PInput<'a, K>) -> Result<PSuccess<'a, K, K>, Error<'a, K>> {
match i.tokens.get(i.loc) {
Some(tok) => {
if (self.test)(tok) {
Ok(PSuccess {
val: i.tokens[i.loc].clone(),
rest: PInput {
tokens: i.tokens,
loc: i.loc + 1,
},
})
} else {
Err(Error {
kind: vec![ErrorKind::Unexpected {
expected: self.expected.clone(),
found: TokenPattern::Token(std::borrow::Cow::Borrowed(tok)),
}],
span: (i.loc, i.loc + 1),
state: PInput {
tokens: i.tokens,
loc: i.loc + 1,
},
})
}
}
None => Err(Error {
kind: vec![ErrorKind::Unexpected {
expected: self.expected.clone(),
found: TokenPattern::String(std::borrow::Cow::Borrowed("No token to read")),
}],
span: (i.loc, i.loc),
state: PInput {
tokens: i.tokens,
loc: i.loc + 1,
},
}),
}
}
}
impl<'a, K> Parser<'a, K, K> for PSat<'a, K> where K: PartialEq + Clone + 'a {}