mirror of
https://github.com/Z3Prover/z3
synced 2025-08-19 09:40:20 +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
2 changed files with 50 additions and 22 deletions
|
@ -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)) {
|
||||
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)) {
|
||||
SASSERT(u().is_char(c1));
|
||||
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)));
|
||||
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();
|
||||
else
|
||||
result = re().mk_ite_simplify(range, epsilon(), nothing());
|
||||
}
|
||||
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));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue