Mercurial > cpdt > repo
comparison src/MoreDep.v @ 91:4a57a4922af5
Add star to regexp matcher; need to automate a bit more
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 07 Oct 2008 14:52:15 -0400 |
parents | 939add5a7db9 |
children | 41392e5acbf5 |
comparison
equal
deleted
inserted
replaced
90:9b0d118abbc9 | 91:4a57a4922af5 |
---|---|
347 (** * A Certified Regular Expression Matcher *) | 347 (** * A Certified Regular Expression Matcher *) |
348 | 348 |
349 Require Import Ascii String. | 349 Require Import Ascii String. |
350 Open Scope string_scope. | 350 Open Scope string_scope. |
351 | 351 |
352 Section star. | |
353 Variable P : string -> Prop. | |
354 | |
355 Inductive star : string -> Prop := | |
356 | Empty : star "" | |
357 | Iter : forall s1 s2, | |
358 P s1 | |
359 -> star s2 | |
360 -> star (s1 ++ s2). | |
361 End star. | |
362 | |
352 Inductive regexp : (string -> Prop) -> Type := | 363 Inductive regexp : (string -> Prop) -> Type := |
353 | Char : forall ch : ascii, | 364 | Char : forall ch : ascii, |
354 regexp (fun s => s = String ch "") | 365 regexp (fun s => s = String ch "") |
355 | Concat : forall P1 P2 (r1 : regexp P1) (r2 : regexp P2), | 366 | Concat : forall P1 P2 (r1 : regexp P1) (r2 : regexp P2), |
356 regexp (fun s => exists s1, exists s2, s = s1 ++ s2 /\ P1 s1 /\ P2 s2) | 367 regexp (fun s => exists s1, exists s2, s = s1 ++ s2 /\ P1 s1 /\ P2 s2) |
357 | Or : forall P1 P2 (r1 : regexp P1) (r2 : regexp P2), | 368 | Or : forall P1 P2 (r1 : regexp P1) (r2 : regexp P2), |
358 regexp (fun s => P1 s \/ P2 s). | 369 regexp (fun s => P1 s \/ P2 s) |
370 | Star : forall P (r : regexp P), | |
371 regexp (star P). | |
359 | 372 |
360 Open Scope specif_scope. | 373 Open Scope specif_scope. |
361 | 374 |
362 Lemma length_emp : length "" <= 0. | 375 Lemma length_emp : length "" <= 0. |
363 crush. | 376 crush. |
414 Hint Rewrite <- minus_n_O : cpdt. | 427 Hint Rewrite <- minus_n_O : cpdt. |
415 | 428 |
416 induction s1; crush. | 429 induction s1; crush. |
417 Qed. | 430 Qed. |
418 | 431 |
419 Hint Rewrite substring_app_fst substring_app_snd using assumption : cpdt. | 432 Hint Rewrite substring_app_fst substring_app_snd using (trivial; fail) : cpdt. |
420 | 433 |
421 Section split. | 434 Section split. |
422 Variables P1 P2 : string -> Prop. | 435 Variables P1 P2 : string -> Prop. |
423 Variable P1_dec : forall s, {P1 s} + {~P1 s}. | 436 Variable P1_dec : forall s, {P1 s} + { ~P1 s}. |
424 Variable P2_dec : forall s, {P2 s} + {~P2 s}. | 437 Variable P2_dec : forall s, {P2 s} + { ~P2 s}. |
425 | 438 |
426 Variable s : string. | 439 Variable s : string. |
427 | 440 |
428 Definition split' (n : nat) : n <= length s | 441 Definition split' (n : nat) : n <= length s |
429 -> {exists s1, exists s2, length s1 <= n /\ s1 ++ s2 = s /\ P1 s1 /\ P2 s2} | 442 -> {exists s1, exists s2, length s1 <= n /\ s1 ++ s2 = s /\ P1 s1 /\ P2 s2} |
451 Defined. | 464 Defined. |
452 End split. | 465 End split. |
453 | 466 |
454 Implicit Arguments split [P1 P2]. | 467 Implicit Arguments split [P1 P2]. |
455 | 468 |
469 Lemma app_empty_end : forall s, s ++ "" = s. | |
470 induction s; crush. | |
471 Qed. | |
472 | |
473 Hint Rewrite app_empty_end : cpdt. | |
474 | |
475 Lemma substring_self : forall s n, | |
476 n <= 0 | |
477 -> substring n (length s - n) s = s. | |
478 induction s; substring. | |
479 Qed. | |
480 | |
481 Lemma substring_empty : forall s n m, | |
482 m <= 0 | |
483 -> substring n m s = "". | |
484 induction s; substring. | |
485 Qed. | |
486 | |
487 Hint Rewrite substring_self substring_empty using omega : cpdt. | |
488 | |
489 Lemma substring_split' : forall s n m, | |
490 substring n m s ++ substring (n + m) (length s - (n + m)) s | |
491 = substring n (length s - n) s. | |
492 Hint Rewrite substring_split : cpdt. | |
493 | |
494 induction s; substring. | |
495 Qed. | |
496 | |
497 Lemma substring_stack : forall s n2 m1 m2, | |
498 m1 <= m2 | |
499 -> substring 0 m1 (substring n2 m2 s) | |
500 = substring n2 m1 s. | |
501 induction s; substring. | |
502 Qed. | |
503 | |
504 Ltac substring' := | |
505 crush; | |
506 repeat match goal with | |
507 | [ |- context[match ?N with O => _ | S _ => _ end] ] => case_eq N; crush | |
508 end. | |
509 | |
510 Lemma substring_stack' : forall s n1 n2 m1 m2, | |
511 n1 + m1 <= m2 | |
512 -> substring n1 m1 (substring n2 m2 s) | |
513 = substring (n1 + n2) m1 s. | |
514 induction s; substring'; | |
515 match goal with | |
516 | [ |- substring ?N1 _ _ = substring ?N2 _ _ ] => | |
517 replace N1 with N2; crush | |
518 end. | |
519 Qed. | |
520 | |
521 Lemma substring_suffix : forall s n, | |
522 n <= length s | |
523 -> length (substring n (length s - n) s) = length s - n. | |
524 induction s; substring. | |
525 Qed. | |
526 | |
527 Lemma substring_suffix_emp' : forall s n m, | |
528 substring n (S m) s = "" | |
529 -> n >= length s. | |
530 induction s; crush; | |
531 match goal with | |
532 | [ |- ?N >= _ ] => destruct N; crush | |
533 end; | |
534 match goal with | |
535 [ |- S ?N >= S ?E ] => assert (N >= E); [ eauto | omega ] | |
536 end. | |
537 Qed. | |
538 | |
539 Lemma substring_suffix_emp : forall s n m, | |
540 m > 0 | |
541 -> substring n m s = "" | |
542 -> n >= length s. | |
543 destruct m as [| m]; [crush | intros; apply substring_suffix_emp' with m; assumption]. | |
544 Qed. | |
545 | |
546 Hint Rewrite substring_stack substring_stack' substring_suffix | |
547 using omega : cpdt. | |
548 | |
549 Lemma minus_minus : forall n m1 m2, | |
550 m1 + m2 <= n | |
551 -> n - m1 - m2 = n - (m1 + m2). | |
552 intros; omega. | |
553 Qed. | |
554 | |
555 Lemma plus_n_Sm' : forall n m : nat, S (n + m) = m + S n. | |
556 intros; omega. | |
557 Qed. | |
558 | |
559 Hint Rewrite minus_minus using omega : cpdt. | |
560 | |
561 Section dec_star. | |
562 Variable P : string -> Prop. | |
563 Variable P_dec : forall s, {P s} + { ~P s}. | |
564 | |
565 Hint Constructors star. | |
566 | |
567 Lemma star_empty : forall s, | |
568 length s = 0 | |
569 -> star P s. | |
570 destruct s; crush. | |
571 Qed. | |
572 | |
573 Lemma star_singleton : forall s, P s -> star P s. | |
574 intros; rewrite <- (app_empty_end s); auto. | |
575 Qed. | |
576 | |
577 Lemma star_app : forall s n m, | |
578 P (substring n m s) | |
579 -> star P (substring (n + m) (length s - (n + m)) s) | |
580 -> star P (substring n (length s - n) s). | |
581 induction n; substring; | |
582 match goal with | |
583 | [ H : P (substring ?N ?M ?S) |- _ ] => | |
584 solve [ rewrite <- (substring_split S M); auto | |
585 | rewrite <- (substring_split' S N M); auto ] | |
586 end. | |
587 Qed. | |
588 | |
589 Hint Resolve star_empty star_singleton star_app. | |
590 | |
591 Variable s : string. | |
592 | |
593 Lemma star_inv : forall s, | |
594 star P s | |
595 -> s = "" | |
596 \/ exists i, i < length s | |
597 /\ P (substring 0 (S i) s) | |
598 /\ star P (substring (S i) (length s - S i) s). | |
599 Hint Extern 1 (exists i : nat, _) => | |
600 match goal with | |
601 | [ H : P (String _ ?S) |- _ ] => exists (length S); crush | |
602 end. | |
603 | |
604 induction 1; [ | |
605 crush | |
606 | match goal with | |
607 | [ _ : P ?S |- _ ] => destruct S; crush | |
608 end | |
609 ]. | |
610 Qed. | |
611 | |
612 Lemma star_substring_inv : forall n, | |
613 n <= length s | |
614 -> star P (substring n (length s - n) s) | |
615 -> substring n (length s - n) s = "" | |
616 \/ exists l, l < length s - n | |
617 /\ P (substring n (S l) s) | |
618 /\ star P (substring (n + S l) (length s - (n + S l)) s). | |
619 Hint Rewrite plus_n_Sm' : cpdt. | |
620 | |
621 intros; | |
622 match goal with | |
623 | [ H : star _ _ |- _ ] => generalize (star_inv H); do 3 crush; eauto | |
624 end. | |
625 Qed. | |
626 | |
627 Section dec_star''. | |
628 Variable n : nat. | |
629 | |
630 Variable P' : string -> Prop. | |
631 Variable P'_dec : forall n' : nat, n' > n | |
632 -> {P' (substring n' (length s - n') s)} | |
633 + { ~P' (substring n' (length s - n') s)}. | |
634 | |
635 Definition dec_star'' (l : nat) | |
636 : {exists l', S l' <= l | |
637 /\ P (substring n (S l') s) /\ P' (substring (n + S l') (length s - (n + S l')) s)} | |
638 + {forall l', S l' <= l | |
639 -> ~P (substring n (S l') s) \/ ~P' (substring (n + S l') (length s - (n + S l')) s)}. | |
640 refine (fix F (l : nat) : {exists l', S l' <= l | |
641 /\ P (substring n (S l') s) /\ P' (substring (n + S l') (length s - (n + S l')) s)} | |
642 + {forall l', S l' <= l | |
643 -> ~P (substring n (S l') s) \/ ~P' (substring (n + S l') (length s - (n + S l')) s)} := | |
644 match l return {exists l', S l' <= l | |
645 /\ P (substring n (S l') s) /\ P' (substring (n + S l') (length s - (n + S l')) s)} | |
646 + {forall l', S l' <= l -> | |
647 ~P (substring n (S l') s) \/ ~P' (substring (n + S l') (length s - (n + S l')) s)} with | |
648 | O => _ | |
649 | S l' => | |
650 (P_dec (substring n (S l') s) && P'_dec (n' := n + S l') _) | |
651 || F l' | |
652 end); clear F; crush; eauto 7; | |
653 match goal with | |
654 | [ H : ?X <= S ?Y |- _ ] => destruct (eq_nat_dec X (S Y)); crush | |
655 end. | |
656 Defined. | |
657 End dec_star''. | |
658 | |
659 Definition dec_star' (n n' : nat) : length s - n' <= n | |
660 -> {star P (substring n' (length s - n') s)} | |
661 + {~star P (substring n' (length s - n') s)}. | |
662 About dec_star''. | |
663 | |
664 refine (fix F (n n' : nat) {struct n} : length s - n' <= n | |
665 -> {star P (substring n' (length s - n') s)} | |
666 + {~star P (substring n' (length s - n') s)} := | |
667 match n return length s - n' <= n | |
668 -> {star P (substring n' (length s - n') s)} | |
669 + {~star P (substring n' (length s - n') s)} with | |
670 | O => fun _ => Yes | |
671 | S n'' => fun _ => | |
672 le_gt_dec (length s) n' | |
673 || dec_star'' (n := n') (star P) (fun n0 _ => Reduce (F n'' n0 _)) (length s - n') | |
674 end); clear F; crush; eauto. | |
675 | |
676 apply star_substring_inv in H; crush; eauto. | |
677 | |
678 assert (n' >= length s); [ | omega]. | |
679 apply substring_suffix_emp with (length s - n'); crush. | |
680 | |
681 assert (S x <= length s - n'); [ omega | ]. | |
682 apply _1 in H1. | |
683 tauto. | |
684 Defined. | |
685 | |
686 Definition dec_star : {star P s} + { ~star P s}. | |
687 refine (match s with | |
688 | "" => Reduce (dec_star' (n := length s) 0 _) | |
689 | _ => Reduce (dec_star' (n := length s) 0 _) | |
690 end); crush. | |
691 Defined. | |
692 End dec_star. | |
693 | |
456 Lemma app_cong : forall x1 y1 x2 y2, | 694 Lemma app_cong : forall x1 y1 x2 y2, |
457 x1 = x2 | 695 x1 = x2 |
458 -> y1 = y2 | 696 -> y1 = y2 |
459 -> x1 ++ y1 = x2 ++ y2. | 697 -> x1 ++ y1 = x2 ++ y2. |
460 congruence. | 698 congruence. |
461 Qed. | 699 Qed. |
462 | 700 |
463 Hint Resolve app_cong. | 701 Hint Resolve app_cong. |
702 | |
703 | |
464 | 704 |
465 Definition matches P (r : regexp P) s : {P s} + { ~P s}. | 705 Definition matches P (r : regexp P) s : {P s} + { ~P s}. |
466 refine (fix F P (r : regexp P) s : {P s} + { ~P s} := | 706 refine (fix F P (r : regexp P) s : {P s} + { ~P s} := |
467 match r with | 707 match r with |
468 | Char ch => string_dec s (String ch "") | 708 | Char ch => string_dec s (String ch "") |
469 | Concat _ _ r1 r2 => Reduce (split (F _ r1) (F _ r2) s) | 709 | Concat _ _ r1 r2 => Reduce (split (F _ r1) (F _ r2) s) |
470 | Or _ _ r1 r2 => F _ r1 s || F _ r2 s | 710 | Or _ _ r1 r2 => F _ r1 s || F _ r2 s |
711 | Star _ r => dec_star _ _ _ | |
471 end); crush; | 712 end); crush; |
472 match goal with | 713 match goal with |
473 | [ H : _ |- _ ] => generalize (H _ _ (refl_equal _)) | 714 | [ H : _ |- _ ] => generalize (H _ _ (refl_equal _)) |
474 end; | 715 end; |
475 tauto. | 716 tauto. |
482 Example a_b := Or (Char "a"%char) (Char "b"%char). | 723 Example a_b := Or (Char "a"%char) (Char "b"%char). |
483 Eval simpl in matches a_b "". | 724 Eval simpl in matches a_b "". |
484 Eval simpl in matches a_b "a". | 725 Eval simpl in matches a_b "a". |
485 Eval simpl in matches a_b "aa". | 726 Eval simpl in matches a_b "aa". |
486 Eval simpl in matches a_b "b". | 727 Eval simpl in matches a_b "b". |
728 | |
729 Example a_star := Star (Char "a"%char). | |
730 Eval simpl in matches a_star "". | |
731 Eval simpl in matches a_star "a". | |
732 Eval simpl in matches a_star "b". | |
733 Eval simpl in matches a_star "aa". |