mod common;
use hashconsing::HConsign;
use simple_term_rewriter::position::PositionInLanguageTerm;
use simple_term_rewriter::rules::combinators::guard::{
ClosureRewriteApplicationGuard, NotUnderSameOpRewriteApplicationGuard,
OnlyUnderOpRewriteApplicationGuard, RewriteApplicationGuard, RootOnlyRewriteApplicationGuard,
TermPredicateRewriteApplicationGuard,
};
use simple_term_rewriter::term::syntax::TermFactory;
use common::regex::constructors::*;
use common::regex::lang::RegexOp;
fn root() -> PositionInLanguageTerm {
PositionInLanguageTerm::get_root_position()
}
fn child(n: usize) -> PositionInLanguageTerm {
root().get_position_of_nth_child(n)
}
#[test]
fn root_only_allows_at_root() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g = RootOnlyRewriteApplicationGuard;
let t = epsilon(&mut f);
assert!(g.allows(&t, &t, &root()));
}
#[test]
fn root_only_blocks_at_depth_one() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g = RootOnlyRewriteApplicationGuard;
let ctx = concat(epsilon(&mut f), empty(&mut f), &mut f);
let node = ctx.sub_terms[0].clone();
assert!(!g.allows(&node, &ctx, &child(0)));
}
#[test]
fn root_only_blocks_at_depth_two() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g = RootOnlyRewriteApplicationGuard;
let ctx = concat(star(epsilon(&mut f), &mut f), empty(&mut f), &mut f);
let node = ctx.sub_terms[0].sub_terms[0].clone();
let pos = child(0).get_position_of_nth_child(0);
assert!(!g.allows(&node, &ctx, &pos));
}
#[test]
fn not_under_same_op_allows_at_root() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g = NotUnderSameOpRewriteApplicationGuard;
let t = concat(epsilon(&mut f), empty(&mut f), &mut f);
assert!(g.allows(&t, &t, &root()));
}
#[test]
fn not_under_same_op_allows_when_parent_differs() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g = NotUnderSameOpRewriteApplicationGuard;
let ctx = concat(
alt(epsilon(&mut f), empty(&mut f), &mut f),
epsilon(&mut f),
&mut f,
);
let node = ctx.sub_terms[0].clone();
assert!(g.allows(&node, &ctx, &child(0)));
}
#[test]
fn not_under_same_op_blocks_when_parent_is_same() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g = NotUnderSameOpRewriteApplicationGuard;
let ctx = concat(
concat(epsilon(&mut f), empty(&mut f), &mut f),
epsilon(&mut f),
&mut f,
);
let node = ctx.sub_terms[0].clone();
assert!(!g.allows(&node, &ctx, &child(0)));
}
#[test]
fn not_under_same_op_allows_when_parent_lookup_returns_none() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g = NotUnderSameOpRewriteApplicationGuard;
let ctx = concat(epsilon(&mut f), empty(&mut f), &mut f);
let t = epsilon(&mut f);
let pos = child(5).get_position_of_nth_child(0);
assert!(g.allows(&t, &ctx, &pos));
}
fn only_under_concat() -> OnlyUnderOpRewriteApplicationGuard<RegexOp> {
OnlyUnderOpRewriteApplicationGuard::new(|op: &RegexOp| *op == RegexOp::Concat)
}
#[test]
fn only_under_op_blocks_at_root() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let ctx = concat(epsilon(&mut f), empty(&mut f), &mut f);
assert!(!only_under_concat().allows(&ctx, &ctx, &root()));
}
#[test]
fn only_under_op_allows_when_parent_matches_predicate() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let ctx = concat(epsilon(&mut f), empty(&mut f), &mut f);
let node = ctx.sub_terms[0].clone();
assert!(only_under_concat().allows(&node, &ctx, &child(0)));
}
#[test]
fn only_under_op_blocks_when_parent_does_not_match_predicate() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let ctx = alt(epsilon(&mut f), empty(&mut f), &mut f);
let node = ctx.sub_terms[0].clone();
assert!(!only_under_concat().allows(&node, &ctx, &child(0)));
}
#[test]
fn only_under_op_blocks_when_parent_lookup_returns_none() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let ctx = concat(epsilon(&mut f), empty(&mut f), &mut f);
let t = epsilon(&mut f);
let pos = child(5).get_position_of_nth_child(0);
assert!(!only_under_concat().allows(&t, &ctx, &pos));
}
#[test]
fn term_predicate_allows_when_predicate_holds() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g =
TermPredicateRewriteApplicationGuard::<RegexOp>::new(|t| t.operator == RegexOp::Epsilon);
let t = epsilon(&mut f);
let ctx = concat(empty(&mut f), empty(&mut f), &mut f);
assert!(g.allows(&t, &ctx, &child(3)));
}
#[test]
fn term_predicate_blocks_when_predicate_fails() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g =
TermPredicateRewriteApplicationGuard::<RegexOp>::new(|t| t.operator == RegexOp::Epsilon);
let t = empty(&mut f);
assert!(!g.allows(&t, &t, &root()));
}
#[test]
fn term_predicate_ignores_context_and_position() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g = TermPredicateRewriteApplicationGuard::<RegexOp>::new(|t| t.operator == RegexOp::Star);
let t = star(epsilon(&mut f), &mut f);
let ctx = concat(empty(&mut f), empty(&mut f), &mut f);
assert!(g.allows(&t, &ctx, &root()));
assert!(g.allows(&t, &ctx, &child(7)));
assert!(g.allows(&t, &t, &child(0).get_position_of_nth_child(2)));
}
#[test]
fn closure_guard_returns_true_when_closure_returns_true() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g = ClosureRewriteApplicationGuard::<RegexOp>::new(|_, _, _| true);
let t = epsilon(&mut f);
assert!(g.allows(&t, &t, &root()));
}
#[test]
fn closure_guard_returns_false_when_closure_returns_false() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g = ClosureRewriteApplicationGuard::<RegexOp>::new(|_, _, _| false);
let t = epsilon(&mut f);
assert!(!g.allows(&t, &t, &root()));
}
#[test]
fn closure_guard_receives_all_three_arguments() {
let mut f: TermFactory<RegexOp> = HConsign::empty();
let g = ClosureRewriteApplicationGuard::<RegexOp>::new(|term, ctx, pos| {
term.operator == RegexOp::Epsilon && ctx.operator == RegexOp::Concat && pos.get_depth() == 1
});
let ctx = concat(epsilon(&mut f), empty(&mut f), &mut f);
let node = ctx.sub_terms[0].clone(); assert!(g.allows(&node, &ctx, &child(0)));
assert!(!g.allows(&node, &ctx, &root())); assert!(!g.allows(&ctx.sub_terms[1].clone(), &ctx, &child(1))); }