#![forbid(missing_docs, missing_debug_implementations)]
type Stack<'a, T> = &'a mut Vec<T>;
type Parser<N, T> = fn(Stack<T>) -> Option<N>;
pub fn enum_parse<N, T>(f: fn(&T) -> Option<N>, stack: Stack<T>) -> Option<N> {
match stack.pop() {
Some(t) => match f(&t) {
Some(n) => Some(n),
None => {
stack.push(t);
None
}
},
None => None,
}
}
pub fn options_parse<N, T: Clone>(l: &[Parser<N, T>], stack: Stack<T>) -> Option<N> {
for p in l.iter() {
if let Some(n) = p(stack) {
return Some(n);
}
}
None
}
pub fn repeated_parse<N, T>(p: Parser<N, T>, stack: Stack<T>) -> Vec<N> {
let mut res: Vec<N> = Vec::new();
loop {
match p(stack) {
Some(s) => res.push(s),
None => return res,
};
}
}
#[cfg(test)]
mod tests {
use crate::{enum_parse, options_parse, repeated_parse, Stack};
#[derive(Debug, PartialEq)]
enum Enum1 {
Even,
Odd,
Zero,
}
fn enum_parse_1(stack: Stack<i32>) -> Option<Enum1> {
enum_parse(
|&n| {
if n < 0 {
None
} else if n == 0 {
Some(Enum1::Zero)
} else if n % 2 == 0 {
Some(Enum1::Even)
} else {
Some(Enum1::Odd)
}
},
stack,
)
}
#[test]
fn enum_parse_1_ok() {
assert_eq!(enum_parse_1(&mut vec![-32, 25, 0]), Some(Enum1::Zero));
assert_eq!(enum_parse_1(&mut vec![-32, 25, 23]), Some(Enum1::Odd));
assert_eq!(enum_parse_1(&mut vec![-32, 25, 2]), Some(Enum1::Even));
}
#[test]
fn enum_parse_1_err() {
assert_eq!(enum_parse_1(&mut vec![-32, 25, -2]), None);
assert_eq!(enum_parse_1(&mut vec![]), None);
}
#[derive(Debug, PartialEq)]
enum Enum2 {
Small,
Tiny,
}
fn enum_parse_2(stack: Stack<i32>) -> Option<Enum2> {
enum_parse(
|&n| {
if n > -10 && n < 0 {
Some(Enum2::Small)
} else if n <= -10 {
Some(Enum2::Tiny)
} else {
None
}
},
stack,
)
}
#[test]
fn enum_parse_2_ok() {
assert_eq!(enum_parse_2(&mut vec![-32, 25, -5]), Some(Enum2::Small));
assert_eq!(enum_parse_2(&mut vec![-32, 25, -20]), Some(Enum2::Tiny));
}
#[test]
fn enum_parse_2_err() {
assert_eq!(enum_parse_2(&mut vec![-32, 25, 2]), None);
assert_eq!(enum_parse_2(&mut vec![]), None);
}
#[derive(Debug, PartialEq)]
enum Enum1And2 {
Is1(Enum1),
Is2(Enum2),
}
fn options_parse_1(stack: Stack<i32>) -> Option<Enum1And2> {
options_parse(
&[
|s| enum_parse_1(s).map(Enum1And2::Is1),
|s| enum_parse_2(s).map(Enum1And2::Is2),
],
stack,
)
}
#[test]
fn options_parse_1_ok() {
assert_eq!(
options_parse_1(&mut vec![5]),
Some(Enum1And2::Is1(Enum1::Odd))
);
assert_eq!(
options_parse_1(&mut vec![0]),
Some(Enum1And2::Is1(Enum1::Zero))
);
assert_eq!(
options_parse_1(&mut vec![-1]),
Some(Enum1And2::Is2(Enum2::Small))
);
assert_eq!(
options_parse_1(&mut vec![-20]),
Some(Enum1And2::Is2(Enum2::Tiny))
);
}
fn repeated_parse_1(stack: Stack<i32>) -> Vec<Enum1> {
repeated_parse(enum_parse_1, stack)
}
#[test]
fn repeated_parse_1_ok() {
assert_eq!(
repeated_parse_1(&mut vec![-1, 3, 2, 1]),
vec![Enum1::Odd, Enum1::Even, Enum1::Odd]
);
assert_eq!(repeated_parse_1(&mut vec![]), vec![]);
assert_eq!(repeated_parse_1(&mut vec![-1]), vec![]);
}
fn repeated_parse_2(stack: Stack<i32>) -> Vec<Enum1And2> {
repeated_parse(options_parse_1, stack)
}
#[test]
fn repeated_parse_2_ok() {
assert_eq!(
repeated_parse_2(&mut vec![-1, 3, 2, 1]),
vec![
Enum1And2::Is1(Enum1::Odd),
Enum1And2::Is1(Enum1::Even),
Enum1And2::Is1(Enum1::Odd),
Enum1And2::Is2(Enum2::Small)
]
);
}
}