Files
why3/examples/coma/re.coma
2024-10-17 20:00:12 +02:00

149 lines
4.3 KiB
Plaintext

use int.Int
use seq.Seq
use seq.FreeMonoid
(** {Logical definition of Regular Expressions} *)
type char
type regexp =
| Empty
| Epsilon
| Char char
| Alt regexp regexp
| Concat regexp regexp
| Star regexp
predicate re_g (r r1: regexp)
axiom re_g_alt :
forall r r1 r2: regexp.
r = Alt r1 r2 -> re_g r r1 /\ re_g r r2
axiom re_g_concat :
forall r r1 r2: regexp.
r = Concat r1 r2 -> re_g r r1 /\ re_g r r2
axiom re_g_star :
forall r r1: regexp.
r = Star r1 -> re_g r r1
-- lemma re_g_trans :
-- forall r1 r2 r3: regexp. re_g r1 r2 -> re_g r2 r3 -> re_g r1 r3
type word = seq char
inductive mem (w: word) (r: regexp) =
| mem_eps:
mem empty Epsilon
| mem_char:
forall c: char. mem (singleton c) (Char c)
| mem_altl:
forall w: word, r1 r2: regexp. mem w r1 -> mem w (Alt r1 r2)
| mem_altr:
forall w: word, r1 r2: regexp. mem w r2 -> mem w (Alt r1 r2)
| mem_concat:
forall w1 w2: word, r1 r2: regexp.
mem w1 r1 -> mem w2 r2 -> mem (w1 ++ w2) (Concat r1 r2)
| mems1:
forall r: regexp. mem empty (Star r)
| mems2:
forall w1 w2: word, r: regexp.
mem w1 r -> mem w2 (Star r) -> mem (w1 ++ w2) (Star r)
lemma mem_star_nonempty: forall w: word. forall r: regexp.
mem w (Star r) ->
w <> empty ->
exists k: int.
0 < k <= length w /\
mem w[..k] r /\
mem w[k..] (Star r)
lemma split_concat: forall w: word. forall r1 r2: regexp.
mem w (Concat r1 r2) ->
exists k: int.
0 <= k <= length w /\
mem w[..k] r1 /\ mem w[k..] r2
lemma concat_split: forall w: word. forall r1 r2: regexp. forall i j k: int.
0 <= i <= k <= j <= length w ->
mem w[i..k] r1 ->
mem w[k..j] r2 ->
mem w[i..j] (Concat r1 r2)
lemma extseq: forall w: word. w[0..length w] = w
(** {Coma Part} *)
use coma.Std
let unRe (r: regexp)
(empty {r = Empty})
(eps {r = Epsilon})
(char (c: char) {r = Char c})
(alt (r1 r2: regexp) {r = Alt r1 r2})
(cat (r1 r2: regexp) {r = Concat r1 r2})
(star (r1: regexp) {r = Star r1})
= any
predicate cons (w: word) (r: regexp) (ck: int -> bool) (i: int) =
[@inline:trivial]
exists j. i <= j <= length w /\ mem w[i..j] r /\ ck j
let accept_nonterm (r: regexp) (w: word) {} (ret (b: bool) {b <-> mem w r})
= a {r} {0} {fun j -> j = n}
(fun (i: int) (h) -> if {i = n} (ret {true}) h)
(ret {false})
[ a (r: regexp) (i: int) (ck: int -> bool) {0 <= i <= n}
(k (j: int) {mem w[i..j] r} {i <= j <= n} (h {not ck j}))
(o {not cons w r ck i})
= unRe {r} empty eps char alt cat star
[ empty -> o
| eps -> k {i} o
| char (c: char) ->
if {i < n && w[i] = c} (k {i+1} o) o
| alt (r1 r2: regexp) ->
a {r1} {i} {ck} k (-> a {r2} {i} {ck} k o)
| cat (r1 r2: regexp) ->
a {r1} {i} {cons w r2 ck}
(fun (j: int) (h) -> a {r2} {j} {ck} k h) o
| star (r1: regexp) ->
k {i} (-> a {r1} {i} {fun j -> i < j && cons w r ck j}
(fun (j: int) (h) -> if {i < j} (-> a {r} {j} {ck} k h) h)
o)
]
]
[ n: int = length w ]
predicate v (n old_i i: int) (old_r r: regexp) =
(n-i) < (n-old_i) || (old_i=i /\ re_g old_r r)
-- variant lexico : n-i, r
let accept_terminates (r: regexp) (w: word) {} (ret (b: bool) {b <-> mem w r})
= a {r} {0} {fun j -> j = n}
(fun (i: int) (h) -> if {i = n} (ret {true}) h)
({not mem w[0..n] r} ret {false})
[ a (r: regexp) (i: int) (ck: int -> bool) {0 <= i <= n}
(k (j: int) {mem w[i..j] r} {i <= j <= n} (h {not ck j}))
(o {not cons w r ck i})
= (fun (r__: regexp) (i__: int) ->
unRe {r} empty eps char alt cat star
[ empty -> o
| eps -> k {i} o
| char (c: char) ->
if {i < n && w[i] = c} (k {i+1} o) o
| alt (r1 r2: regexp) ->
arec {r1} {i} {ck} k (-> arec {r2} {i} {ck} k o)
| cat (r1 r2: regexp) ->
arec {r1} {i} {cons w r2 ck}
(fun (j: int) (h) -> arec {r2} {j} {ck} k h) o
| star (r1: regexp) ->
k {i} (-> arec {r1} {i} {fun j -> i < j && cons w r ck j}
(fun (j: int) (h) -> if {i < j} (-> arec {r} {j} {ck} k h) h)
o)
]
[ arec (r_: regexp) (i_: int) (ck_: int -> bool) (k_ (j: int) (h)) (o_)
-> { v n i__ i_ r__ r_ } a {r_} {i_} {ck_} k_ o_ ]) {r} {i}
]
[ n: int = length w ]