use simple_term_rewriter::process::strategy::{DepthOrder, RewriteProcess, SiblingOrder};
use simple_term_rewriter::process::untraced::RewriteProcessUntracedExecutor;
use simple_term_rewriter::rule::{ClosureRewriteRule, RewriteRule};
use simple_term_rewriter::term::syntax::{LanguageTerm, LanguageTermNode, TermFactory};
use super::lang::RegexOp;
pub fn rewrite(
process: RewriteProcess<RegexOp>,
term: LanguageTerm<RegexOp>,
factory: &mut TermFactory<RegexOp>,
) -> Vec<LanguageTerm<RegexOp>> {
RewriteProcessUntracedExecutor::rewrite(&process, &term, factory)
}
pub fn rule_as_process(r: impl RewriteRule<RegexOp> + 'static) -> RewriteProcess<RegexOp> {
RewriteProcess::Rule(Box::new(r))
}
pub fn rule_star_empty() -> ClosureRewriteRule<RegexOp> {
ClosureRewriteRule::new("star(∅)→ε", |t, _, _, f| {
if t.operator != RegexOp::Star {
return None;
}
if t.sub_terms[0].operator == RegexOp::Empty {
Some(LanguageTermNode::build(RegexOp::Epsilon, vec![], f))
} else {
None
}
})
}
pub fn rule_star_epsilon() -> ClosureRewriteRule<RegexOp> {
ClosureRewriteRule::new("star(ε)→ε", |t, _, _, f| {
if t.operator != RegexOp::Star {
return None;
}
if t.sub_terms[0].operator == RegexOp::Epsilon {
Some(LanguageTermNode::build(RegexOp::Epsilon, vec![], f))
} else {
None
}
})
}
pub fn rule_double_star() -> ClosureRewriteRule<RegexOp> {
ClosureRewriteRule::new("star(star(r))→star(r)", |t, _, _, _f| {
if t.operator != RegexOp::Star {
return None;
}
if t.sub_terms[0].operator == RegexOp::Star {
Some(t.sub_terms[0].clone())
} else {
None
}
})
}
pub fn rule_concat_left_empty() -> ClosureRewriteRule<RegexOp> {
ClosureRewriteRule::new("concat(∅,r)→∅", |t, _, _, f| {
if t.operator != RegexOp::Concat {
return None;
}
if t.sub_terms[0].operator == RegexOp::Empty {
Some(LanguageTermNode::build(RegexOp::Empty, vec![], f))
} else {
None
}
})
}
pub fn rule_concat_right_empty() -> ClosureRewriteRule<RegexOp> {
ClosureRewriteRule::new("concat(r,∅)→∅", |t, _, _, f| {
if t.operator != RegexOp::Concat {
return None;
}
if t.sub_terms[1].operator == RegexOp::Empty {
Some(LanguageTermNode::build(RegexOp::Empty, vec![], f))
} else {
None
}
})
}
pub fn rule_concat_left_epsilon() -> ClosureRewriteRule<RegexOp> {
ClosureRewriteRule::new("concat(ε,r)→r", |t, _, _, _f| {
if t.operator != RegexOp::Concat {
return None;
}
if t.sub_terms[0].operator == RegexOp::Epsilon {
Some(t.sub_terms[1].clone())
} else {
None
}
})
}
pub fn rule_concat_right_epsilon() -> ClosureRewriteRule<RegexOp> {
ClosureRewriteRule::new("concat(r,ε)→r", |t, _, _, _f| {
if t.operator != RegexOp::Concat {
return None;
}
if t.sub_terms[1].operator == RegexOp::Epsilon {
Some(t.sub_terms[0].clone())
} else {
None
}
})
}
pub fn rule_alt_left_empty() -> ClosureRewriteRule<RegexOp> {
ClosureRewriteRule::new("alt(∅,r)→r", |t, _, _, _f| {
if t.operator != RegexOp::Alt {
return None;
}
if t.sub_terms[0].operator == RegexOp::Empty {
Some(t.sub_terms[1].clone())
} else {
None
}
})
}
pub fn rule_alt_right_empty() -> ClosureRewriteRule<RegexOp> {
ClosureRewriteRule::new("alt(r,∅)→r", |t, _, _, _f| {
if t.operator != RegexOp::Alt {
return None;
}
if t.sub_terms[1].operator == RegexOp::Empty {
Some(t.sub_terms[0].clone())
} else {
None
}
})
}
pub fn rule_alt_idempotent() -> ClosureRewriteRule<RegexOp> {
ClosureRewriteRule::new("alt(r,r)→r", |t, _, _, _f| {
if t.operator != RegexOp::Alt {
return None;
}
if t.sub_terms[0] == t.sub_terms[1] {
Some(t.sub_terms[0].clone())
} else {
None
}
})
}
pub fn all_rules() -> Vec<Box<dyn RewriteRule<RegexOp>>> {
vec![
Box::new(rule_star_empty()),
Box::new(rule_star_epsilon()),
Box::new(rule_double_star()),
Box::new(rule_concat_left_empty()),
Box::new(rule_concat_right_empty()),
Box::new(rule_concat_left_epsilon()),
Box::new(rule_concat_right_epsilon()),
Box::new(rule_alt_left_empty()),
Box::new(rule_alt_right_empty()),
Box::new(rule_alt_idempotent()),
]
}
pub fn one_step_outermost() -> RewriteProcess<RegexOp> {
let try_root =
RewriteProcess::TryOnePath(all_rules().into_iter().map(RewriteProcess::Rule).collect());
let try_child = RewriteProcess::AnyChild(
SiblingOrder::Leftmost,
DepthOrder::Outermost,
Box::new(RewriteProcess::TryOnePath(
all_rules().into_iter().map(RewriteProcess::Rule).collect(),
)),
);
RewriteProcess::TryOnePath(vec![try_root, try_child])
}
pub fn normalization_strategy() -> RewriteProcess<RegexOp> {
RewriteProcess::Repeat(Box::new(one_step_outermost()))
}