use core::marker::PhantomData;
use std::iter::Map;
enum Node {
Null,
Leaf(u8),
And(Box<Node>, Box<Node>),
Or(Box<Node>, Box<Node>),
Dl(Box<Node>, Box<Node>),
Dr(Box<Node>, Box<Node>),
P(Box<dyn Fn(u8) -> bool + 'static>),
Tuf(Box<Node>)
}
#[derive(Debug, PartialEq)]
pub enum Ret {
NoVal,
Char(u8),
Val(Box<Ret>),
Tup(Box<Ret>, Box<Ret>),
}
use Ret::*;
use Node::*;
use core::ops::{BitOr, BitAnd, Shl, Shr};
impl Node {
pub fn run(&self, input: &str) -> Option<Ret> {
self._run(input.as_bytes(), &mut 0)
}
fn _run(&self, input: &[u8], index: &mut usize) -> Option<Ret> {
match self {
Null => Some(NoVal),
Leaf(ch) => {
let result = input
.get(*index)
.filter(|x| **x == *ch)
.map(|x| Char(*x));
*index += 1;
result
},
And(box lhs, box rhs) => {
let x = lhs._run(input, index)?;
let y = rhs._run(input, index)?;
Some(Tup(box x, box y))
},
Or(box lhs, box rhs) => {
lhs._run(input, index)
.map(|x| Val(box x))
.or_else(|| rhs._run(input, index).map(|x| Val(box x)))
},
Dl(box lhs, box rhs) => {
lhs._run(input, index)?;
rhs._run(input, index).map(|x| Val(box x))
},
Dr(box lhs, box rhs) => {
let x = lhs._run(input, index)?;
rhs._run(input, index)?;
Some(Val(box x))
},
P(f) => {
Some(input
.iter()
.take_while(|&&ch| f(ch))
.fold(NoVal, |rest, ch| Tup(box Char(*ch), box rest)))
},
Tuf(box p) => {
let mut result = NoVal;
while let Some(ret) = p._run(input, index) {
result = Tup(box ret, box result);
}
Some(result)
}
}
}
}
impl BitOr for Node {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Or(box self, box rhs)
}
}
impl BitAnd for Node {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
And(box self, box rhs)
}
}
impl Shr for Node {
type Output = Self;
fn shr(self, rhs: Self) -> Self::Output {
Dl(box self, box rhs)
}
}
impl Shl for Node {
type Output = Self;
fn shl(self, rhs: Self) -> Self::Output {
Dr(box self, box rhs)
}
}
impl TryFrom<Ret> for u8 {
type Error = &'static str;
fn try_from(val: Ret) -> Result<u8, Self::Error> {
match val {
NoVal => Err("Empty value cannot be converted to char!"),
Char(ch) | Val(box Char(ch)) => Ok(ch),
_ => Err("Collection of values cannot be converted to a single char!")
}
}
}
impl TryFrom<Ret> for char {
type Error = &'static str;
fn try_from(val: Ret) -> Result<char, Self::Error> {
let b: u8 = val.try_into()?;
Ok(b as char)
}
}
impl TryFrom<Ret> for String {
type Error = &'static str;
fn try_from(val: Ret) -> Result<String, Self::Error> {
match val {
NoVal => Ok("".into()),
Char(ch) | Val(box Char(ch)) => Ok((ch as char).into()),
Val(box ret) => ret.try_into(),
Tup(box lhs, box rhs) => {
let fhalf: String = lhs.try_into()?;
let shalf: String = rhs.try_into()?;
Ok(fhalf + &shalf)
}
}
}
}
impl TryFrom<Ret> for bool {
type Error = &'static str;
fn try_from(val: Ret) -> Result<bool, Self::Error> {
let result: String = val.try_into()?;
match result.as_str() {
"true" => Ok(true),
"false" => Ok(false),
x => Err("Cannot convert to bool")
}
}
}
impl<T: TryFrom<Ret>> TryFrom<Ret> for Vec<T> {
type Error = <T as TryFrom<Ret>>::Error;
fn try_from(mut val: Ret) -> Result<Vec<T>, Self::Error> {
let mut result = vec![];
while let Tup(box x, box xs) = val {
result.push(x.try_into()?);
val = xs;
}
Ok(result)
}
}
impl TryFrom<Ret> for i64 {
type Error = &'static str;
fn try_from(val: Ret) -> Result<i64, Self::Error> {
let st: String = val.try_into()?;
st.parse().map_err(|_| "Unable to parse as a valid integer")
}
}
pub struct Parser<T: TryFrom<Ret>>(Node, PhantomData<T>);
impl<T: TryFrom<Ret>> Parser<T>
{
fn new(node: Node) -> Self {
Parser(node, PhantomData)
}
pub fn lift<U: TryFrom<Ret>>(self) -> Parser<U> {
Parser::<U>::new(self.0)
}
pub fn run(&self, input: &str) -> Option<Result<T, <T as TryFrom<Ret>>::Error>> {
self.0
.run(input)
.map(|x| x.try_into())
}
}
pub fn char_p(ch: char) -> Parser<char> {
Parser::new(Leaf(ch as u8))
}
pub fn one_of_p<T, I>(iter: I) -> Parser<T>
where
T: TryFrom<Ret>,
I: IntoIterator<Item=Parser<T>>
{
Parser::new(
iter
.into_iter()
.fold(Null,
move |rest, Parser(node, _)| Or(box node, box rest))
)
}
pub fn all_of_p<T, I>(iter: I) -> Parser<Vec<T>>
where
T: TryFrom<Ret>,
I: IntoIterator<Item=Parser<T>>,
{
Parser::new(
iter
.into_iter()
.fold(Null,
move |rest, Parser(node, _)| And(box node, box rest))
)
}
pub fn zero_or_more_p<T, C>(Parser(p, _): Parser<T>) -> Parser<Vec<T>>
where
T: TryFrom<Ret>,
{
Parser::new(Tuf(box p))
}
pub fn till_p<F>(f: F) -> Parser<String>
where
F: Fn(u8) -> bool + 'static
{
Parser::new(P(box f))
}
pub fn str_p(st: &str) -> Parser<String> {
Parser::new(
st
.chars()
.fold(Null,
move |rest, ch| And(box Leaf(ch as u8), box rest))
)
}
pub fn bool_p() -> Parser<bool> {
let p = one_of_p([str_p("true"), str_p("false")]);
p.lift()
}
pub fn digit_p() -> Parser<char> {
one_of_p(('0'..'9').map(|x| Parser::new(Leaf(x as u8))))
}