2013-01-16 11:25:41 +01:00
|
|
|
|
|
|
|
|
module DfaExample
|
|
|
|
|
|
|
|
|
|
(** regular expressions on alphabet {0,1} *)
|
|
|
|
|
|
|
|
|
|
type char = Zero | One
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
clone regexp.Regexp with type char = char
|
2013-01-16 11:25:41 +01:00
|
|
|
|
|
|
|
|
(** mutable input stream *)
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use option.Option
|
2024-03-20 18:13:00 +01:00
|
|
|
use seq.Seq
|
2013-01-16 11:25:41 +01:00
|
|
|
|
2024-03-20 18:13:00 +01:00
|
|
|
type stream = abstract { mutable state: seq char }
|
2013-01-16 11:25:41 +01:00
|
|
|
|
|
|
|
|
val input: stream
|
|
|
|
|
|
|
|
|
|
val get () : option char writes {input}
|
2024-03-20 18:13:00 +01:00
|
|
|
ensures {
|
|
|
|
|
if old input.state = empty then
|
|
|
|
|
old input.state = input.state = empty /\ result = None
|
|
|
|
|
else
|
|
|
|
|
input.state = (old input.state)[1..] /\
|
|
|
|
|
result = Some ((old input.state)[0]) }
|
2013-01-16 11:25:41 +01:00
|
|
|
|
|
|
|
|
(** 2-state DFA to recognize words ending with a 1, that is (0|1)*1
|
|
|
|
|
|
|
|
|
|
--------- 1 -------->
|
|
|
|
|
+- state 1 state 2-------+
|
|
|
|
|
| ^ <-------- 0 --------- ^ |
|
|
|
|
|
+-0--/ \----- 1 --+
|
|
|
|
|
*)
|
|
|
|
|
|
2014-02-03 14:38:59 +01:00
|
|
|
constant r0 : regexp = Star (Alt (Char Zero) (Char One))
|
|
|
|
|
constant r1 : regexp = Concat r0 (Char One)
|
2013-01-16 11:25:41 +01:00
|
|
|
constant r2 : regexp = Alt Epsilon r1
|
|
|
|
|
|
2024-03-20 18:13:00 +01:00
|
|
|
lemma empty_notin_r1: not (mem empty r1)
|
2013-01-16 11:25:41 +01:00
|
|
|
|
2024-03-20 18:13:00 +01:00
|
|
|
let rec lemma all_in_r0 (w: word)
|
|
|
|
|
variant { length w }
|
2014-02-03 14:38:59 +01:00
|
|
|
ensures { mem w r0 }
|
2024-03-20 18:13:00 +01:00
|
|
|
= if w = empty then ()
|
|
|
|
|
else (
|
|
|
|
|
assert { w = (cons w[0] empty) ++ w[1..] };
|
|
|
|
|
all_in_r0 w[1..])
|
2014-02-03 14:38:59 +01:00
|
|
|
|
2015-10-22 15:30:14 +02:00
|
|
|
lemma words_in_r1_end_with_one:
|
2024-03-20 18:13:00 +01:00
|
|
|
forall w: word.
|
|
|
|
|
mem w r1 <-> exists w': word. w = w' ++ cons One empty
|
2013-01-16 11:25:41 +01:00
|
|
|
|
2024-03-20 18:13:00 +01:00
|
|
|
lemma words_in_r1_suffix_in_r1:
|
|
|
|
|
forall c c': char. forall w: word.
|
|
|
|
|
mem (cons c (cons c' w)) r1 -> mem (cons c' w) r1
|
2015-10-22 15:30:14 +02:00
|
|
|
|
2024-03-20 18:13:00 +01:00
|
|
|
lemma zero_w_in_r1: forall w: word. mem w r1 <-> mem (cons Zero w) r1
|
|
|
|
|
lemma zero_w_in_r2: forall w: word. mem w r1 <-> mem (cons Zero w) r2
|
|
|
|
|
let lemma one_w_in_r1 (w: word)
|
|
|
|
|
ensures { mem w r2 <-> mem (cons One w) r1 }
|
|
|
|
|
= if length w = 0 then ()
|
|
|
|
|
else (
|
|
|
|
|
let c = w[0] in
|
|
|
|
|
let r = w[1..] in
|
2015-10-22 15:30:14 +02:00
|
|
|
assert { mem w r2 -> mem w r1 };
|
2024-03-20 18:13:00 +01:00
|
|
|
assert { mem (cons One (cons c r)) r1 -> mem w r1 }
|
|
|
|
|
)
|
2013-01-16 11:25:41 +01:00
|
|
|
|
2024-03-20 18:13:00 +01:00
|
|
|
lemma one_w_in_r2: forall w: word. mem w r2 <-> mem (cons One w) r2
|
2013-01-16 11:25:41 +01:00
|
|
|
|
|
|
|
|
let rec astate1 () : bool
|
2014-02-03 14:38:59 +01:00
|
|
|
variant { length input.state }
|
2024-03-20 18:13:00 +01:00
|
|
|
ensures { result <-> input.state = empty /\ mem (old input.state) r1 }
|
|
|
|
|
= match get () with
|
|
|
|
|
| None -> false
|
2013-01-16 11:25:41 +01:00
|
|
|
| Some Zero -> astate1 ()
|
|
|
|
|
| Some One -> astate2 ()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
with astate2 () : bool
|
2014-02-03 14:38:59 +01:00
|
|
|
variant { length input.state }
|
2024-03-20 18:13:00 +01:00
|
|
|
ensures { result <-> input.state = empty /\ mem (old input.state) r2 }
|
|
|
|
|
= match get () with
|
|
|
|
|
| None -> true
|
2013-01-16 11:25:41 +01:00
|
|
|
| Some Zero -> astate1 ()
|
|
|
|
|
| Some One -> astate2 ()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|