mirror of
https://github.com/Z3Prover/z3
synced 2025-07-18 02:16:40 +00:00
add partial support for complementation of regular expressions. Handles case of complementing character ranges
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
9dbb8057ca
commit
94453033b6
4 changed files with 93 additions and 6 deletions
|
@ -83,7 +83,7 @@ eautomaton* re2automaton::operator()(expr* e) {
|
|||
|
||||
eautomaton* re2automaton::re2aut(expr* e) {
|
||||
SASSERT(u.is_re(e));
|
||||
expr* e1, *e2;
|
||||
expr *e0, *e1, *e2;
|
||||
scoped_ptr<eautomaton> a, b;
|
||||
unsigned lo, hi;
|
||||
zstring s1, s2;
|
||||
|
@ -98,8 +98,7 @@ eautomaton* re2automaton::re2aut(expr* e) {
|
|||
}
|
||||
else if (u.re.is_star(e, e1) && (a = re2aut(e1))) {
|
||||
a->add_final_to_init_moves();
|
||||
a->add_init_to_final_states();
|
||||
|
||||
a->add_init_to_final_states();
|
||||
return a.detach();
|
||||
}
|
||||
else if (u.re.is_plus(e, e1) && (a = re2aut(e1))) {
|
||||
|
@ -116,8 +115,6 @@ eautomaton* re2automaton::re2aut(expr* e) {
|
|||
unsigned start = s1[0];
|
||||
unsigned stop = s2[0];
|
||||
unsigned nb = s1.num_bits();
|
||||
sort_ref s(bv.mk_sort(nb), m);
|
||||
expr_ref v(m.mk_var(0, s), m);
|
||||
expr_ref _start(bv.mk_numeral(start, nb), m);
|
||||
expr_ref _stop(bv.mk_numeral(stop, nb), m);
|
||||
a = alloc(eautomaton, sm, sym_expr::mk_range(_start, _stop));
|
||||
|
@ -127,6 +124,39 @@ eautomaton* re2automaton::re2aut(expr* e) {
|
|||
TRACE("seq", tout << "Range expression is not handled: " << mk_pp(e, m) << "\n";);
|
||||
}
|
||||
}
|
||||
else if (u.re.is_complement(e, e0)) {
|
||||
if (u.re.is_range(e0, e1, e2) && u.str.is_string(e1, s1) && u.str.is_string(e2, s2) &&
|
||||
s1.length() == 1 && s2.length() == 1) {
|
||||
unsigned start = s1[0];
|
||||
unsigned stop = s2[0];
|
||||
unsigned nb = s1.num_bits();
|
||||
sort_ref s(bv.mk_sort(nb), m);
|
||||
expr_ref v(m.mk_var(0, s), m);
|
||||
expr_ref _start(bv.mk_numeral(start, nb), m);
|
||||
expr_ref _stop(bv.mk_numeral(stop, nb), m);
|
||||
expr_ref _pred(m.mk_not(m.mk_and(bv.mk_ule(_start, v), bv.mk_ule(v, _stop))), m);
|
||||
a = alloc(eautomaton, sm, sym_expr::mk_pred(_pred));
|
||||
return a.detach();
|
||||
}
|
||||
else if (u.re.is_to_re(e0, e1) && u.str.is_string(e1, s1) && s1.length() == 1) {
|
||||
unsigned nb = s1.num_bits();
|
||||
sort_ref s(bv.mk_sort(nb), m);
|
||||
expr_ref v(m.mk_var(0, s), m);
|
||||
expr_ref _ch(bv.mk_numeral(s1[0], nb), m);
|
||||
expr_ref _pred(m.mk_not(m.mk_eq(v, _ch)), m);
|
||||
a = alloc(eautomaton, sm, sym_expr::mk_pred(_pred));
|
||||
return a.detach();
|
||||
}
|
||||
else if (u.re.is_to_re(e0, e1) && u.str.is_unit(e1, e2)) {
|
||||
expr_ref v(m.mk_var(0, m.get_sort(e2)), m);
|
||||
expr_ref _pred(m.mk_not(m.mk_eq(v, e2)), m);
|
||||
a = alloc(eautomaton, sm, sym_expr::mk_pred(_pred));
|
||||
return a.detach();
|
||||
}
|
||||
else {
|
||||
TRACE("seq", tout << "Complement expression is not handled: " << mk_pp(e, m) << "\n";);
|
||||
}
|
||||
}
|
||||
else if (u.re.is_loop(e, e1, lo, hi) && (a = re2aut(e1))) {
|
||||
scoped_ptr<eautomaton> eps = eautomaton::mk_epsilon(sm);
|
||||
b = eautomaton::mk_epsilon(sm);
|
||||
|
@ -225,6 +255,9 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
case OP_RE_INTERSECT:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_re_inter(args[0], args[1], result);
|
||||
case OP_RE_COMPLEMENT:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_re_complement(args[0], result);
|
||||
case OP_RE_LOOP:
|
||||
return mk_re_loop(num_args, args, result);
|
||||
case OP_RE_EMPTY_SET:
|
||||
|
@ -967,6 +1000,26 @@ br_status seq_rewriter::mk_re_union(expr* a, expr* b, expr_ref& result) {
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_re_complement(expr* a, expr_ref& result) {
|
||||
expr* e1, *e2;
|
||||
if (m_util.re.is_intersection(a, e1, e2)) {
|
||||
result = m_util.re.mk_union(m_util.re.mk_complement(e1), m_util.re.mk_complement(e2));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m_util.re.is_union(a, e1, e2)) {
|
||||
result = m_util.re.mk_inter(m_util.re.mk_complement(e1), m_util.re.mk_complement(e2));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m_util.re.is_empty(a)) {
|
||||
result = m_util.re.mk_full(m().get_sort(a));
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.re.is_full(a)) {
|
||||
result = m_util.re.mk_empty(m().get_sort(a));
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
(emp n r) = emp
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue