use crate::Regex;
use crate::Regex::*;
use std::cmp::Ordering;
use std::iter::Peekable;
#[derive(Debug, Clone)]
pub struct Derivatives<T, R> {
pub d: Vec<(Vec<T>, R)>,
pub rest: R,
}
impl<T, R> Derivatives<T, R> {
pub fn map<F: FnMut(R) -> R>(self, mut f: F) -> Derivatives<T, R> {
Derivatives {
d: self.d.into_iter().map(|(x, r)| (x, f(r))).collect(),
rest: f(self.rest),
}
}
}
pub trait Differentiable<T>: Sized {
fn derivative(&self) -> Derivatives<T, Self>;
}
struct Union<T: Ord, It1: Iterator<Item = T>, It2: Iterator<Item = T>> {
a: Peekable<It1>,
b: Peekable<It2>,
}
fn union<T: Ord, It1: Iterator<Item = T>, It2: Iterator<Item = T>>(
a: It1,
b: It2,
) -> Union<T, It1, It2> {
Union {
a: a.peekable(),
b: b.peekable(),
}
}
impl<T: Ord, It1: Iterator<Item = T>, It2: Iterator<Item = T>> Iterator for Union<T, It1, It2> {
type Item = T;
fn next(&mut self) -> Option<T> {
match match self.a.peek() {
Some(av) => match self.b.peek() {
Some(bv) => av.cmp(bv),
None => Ordering::Less,
},
None => Ordering::Greater,
} {
Ordering::Less => self.a.next(),
Ordering::Greater => self.b.next(),
Ordering::Equal => {
self.a.next();
self.b.next()
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (a1, a2) = self.a.size_hint();
let (b1, b2) = self.b.size_hint();
(
a1 + b1,
if let (Some(a2), Some(b2)) = (a2, b2) {
Some(a2 + b2)
} else {
None
},
)
}
}
struct Inter<T: Ord, It1: Iterator<Item = T>, It2: Iterator<Item = T>> {
a: Peekable<It1>,
b: Peekable<It2>,
}
fn inter<T: Ord, It1: Iterator<Item = T>, It2: Iterator<Item = T>>(
a: It1,
b: It2,
) -> Inter<T, It1, It2> {
Inter {
a: a.peekable(),
b: b.peekable(),
}
}
impl<T: Ord, It1: Iterator<Item = T>, It2: Iterator<Item = T>> Iterator for Inter<T, It1, It2> {
type Item = T;
fn next(&mut self) -> Option<T> {
loop {
match if let (Some(av), Some(bv)) = (self.a.peek(), self.b.peek()) {
av.cmp(bv)
} else {
return None;
} {
Ordering::Less => {
self.a.next();
}
Ordering::Greater => {
self.b.next();
}
Ordering::Equal => {
self.a.next();
return self.b.next();
}
}
}
}
}
struct Subtract<T: Ord, It1: Iterator<Item = T>, It2: Iterator<Item = T>> {
a: Peekable<It1>,
b: Peekable<It2>,
}
fn subtract<T: Ord, It1: Iterator<Item = T>, It2: Iterator<Item = T>>(
a: It1,
b: It2,
) -> Subtract<T, It1, It2> {
Subtract {
a: a.peekable(),
b: b.peekable(),
}
}
impl<T: Ord, It1: Iterator<Item = T>, It2: Iterator<Item = T>> Iterator for Subtract<T, It1, It2> {
type Item = T;
fn next(&mut self) -> Option<T> {
loop {
match match (self.a.peek(), self.b.peek()) {
(Some(av), Some(bv)) => av.cmp(bv),
(_, None) => Ordering::Less,
(None, _) => return None,
} {
Ordering::Less => {
return self.a.next();
}
Ordering::Greater => {
self.b.next();
}
Ordering::Equal => {
self.a.next();
self.b.next();
}
}
}
}
}
enum Set<T> {
Just(Vec<T>),
Not(Vec<T>),
}
impl<T: Ord + Clone> Set<T> {
fn inter(&self, b: &[T]) -> Set<T> {
use self::Set::*;
match *self {
Just(ref a) => Just(inter(a.iter().cloned(), b.iter().cloned()).collect()),
Not(ref a) => Just(subtract(b.iter().cloned(), a.iter().cloned()).collect()),
}
}
fn subtract(&self, b: &[T]) -> Set<T> {
use self::Set::*;
match *self {
Just(ref a) => Just(subtract(a.iter().cloned(), b.iter().cloned()).collect()),
Not(ref a) => Not(union(a.iter().cloned(), b.iter().cloned()).collect()),
}
}
}
fn combine<T: Ord + Clone, R, S, F: FnMut(&[&R]) -> S>(
v: &[Derivatives<T, R>],
mut f: F,
) -> Derivatives<T, S> {
fn go<'a, T: Ord + Clone, R, S, F: FnMut(&[&R]) -> S>(
v: &'a [Derivatives<T, R>],
f: &mut F,
what: Set<T>,
current: &mut Vec<&'a R>,
out: &mut (Vec<(Vec<T>, S)>, Option<S>),
) {
if let Set::Just(ref v) = what {
if v.is_empty() {
return;
}
}
if v.is_empty() {
let reg = f(current);
match what {
Set::Just(c) => out.0.push((c, reg)),
Set::Not(_) => {
assert!(out.1.is_none());
out.1 = Some(reg);
}
}
return;
}
let (first, rest) = v.split_at(1);
let first = &first[0];
let mut all_chars = Vec::new();
for (chars, reg) in first.d.iter() {
all_chars = union(all_chars.into_iter(), chars.iter().cloned()).collect();
let inter = what.inter(chars);
current.push(reg);
go(rest, f, inter, current, out);
current.pop();
}
let inter = what.subtract(&all_chars);
current.push(&first.rest);
go(rest, f, inter, current, out);
current.pop();
}
let mut result = (Vec::new(), None);
let mut regexes = Vec::new();
go(v, &mut f, Set::Not(Vec::new()), &mut regexes, &mut result);
Derivatives {
d: result.0,
rest: result.1.unwrap(),
}
}
impl<T: Ord + Clone> Differentiable<T> for Regex<T> {
fn derivative(&self) -> Derivatives<T, Regex<T>> {
match *self {
Null => Derivatives {
d: Vec::new(),
rest: Null,
},
Empty => Derivatives {
d: Vec::new(),
rest: Null,
},
Except(ref cs) => {
if cs.is_empty() {
Derivatives {
d: Vec::new(),
rest: Empty,
}
} else {
Derivatives {
d: vec![(cs.clone(), Null)],
rest: Empty,
}
}
}
Alt(ref cs, ref xs) => {
let mut ds = Vec::with_capacity(if !cs.is_empty() { 1 } else { 0 } + xs.len());
if !cs.is_empty() {
ds.push(Derivatives {
d: vec![(cs.clone(), Empty)],
rest: Null,
});
}
ds.extend(xs.iter().map(Differentiable::derivative));
combine(&ds, |regexes| {
Alt(Vec::new(), regexes.iter().map(|r| (*r).clone()).collect())
})
}
And(ref xs) => {
let ds: Vec<_> = xs.iter().map(Differentiable::derivative).collect();
combine(&ds, |regexes| {
And(regexes.iter().map(|r| (*r).clone()).collect())
})
}
Not(ref x) => x.derivative().map(|r| Not(Box::new(r))),
Cat(ref xs) => {
let mut ds = Vec::new();
for i in 0..xs.len() {
ds.push(xs[i].derivative().map(|r| {
let mut v = vec![r];
v.extend(xs[i + 1..].iter().cloned());
Cat(v)
}));
if !xs[i].nullable() {
break;
}
}
combine(&ds, |regexes| {
Alt(Vec::new(), regexes.iter().map(|r| (*r).clone()).collect())
})
}
Kleene(ref x) => x.derivative().map(|r| Cat(vec![r, Kleene(x.clone())])),
}
}
}
impl<T: Ord + Clone, R: Differentiable<T> + Clone> Differentiable<T> for Vec<R> {
fn derivative(&self) -> Derivatives<T, Vec<R>> {
let v: Vec<Derivatives<T, R>> = self.iter().map(Differentiable::derivative).collect();
combine(&v, |xs: &[&R]| xs.iter().map(|&x| x.clone()).collect())
}
}