mirror of
https://github.com/Z3Prover/z3
synced 2026-07-17 04:25:44 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Margus Veanes <margus@microsoft.com> Co-authored-by: Margus Veanes <veanes@users.noreply.github.com>
71 lines
2.7 KiB
C++
71 lines
2.7 KiB
C++
/*++
|
|
Copyright (c) 2026 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
seq_range_collapse.h
|
|
|
|
Abstract:
|
|
|
|
Recognize regexes that are boolean combinations of character-class
|
|
primitives (re.empty, re.full_char, re.range with concrete chars,
|
|
and re.union/inter/comp/diff over translatable arguments), and
|
|
materialize a seq::range_predicate back into a canonical regex AST.
|
|
|
|
Together with seq_rewriter integration, this lets any boolean
|
|
combination of character-class regexes collapse to a canonical
|
|
multi-range form, so that equivalent character classes share AST
|
|
identity, and downstream consumers (derivative, OneStep, caching)
|
|
can short-circuit them as pure range predicates.
|
|
|
|
Authors:
|
|
|
|
Margus Veanes (veanes) 2026
|
|
|
|
--*/
|
|
#pragma once
|
|
|
|
#include "ast/rewriter/seq_range_predicate.h"
|
|
#include "ast/seq_decl_plugin.h"
|
|
|
|
namespace seq {
|
|
|
|
/**
|
|
* If r is a boolean combination of character-class regex primitives
|
|
* over the unsigned character domain [0, max_char], compute the
|
|
* equivalent range_predicate and return true. Otherwise return false
|
|
* with out untouched.
|
|
*
|
|
* Recognized fragment (all character-class-preserving operations):
|
|
* re.empty -> empty
|
|
* re.full_char_set -> top
|
|
* re.range "c_lo" "c_hi" (concrete) -> [c_lo, c_hi]
|
|
* re.union r1 r2 -> p1 | p2
|
|
* re.intersection r1 r2 -> p1 & p2
|
|
* re.diff r1 r2 -> p1 - p2
|
|
*
|
|
* Notably re.complement is NOT recognized: it is a SEQUENCE-level
|
|
* complement (over all of Σ*), not a character-class complement, so
|
|
* collapsing it would change semantics whenever the result is used
|
|
* in any non-character-class context. Sequence-level rewrites for
|
|
* re.complement (double-comp, deMorgan, etc.) are handled directly
|
|
* in seq_rewriter::mk_re_complement.
|
|
*/
|
|
bool regex_to_range_predicate(seq_util& u, expr* r, range_predicate& out);
|
|
|
|
/**
|
|
* Canonical materialization of p as a regex AST over the given
|
|
* sequence sort. Two range_predicates with equal canonical
|
|
* representations produce structurally identical regex ASTs:
|
|
*
|
|
* empty -> re.empty
|
|
* top -> re.full_char_set
|
|
* single range [lo, hi] -> re.range "lo" "hi"
|
|
* multiple ranges -> right-associated re.union of single
|
|
* ranges, in increasing order of lo
|
|
* (matching the canonical range order
|
|
* held by range_predicate).
|
|
*/
|
|
expr_ref range_predicate_to_regex(seq_util& u, range_predicate const& p, sort* seq_sort);
|
|
|
|
}
|