regex matching
This commit is contained in:
parent
e6c9c27b33
commit
009b3cb261
113
src/main.rs
113
src/main.rs
|
@ -8,6 +8,9 @@ enum RegExp {
|
|||
Kleene(Box<RegExp>),
|
||||
}
|
||||
|
||||
|
||||
// Derivatives
|
||||
|
||||
fn is_nullable (r : &RegExp) -> bool {
|
||||
match r {
|
||||
RegExp::Epsilon => true,
|
||||
|
@ -43,22 +46,102 @@ fn derivative(r : &RegExp, a : char) -> RegExp {
|
|||
}
|
||||
}
|
||||
|
||||
fn regexp_match(r : RegExp, s : &String) -> bool {
|
||||
let chrs = s.chars();
|
||||
let mut rs : RegExp = r;
|
||||
for c in chrs {
|
||||
println!("Computing der({:?}, {:?}) ...", rs, c);
|
||||
rs = derivative(&rs, c);
|
||||
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)
|
||||
}
|
||||
println!("Result: {:?}", rs);
|
||||
is_nullable(&rs)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let r1 = RegExp::Concat(Box::new( RegExp::Char('a')), Box::new( RegExp::Char('b')));
|
||||
let r2 = RegExp::Kleene(Box::new(r1.clone()));
|
||||
let r3 = RegExp::Concat(Box::new(RegExp::Union(Box::new(r1.clone()), Box::new(RegExp::Char('c')))), Box::new(r2.clone()));
|
||||
let inp = String::from("c");
|
||||
let res = regexp_match(r3.clone(), &inp);
|
||||
println!("match {:?}, {:?} = {:?}", r3, inp, res);
|
||||
use std::iter::Peekable;
|
||||
use std::str::Chars;
|
||||
|
||||
enum ParseError {
|
||||
EatMismatch(char),
|
||||
EndOfString,
|
||||
Heh
|
||||
}
|
||||
|
||||
fn eat(str : &mut Peekable<Chars>, c : char) -> Result<char, ParseError> {
|
||||
match str.next_if(|&x| x == c) {
|
||||
Some(c) => Ok(c),
|
||||
None => Err(ParseError::EatMismatch(c))
|
||||
}
|
||||
}
|
||||
|
||||
fn term(str : &mut Peekable<Chars>) -> Result<RegExp, ParseError> {
|
||||
let mut result = RegExp::Epsilon;
|
||||
loop {
|
||||
match str.peek() {
|
||||
Some(&c) if (c != ')') & (c != '|') => {
|
||||
let r = factor(str)?;
|
||||
result = RegExp::Concat(Box::new(result), Box::new(r))
|
||||
},
|
||||
_ => { break; }
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn regex(str : &mut Peekable<Chars>) -> Result<RegExp, ParseError> {
|
||||
let t = term(str)?;
|
||||
match str.peek() {
|
||||
Some('|') => {
|
||||
let _ = eat(str, '|');
|
||||
let r = regex(str)?;
|
||||
Ok(RegExp::Union(Box::new(t), Box::new(r)))
|
||||
},
|
||||
_ => Ok(t)
|
||||
}
|
||||
}
|
||||
|
||||
fn factor(str : &mut Peekable<Chars>) -> Result<RegExp, ParseError> {
|
||||
let mut result = base(str)?;
|
||||
loop {
|
||||
match str.peek() {
|
||||
Some(&c) if (c == '*') => {
|
||||
let _ = eat(str, '*')?;
|
||||
result = RegExp::Kleene(Box::new(result))
|
||||
},
|
||||
_ => { break; }
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn base(str : &mut Peekable<Chars>) -> Result<RegExp, ParseError> {
|
||||
match str.peek() {
|
||||
Some(&c) => {
|
||||
if c == '(' {
|
||||
let _ = eat(str, '(')?;
|
||||
let r = regex(str)?;
|
||||
let _ = eat(str, ')')?;
|
||||
Ok(r)
|
||||
} else {
|
||||
let _ = eat(str, c)?;
|
||||
Ok(RegExp::Char(c))
|
||||
}
|
||||
},
|
||||
None => Err(ParseError::EndOfString)
|
||||
}
|
||||
}
|
||||
|
||||
impl RegExp {
|
||||
fn from(str : String) -> RegExp {
|
||||
match regex(&mut str.chars().peekable()) {
|
||||
Ok(r) => r,
|
||||
_ => panic!("Ooooo")
|
||||
}
|
||||
}
|
||||
}
|
||||
fn main() {
|
||||
let s1 = RegExp::from(String::from("(ab|c)(ab)*"));
|
||||
let inp = String::from("abab");
|
||||
let res = s1.clone().match_string(&inp);
|
||||
println!("match {:?}, {:?} = {:?}", s1, inp, res);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue