This commit is contained in:
Dan Frumin 2024-06-11 16:18:40 +02:00
parent 009b3cb261
commit ba64e19894
1 changed files with 49 additions and 49 deletions

View File

@ -8,55 +8,6 @@ enum RegExp {
Kleene(Box<RegExp>), Kleene(Box<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)
}
}
use std::iter::Peekable; use std::iter::Peekable;
use std::str::Chars; 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() { fn main() {
let s1 = RegExp::from(String::from("(ab|c)(ab)*")); let s1 = RegExp::from(String::from("(ab|c)(ab)*"));
let inp = String::from("abab"); let inp = String::from("abab");