Mercurial > cpdt > repo
diff src/MoreDep.v @ 86:fd505bcb5632
Start of certified regexp matcher
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Mon, 06 Oct 2008 14:33:11 -0400 |
parents | 3746a2ded8da |
children | a0b8b550e265 |
line wrap: on
line diff
--- a/src/MoreDep.v Mon Oct 06 13:07:24 2008 -0400 +++ b/src/MoreDep.v Mon Oct 06 14:33:11 2008 -0400 @@ -10,7 +10,7 @@ (* begin hide *) Require Import Arith Bool List. -Require Import Tactics. +Require Import Tactics MoreSpecif. Set Implicit Arguments. (* end hide *) @@ -342,3 +342,136 @@ | [ |- (if ?E then _ else _) = _ ] => destruct E end; crush). Qed. + + +(** * A Certified Regular Expression Matcher *) + +Require Import Ascii String. +Open Scope string_scope. + +Inductive regexp : (string -> Prop) -> Set := +| Char : forall ch : ascii, + regexp (fun s => s = String ch "") +| Concat : forall P1 P2 (r1 : regexp P1) (r2 : regexp P2), + regexp (fun s => exists s1, exists s2, s = s1 ++ s2 /\ P1 s1 /\ P2 s2). + +Open Scope specif_scope. + +Lemma length_emp : length "" <= 0. + crush. +Qed. + +Lemma append_emp : forall s, s = "" ++ s. + crush. +Qed. + +Ltac substring := + crush; + repeat match goal with + | [ |- context[match ?N with O => _ | S _ => _ end] ] => destruct N; crush + end. + +Lemma substring_le : forall s n m, + length (substring n m s) <= m. + induction s; substring. +Qed. + +Lemma substring_all : forall s, + substring 0 (length s) s = s. + induction s; substring. +Qed. + +Lemma substring_none : forall s n, + substring n 0 s = EmptyString. + induction s; substring. +Qed. + +Hint Rewrite substring_all substring_none : cpdt. + +Lemma substring_split : forall s m, + substring 0 m s ++ substring m (length s - m) s = s. + induction s; substring. +Qed. + +Lemma length_app1 : forall s1 s2, + length s1 <= length (s1 ++ s2). + induction s1; crush. +Qed. + +Hint Resolve length_emp append_emp substring_le substring_split length_app1. + +Lemma substring_app_fst : forall s2 s1 n, + length s1 = n + -> substring 0 n (s1 ++ s2) = s1. + induction s1; crush. +Qed. + +Lemma substring_app_snd : forall s2 s1 n, + length s1 = n + -> substring n (length (s1 ++ s2) - n) (s1 ++ s2) = s2. + Hint Rewrite <- minus_n_O : cpdt. + + induction s1; crush. +Qed. + +Hint Rewrite substring_app_fst substring_app_snd using assumption : cpdt. + +Section split. + Variables P1 P2 : string -> Prop. + Variable P1_dec : forall s, {P1 s} + {~P1 s}. + Variable P2_dec : forall s, {P2 s} + {~P2 s}. + + Variable s : string. + + Definition split' (n : nat) : n <= length s + -> {exists s1, exists s2, length s1 <= n /\ s1 ++ s2 = s /\ P1 s1 /\ P2 s2} + + {forall s1 s2, length s1 <= n -> s1 ++ s2 = s -> ~P1 s1 \/ ~P2 s2}. + refine (fix F (n : nat) : n <= length s + -> {exists s1, exists s2, length s1 <= n /\ s1 ++ s2 = s /\ P1 s1 /\ P2 s2} + + {forall s1 s2, length s1 <= n -> s1 ++ s2 = s -> ~P1 s1 \/ ~P2 s2} := + match n return n <= length s + -> {exists s1, exists s2, length s1 <= n /\ s1 ++ s2 = s /\ P1 s1 /\ P2 s2} + + {forall s1 s2, length s1 <= n -> s1 ++ s2 = s -> ~P1 s1 \/ ~P2 s2} with + | O => fun _ => Reduce (P1_dec "" && P2_dec s) + | S n' => fun _ => (P1_dec (substring 0 (S n') s) && P2_dec (substring (S n') (length s - S n') s)) + || F n' _ + end); clear F; crush; eauto 7; + match goal with + | [ _ : length ?S <= 0 |- _ ] => destruct S + | [ _ : length ?S' <= S ?N |- _ ] => + generalize (eq_nat_dec (length S') (S N)); destruct 1 + end; crush. + Defined. + + Definition split : {exists s1, exists s2, s = s1 ++ s2 /\ P1 s1 /\ P2 s2} + + {forall s1 s2, s = s1 ++ s2 -> ~P1 s1 \/ ~P2 s2}. + refine (Reduce (split' (n := length s) _)); crush; eauto. + Defined. +End split. + +Implicit Arguments split [P1 P2]. + +Lemma app_cong : forall x1 y1 x2 y2, + x1 = x2 + -> y1 = y2 + -> x1 ++ y1 = x2 ++ y2. + congruence. +Qed. + +Hint Resolve app_cong. + +Definition matches P (r : regexp P) s : {P s} + { ~P s}. + refine (fix F P (r : regexp P) s : {P s} + { ~P s} := + match r with + | Char ch => string_dec s (String ch "") + | Concat _ _ r1 r2 => Reduce (split (F _ r1) (F _ r2) s) + end); crush; + match goal with + | [ H : _ |- _ ] => generalize (H _ _ (refl_equal _)) + end; + tauto. +Defined. + +Example hi := Concat (Char "h"%char) (Char "i"%char). +Eval simpl in matches hi "hi". +Eval simpl in matches hi "bye".