use crate::parser::*;
use std::sync::Arc;
#[derive(Clone)]
pub struct PSat<K: PartialEq> {
test: Arc<dyn Fn(&K) -> bool>,
condition: String,
}
pub fn psat<K, F>(test: F, condition: impl Into<String>) -> PSat<K>
where
K: PartialEq,
F: Fn(&K) -> bool + 'static,
{
let func = move |input: &K| test(input);
PSat {
test: Arc::new(func),
condition: condition.into(),
}
}
impl<'a, K> ParserCore<'a, K, K> for PSat<K>
where
K: PartialEq + Clone + 'a,
{
fn parse(&self, i: PInput<'a, K>) -> Result<PSuccess<'a, K, K>, PFail<'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(PFail {
error: vec![self.condition.clone()],
span: vec![(i.loc, i.loc + 1)],
rest: PInput {
tokens: i.tokens,
loc: i.loc + 1,
},
})
}
}
None => Err(PFail {
error: vec!["No token to read".to_string()],
span: vec![(i.loc, i.loc)],
rest: PInput {
tokens: i.tokens,
loc: i.loc + 1,
},
}),
}
}
}
impl<'a, K> Parser<'a, K, K> for PSat<K> where K: PartialEq + Clone + 'a {}