mirror of
https://github.com/Z3Prover/z3
synced 2025-04-12 04:03:39 +00:00
Regex range bug fix (#5601)
* added a missing derivative case for nonground range * further missing cases and a bug fix in re.to_str
This commit is contained in:
parent
6302b864c8
commit
cb120c93f4
|
@ -3126,21 +3126,49 @@ void seq_rewriter::mk_antimirov_deriv_rec(expr* e, expr* r, expr* path, expr_ref
|
||||||
}
|
}
|
||||||
else if (re().is_range(r, r1, r2)) {
|
else if (re().is_range(r, r1, r2)) {
|
||||||
expr_ref range(m());
|
expr_ref range(m());
|
||||||
expr_ref psi(m());
|
expr_ref psi(m().mk_false(), m());
|
||||||
if (str().is_unit_string(r1, c1) && str().is_unit_string(r2, c2)) {
|
if (str().is_unit_string(r1, c1) && str().is_unit_string(r2, c2)) {
|
||||||
SASSERT(u().is_char(c1));
|
SASSERT(u().is_char(c1));
|
||||||
SASSERT(u().is_char(c2));
|
SASSERT(u().is_char(c2));
|
||||||
// range represents c1 <= e <= c2
|
// case: c1 <= e <= c2
|
||||||
range = simplify_path(m().mk_and(u().mk_le(c1, e), u().mk_le(e, c2)));
|
range = simplify_path(m().mk_and(u().mk_le(c1, e), u().mk_le(e, c2)));
|
||||||
psi = simplify_path(m().mk_and(path, range));
|
psi = simplify_path(m().mk_and(path, range));
|
||||||
if (m().is_false(psi))
|
|
||||||
result = nothing();
|
|
||||||
else
|
|
||||||
// D(e,c1..c2) = if (c1<=e<=c2) then () else []
|
|
||||||
result = re().mk_ite_simplify(range, epsilon(), nothing());
|
|
||||||
}
|
}
|
||||||
else
|
else if (!str().is_string(r1) && str().is_unit_string(r2, c2)) {
|
||||||
|
SASSERT(u().is_char(c2));
|
||||||
|
// r1 nonground: |r1|=1 & r1[0] <= e <= c2
|
||||||
|
expr_ref one(m_autil.mk_int(1), m());
|
||||||
|
expr_ref zero(m_autil.mk_int(0), m());
|
||||||
|
expr_ref r1_length_eq_one(m().mk_eq(str().mk_length(r1), one), m());
|
||||||
|
expr_ref r1_0(str().mk_nth_i(r1, zero), m());
|
||||||
|
range = simplify_path(m().mk_and(r1_length_eq_one, m().mk_and(u().mk_le(r1_0, e), u().mk_le(e, c2))));
|
||||||
|
psi = simplify_path(m().mk_and(path, range));
|
||||||
|
}
|
||||||
|
else if (!str().is_string(r2) && str().is_unit_string(r1, c1)) {
|
||||||
|
SASSERT(u().is_char(c1));
|
||||||
|
// r2 nonground: |r2|=1 & c1 <= e <= r2_0
|
||||||
|
expr_ref one(m_autil.mk_int(1), m());
|
||||||
|
expr_ref zero(m_autil.mk_int(0), m());
|
||||||
|
expr_ref r2_length_eq_one(m().mk_eq(str().mk_length(r2), one), m());
|
||||||
|
expr_ref r2_0(str().mk_nth_i(r2, zero), m());
|
||||||
|
range = simplify_path(m().mk_and(r2_length_eq_one, m().mk_and(u().mk_le(c1, e), u().mk_le(e, r2_0))));
|
||||||
|
psi = simplify_path(m().mk_and(path, range));
|
||||||
|
}
|
||||||
|
else if (!str().is_string(r1) && !str().is_string(r2)) {
|
||||||
|
// both r1 and r2 nonground: |r1|=1 & |r2|=1 & r1[0] <= e <= r2[0]
|
||||||
|
expr_ref one(m_autil.mk_int(1), m());
|
||||||
|
expr_ref zero(m_autil.mk_int(0), m());
|
||||||
|
expr_ref r1_length_eq_one(m().mk_eq(str().mk_length(r1), one), m());
|
||||||
|
expr_ref r1_0(str().mk_nth_i(r1, zero), m());
|
||||||
|
expr_ref r2_length_eq_one(m().mk_eq(str().mk_length(r2), one), m());
|
||||||
|
expr_ref r2_0(str().mk_nth_i(r2, zero), m());
|
||||||
|
range = simplify_path(m().mk_and(r1_length_eq_one, m().mk_and(r2_length_eq_one, m().mk_and(u().mk_le(r1_0, e), u().mk_le(e, r2_0)))));
|
||||||
|
psi = simplify_path(m().mk_and(path, range));
|
||||||
|
}
|
||||||
|
if (m().is_false(psi))
|
||||||
result = nothing();
|
result = nothing();
|
||||||
|
else
|
||||||
|
result = re().mk_ite_simplify(range, epsilon(), nothing());
|
||||||
}
|
}
|
||||||
else if (re().is_union(r, r1, r2))
|
else if (re().is_union(r, r1, r2))
|
||||||
result = mk_antimirov_deriv_union(mk_antimirov_deriv(e, r1, path), mk_antimirov_deriv(e, r2, path));
|
result = mk_antimirov_deriv_union(mk_antimirov_deriv(e, r1, path), mk_antimirov_deriv(e, r2, path));
|
||||||
|
|
|
@ -1233,11 +1233,11 @@ std::ostream& seq_util::rex::pp::print_unit(std::ostream& out, expr* s) const {
|
||||||
print(out, e);
|
print(out, e);
|
||||||
out << "[" << mk_pp(i, re.m) << "]";
|
out << "[" << mk_pp(i, re.m) << "]";
|
||||||
}
|
}
|
||||||
else if (re.m.is_value(e))
|
else if (re.m.is_value(s))
|
||||||
out << mk_pp(e, re.m);
|
out << mk_pp(s, re.m);
|
||||||
else if (is_app(e)) {
|
else if (is_app(s)) {
|
||||||
out << "(" << to_app(e)->get_decl()->get_name().str();
|
out << "(" << to_app(s)->get_decl()->get_name().str();
|
||||||
for (expr * arg : *to_app(e))
|
for (expr * arg : *to_app(s))
|
||||||
print(out << " ", arg);
|
print(out << " ", arg);
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
@ -1266,11 +1266,11 @@ std::ostream& seq_util::rex::pp::print(std::ostream& out, expr* e) const {
|
||||||
else if (re.is_range(e, s, s2))
|
else if (re.is_range(e, s, s2))
|
||||||
print_range(out, s, s2);
|
print_range(out, s, s2);
|
||||||
else if (re.is_epsilon(e))
|
else if (re.is_epsilon(e))
|
||||||
// ε = epsilon
|
// ε = epsilon
|
||||||
out << (html_encode ? "ε" : "()");
|
out << (html_encode ? "ε" : "()");
|
||||||
else if (re.is_empty(e))
|
else if (re.is_empty(e))
|
||||||
// ∅ = emptyset
|
// ∅ = emptyset
|
||||||
out << (html_encode ? "∅" : "[]");
|
out << (html_encode ? "∅" : "[]");
|
||||||
else if (re.is_concat(e, r1, r2)) {
|
else if (re.is_concat(e, r1, r2)) {
|
||||||
print(out, r1);
|
print(out, r1);
|
||||||
print(out, r2);
|
print(out, r2);
|
||||||
|
@ -1278,7 +1278,7 @@ std::ostream& seq_util::rex::pp::print(std::ostream& out, expr* e) const {
|
||||||
else if (re.is_antimorov_union(e, r1, r2) || re.is_union(e, r1, r2)) {
|
else if (re.is_antimorov_union(e, r1, r2) || re.is_union(e, r1, r2)) {
|
||||||
out << "(";
|
out << "(";
|
||||||
print(out, r1);
|
print(out, r1);
|
||||||
out << (html_encode ? "⋃" : "|");
|
out << (html_encode ? "⋃" : "|");
|
||||||
print(out, r2);
|
print(out, r2);
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
@ -1286,7 +1286,7 @@ std::ostream& seq_util::rex::pp::print(std::ostream& out, expr* e) const {
|
||||||
{
|
{
|
||||||
out << "(";
|
out << "(";
|
||||||
print(out, r1);
|
print(out, r1);
|
||||||
out << (html_encode ? "⋂" : "&");
|
out << (html_encode ? "⋂" : "&");
|
||||||
print(out, r2);
|
print(out, r2);
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
@ -1359,11 +1359,11 @@ std::ostream& seq_util::rex::pp::print(std::ostream& out, expr* e) const {
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
else if (re.m.is_ite(e, s, r1, r2)) {
|
else if (re.m.is_ite(e, s, r1, r2)) {
|
||||||
out << (html_encode ? "(𝐢𝐟 " : "(if ");
|
out << (html_encode ? "(𝐢𝐟 " : "(if ");
|
||||||
print(out, s);
|
print(out, s);
|
||||||
out << (html_encode ? " 𝐭𝗵𝐞𝐧 " : " then ");
|
out << (html_encode ? " 𝐭𝗵𝐞𝐧 " : " then ");
|
||||||
print(out, r1);
|
print(out, r1);
|
||||||
out << (html_encode ? " 𝐞𝐥𝘀𝐞 " : " else ");
|
out << (html_encode ? " 𝐞𝐥𝘀𝐞 " : " else ");
|
||||||
print(out, r2);
|
print(out, r2);
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue