pub trait SyllableChar {
fn char(&self) -> char;
}
pub fn match_unit<T: SyllableChar>() -> impl Fn(&[T]) -> Option<usize> {
|_cs: &[T]| Some(0)
}
pub fn match_one<T: SyllableChar>(f: impl Fn(char) -> bool) -> impl Fn(&[T]) -> Option<usize> {
move |cs: &[T]| match cs.first() {
Some(c) if f(c.char()) => Some(1),
_ => None,
}
}
pub fn match_nonempty<T: SyllableChar>(
f: impl Fn(&[T]) -> Option<usize>,
) -> impl Fn(&[T]) -> Option<usize> {
move |cs: &[T]| f(cs).filter(|&n| n > 0)
}
pub fn match_optional<T: SyllableChar>(
f: impl Fn(&[T]) -> Option<usize>,
) -> impl Fn(&[T]) -> Option<usize> {
move |cs: &[T]| f(cs).or(Some(0))
}
pub fn match_optional_seq<T: SyllableChar>(
f: impl Fn(&[T]) -> Option<usize>,
g: impl Fn(&[T]) -> Option<usize>,
) -> impl Fn(&[T]) -> Option<usize> {
move |cs: &[T]| match_either(&g, match_seq(&f, &g))(cs)
}
#[allow(dead_code)]
pub fn match_repeat_num<T: SyllableChar>(
num: usize,
f: impl Fn(&[T]) -> Option<usize>,
) -> impl Fn(&[T]) -> Option<usize> {
move |mut cs: &[T]| {
let mut total = 0;
for _ in 0..num {
let n = f(cs)?;
total += n;
cs = &cs[n..];
}
Some(total)
}
}
pub fn match_repeat_upto<T: SyllableChar>(
max: usize,
f: impl Fn(&[T]) -> Option<usize>,
g: impl Fn(&[T]) -> Option<usize>,
) -> impl Fn(&[T]) -> Option<usize> {
move |mut cs: &[T]| {
let mut best = g(cs);
let mut nf = 0;
for _ in 0..max {
if let Some(n) = f(cs) {
nf += n;
cs = &cs[n..];
if let Some(ng) = g(cs) {
best = Some(nf + ng);
}
} else {
break;
}
}
best
}
}
pub fn match_seq<T: SyllableChar>(
f1: impl Fn(&[T]) -> Option<usize>,
f2: impl Fn(&[T]) -> Option<usize>,
) -> impl Fn(&[T]) -> Option<usize> {
move |cs: &[T]| {
let n1 = f1(cs)?;
let n2 = f2(&cs[n1..])?;
Some(n1 + n2)
}
}
pub fn match_either<T: SyllableChar>(
f1: impl Fn(&[T]) -> Option<usize>,
f2: impl Fn(&[T]) -> Option<usize>,
) -> impl Fn(&[T]) -> Option<usize> {
move |cs: &[T]| {
let n1 = f1(cs);
let n2 = f2(cs);
std::cmp::max(n1, n2)
}
}
pub fn match_either_seq<T: SyllableChar>(
f1: impl Fn(&[T]) -> Option<usize>,
f2: impl Fn(&[T]) -> Option<usize>,
g: impl Fn(&[T]) -> Option<usize>,
) -> impl Fn(&[T]) -> Option<usize> {
move |cs: &[T]| {
let n1 = match_seq(&f1, &g)(cs);
let n2 = match_seq(&f2, &g)(cs);
std::cmp::max(n1, n2)
}
}