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".