diff --git a/src/main.rs b/src/main.rs index 425d79e..535e5ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,55 +8,6 @@ enum RegExp { Kleene(Box), } - -// Derivatives - -fn is_nullable (r : &RegExp) -> bool { - match r { - RegExp::Epsilon => true, - RegExp::Kleene(_) => true, - RegExp::Union(r1, r2) => is_nullable(&*r1) | is_nullable(&*r2), - RegExp::Concat(r1, r2) => is_nullable(&*r1) & is_nullable(&*r2), - _ => false, - } -} - -fn derivative(r : &RegExp, a : char) -> RegExp { - match r { - RegExp::Empt => RegExp::Empt, - RegExp::Epsilon => RegExp::Empt, - RegExp::Char(c) => if *c == a { - RegExp::Epsilon - } else { RegExp::Empt }, - RegExp::Union(r1, r2) => - RegExp::Union(Box::new(derivative(&*r1, a)), Box::new(derivative(&*r2, a))), - RegExp::Kleene(r) => - RegExp::Concat(Box::new(derivative(&*r, a)), - Box::new(RegExp::Kleene(Box::new(*r.clone())))), - RegExp::Concat(r1, r2) => { - let r : RegExp = RegExp::Concat(Box::new(derivative(&*r1, a)), - Box::new(*r2.clone())); - if is_nullable(&*r1) { - RegExp::Union(Box::new(derivative(&*r2, a)), Box::new(r)) - } else { - r - } - } - _ => RegExp::Empt, - } -} - -impl RegExp { - fn match_string(self : RegExp, s : &String) -> bool { - let chrs = s.chars(); - let mut rs : RegExp = self; - for c in chrs { - rs = derivative(&rs, c); - } - is_nullable(&rs) - } -} - use std::iter::Peekable; use std::str::Chars; @@ -138,6 +89,55 @@ impl RegExp { } } } + +// Derivatives + +fn is_nullable (r : &RegExp) -> bool { + match r { + RegExp::Epsilon => true, + RegExp::Kleene(_) => true, + RegExp::Union(r1, r2) => is_nullable(&*r1) | is_nullable(&*r2), + RegExp::Concat(r1, r2) => is_nullable(&*r1) & is_nullable(&*r2), + _ => false, + } +} + +fn derivative(r : &RegExp, a : char) -> RegExp { + match r { + RegExp::Empt => RegExp::Empt, + RegExp::Epsilon => RegExp::Empt, + RegExp::Char(c) => if *c == a { + RegExp::Epsilon + } else { RegExp::Empt }, + RegExp::Union(r1, r2) => + RegExp::Union(Box::new(derivative(&*r1, a)), Box::new(derivative(&*r2, a))), + RegExp::Kleene(r) => + RegExp::Concat(Box::new(derivative(&*r, a)), + Box::new(RegExp::Kleene(Box::new(*r.clone())))), + RegExp::Concat(r1, r2) => { + let r : RegExp = RegExp::Concat(Box::new(derivative(&*r1, a)), + Box::new(*r2.clone())); + if is_nullable(&*r1) { + RegExp::Union(Box::new(derivative(&*r2, a)), Box::new(r)) + } else { + r + } + } + _ => RegExp::Empt, + } +} + +impl RegExp { + fn match_string(self : RegExp, s : &String) -> bool { + let chrs = s.chars(); + let mut rs : RegExp = self; + for c in chrs { + rs = derivative(&rs, c); + } + is_nullable(&rs) + } +} + fn main() { let s1 = RegExp::from(String::from("(ab|c)(ab)*")); let inp = String::from("abab");