513 |
513 |
514 @{ML OuterParse.position} |
514 @{ML OuterParse.position} |
515 |
515 |
516 *} |
516 *} |
517 |
517 |
518 ML{* |
|
519 OuterParse.position |
|
520 *} |
|
521 |
|
522 |
|
523 section {* Parsing Inner Syntax *} |
518 section {* Parsing Inner Syntax *} |
524 |
519 |
525 ML{* |
520 ML{*let |
526 let |
|
527 val input = OuterSyntax.scan Position.none "0" |
521 val input = OuterSyntax.scan Position.none "0" |
528 in |
522 in |
529 OuterParse.prop input |
523 OuterParse.prop input |
530 end |
524 end*} |
531 |
|
532 *} |
|
533 |
|
534 ML{* |
|
535 OuterParse.opt_target |
|
536 *} |
|
537 |
525 |
538 text {* (FIXME funny output for a proposition) *} |
526 text {* (FIXME funny output for a proposition) *} |
539 |
527 |
540 ML{* |
528 section {* Parsing Specifications *} |
541 OuterParse.opt_target -- |
529 |
542 OuterParse.fixes -- |
530 text {* |
543 OuterParse.for_fixes -- |
531 There are a number of special purpose parsers that help for parsing specifications. |
544 Scan.optional (OuterParse.$$$ "where" |-- |
532 For example the function @{ML OuterParse.target} reads a target in order to indicate |
545 OuterParse.!!! (OuterParse.enum1 "|" (SpecParse.opt_thm_name ":" -- OuterParse.prop))) [] |
533 a locale. |
546 |
534 |
547 *} |
535 @{ML_response [display,gray] |
548 |
536 "let |
549 ML{* OuterSyntax.command *} |
537 val input = filtered_input \"(in test)\" |
|
538 in |
|
539 parse OuterParse.target input |
|
540 end" "(\"test\",[])"} |
|
541 |
|
542 The function @{ML OuterParse.opt_target} makes this parser ``optional''. |
|
543 |
|
544 The function @{ML OuterParse.fixes} reads a list of constants |
|
545 which can include a type annotation and a syntax translation. |
|
546 The list needs to be separated by \isacommand{and}. |
|
547 |
|
548 *} |
|
549 |
|
550 text {* |
|
551 |
|
552 @{ML_response [display,gray] |
|
553 "let |
|
554 val input = filtered_input |
|
555 \"foo::\\\"int \<Rightarrow> bool\\\" (\\\"FOO\\\" [100] 100) and bar::nat and blonk\" |
|
556 in |
|
557 parse OuterParse.fixes input |
|
558 end" |
|
559 "([(foo, SOME \<dots>, Mixfix (\"FOO\",[100],100)), |
|
560 (bar, SOME \<dots>, NoSyn), |
|
561 (blonk, NONE, NoSyn)],[])"} |
|
562 |
|
563 The types of the constants is stored in the @{ML SOME}s. |
|
564 We need to write @{text "\\\"int \<Rightarrow> bool\\\""} to properly |
|
565 escape the type. |
|
566 |
|
567 @{ML OuterParse.for_fixes} is an ``optional'' that prefixes |
|
568 @{ML OuterParse.fixes} with the comman \isacommand{for}. |
|
569 *} |
|
570 |
|
571 ML{*let |
|
572 val input = filtered_input "test_lemma[intro,foo,elim,dest!,bar]:" |
|
573 in |
|
574 parse (SpecParse.thm_name ":") input |
|
575 |> fst |> snd |> (Attrib.pretty_attribs @{context}) |> (map Pretty.string_of) |
|
576 end*} |
|
577 |
|
578 text {* |
|
579 (FIXME: why is intro, elim and dest treated differently from bar?) |
|
580 *} |
|
581 |
|
582 text {* |
|
583 @{ML_response [display,gray] |
|
584 "let |
|
585 val input = filtered_input |
|
586 (\"even and odd \" ^ |
|
587 \"where \" ^ |
|
588 \" even0[intro]: \\\"even 0\\\" \" ^ |
|
589 \"| evenS[intro]: \\\"odd n \<Longrightarrow> even (Suc n)\\\" \" ^ |
|
590 \"| oddS[intro]: \\\"even n \<Longrightarrow> odd (Suc n)\\\"\") |
|
591 |
|
592 val parser = |
|
593 OuterParse.opt_target -- |
|
594 OuterParse.fixes -- |
|
595 OuterParse.for_fixes -- |
|
596 Scan.optional |
|
597 (OuterParse.$$$ \"where\" |-- |
|
598 OuterParse.!!! |
|
599 (OuterParse.enum1 \"|\" |
|
600 (SpecParse.opt_thm_name \":\" -- OuterParse.prop))) [] |
|
601 in |
|
602 parse parser input |
|
603 end" |
|
604 "((((NONE, [(even, NONE, NoSyn), (odd, NONE, NoSyn)]), []), |
|
605 [((even0,\<dots>), \"\\^E\\^Ftoken\\^Eeven 0\\^E\\^F\\^E\"), |
|
606 ((evenS,\<dots>), \"\\^E\\^Ftoken\\^Eodd n \<Longrightarrow> even (Suc n)\\^E\\^F\\^E\"), |
|
607 ((oddS,\<dots>), \"\\^E\\^Ftoken\\^Eeven n \<Longrightarrow> odd (Suc n)\\^E\\^F\\^E\")]), [])"} |
|
608 *} |
|
609 |
|
610 text {* |
|
611 The (outer?) parser for the package: returns optionally a locale; |
|
612 a list of predicate constants with optional type-annotation and |
|
613 optional syntax-annotation; a list of for-fixes (fixed parameters); |
|
614 and a list of rules where each rule has optionally a name and an attribute. |
|
615 *} |
550 |
616 |
551 section {* New Commands and Keyword Files *} |
617 section {* New Commands and Keyword Files *} |
552 |
618 |
553 text {* |
619 text {* |
554 Often new commands, for example for providing new definitional principles, |
620 Often new commands, for example for providing new definitional principles, |
573 The crucial function @{ML OuterSyntax.command} expects a name for the command, a |
639 The crucial function @{ML OuterSyntax.command} expects a name for the command, a |
574 short description, a kind indicator (which we will explain later on more thoroughly) and a |
640 short description, a kind indicator (which we will explain later on more thoroughly) and a |
575 parser producing a top-level transition function (its purpose will also explained |
641 parser producing a top-level transition function (its purpose will also explained |
576 later). |
642 later). |
577 |
643 |
578 While this is everything we have to do on the ML-level, we need a keyword |
644 While this is everything you have to do on the ML-level, you need a keyword |
579 file that can be loaded by ProofGeneral. This is to enable ProofGeneral to |
645 file that can be loaded by ProofGeneral. This is to enable ProofGeneral to |
580 recognise \isacommand{foobar} as a command. Such a keyword file can be |
646 recognise \isacommand{foobar} as a command. Such a keyword file can be |
581 generated with the command-line: |
647 generated with the command-line: |
582 |
648 |
583 @{text [display] "$ isabelle keywords -k foobar some_log_files"} |
649 @{text [display] "$ isabelle keywords -k foobar some_log_files"} |
584 |
650 |
585 The option @{text "-k foobar"} indicates which postfix the name of the keyword file |
651 The option @{text "-k foobar"} indicates which postfix the name of the keyword file |
586 will be assigned. In the case above the file will be named @{text |
652 will be assigned. In the case above the file will be named @{text |
587 "isar-keywords-foobar.el"}. This command requires log files to be |
653 "isar-keywords-foobar.el"}. This command requires log files to be |
588 present (in order to extract the keywords from them). To generate these log |
654 present (in order to extract the keywords from them). To generate these log |
589 files, we first package the code above into a separate theory file named |
655 files, you first need to package the code above into a separate theory file named |
590 @{text "Command.thy"}, say---see Figure~\ref{fig:commandtheory} for the |
656 @{text "Command.thy"}, say---see Figure~\ref{fig:commandtheory} for the |
591 complete code. |
657 complete code. |
592 |
658 |
593 |
659 |
594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
645 ./FoobarCommand/ROOT.ML |
711 ./FoobarCommand/ROOT.ML |
646 ./FoobarCommand/document |
712 ./FoobarCommand/document |
647 ./FoobarCommand/document/root.tex"} |
713 ./FoobarCommand/document/root.tex"} |
648 |
714 |
649 |
715 |
650 We need to copy the file @{text "Command.thy"} into the directory @{text "FoobarCommand"} |
716 You need to copy the file @{text "Command.thy"} into the directory @{text "FoobarCommand"} |
651 and add the line |
717 and add the line |
652 |
718 |
653 @{text [display] "use_thy \"Command\";"} |
719 @{text [display] "use_thy \"Command\";"} |
654 |
720 |
655 to the file @{text "./FoobarCommand/ROOT.ML"}. We can now compile the theory by just typing |
721 to the file @{text "./FoobarCommand/ROOT.ML"}. You can now compile the theory by just typing |
656 |
722 |
657 @{text [display] "$ isabelle make"} |
723 @{text [display] "$ isabelle make"} |
658 |
724 |
659 We created finally all the necessary log files. They are stored |
725 If the compilation succeeds, you have finally created all the necessary log files. |
660 in the directory |
726 They are stored in the directory |
661 |
727 |
662 @{text [display] "~/.isabelle/heaps/Isabelle2008/polyml-5.2.1_x86-linux/log"} |
728 @{text [display] "~/.isabelle/heaps/Isabelle2008/polyml-5.2.1_x86-linux/log"} |
663 |
729 |
664 or something similar depending on your Isabelle distribution and architecture. |
730 or something similar depending on your Isabelle distribution and architecture. |
665 One quick way to assign a shell variable to this directory is by typing |
731 One quick way to assign a shell variable to this directory is by typing |
685 The result is the file @{text "isar-keywords-foobar.el"}. It should contain |
751 The result is the file @{text "isar-keywords-foobar.el"}. It should contain |
686 the string @{text "foobar"} twice.\footnote{To see whether things are fine, check |
752 the string @{text "foobar"} twice.\footnote{To see whether things are fine, check |
687 that @{text "grep foobar"} on this file returns something |
753 that @{text "grep foobar"} on this file returns something |
688 non-empty.} This keyword file needs to |
754 non-empty.} This keyword file needs to |
689 be copied into the directory @{text "~/.isabelle/etc"}. To make Isabelle |
755 be copied into the directory @{text "~/.isabelle/etc"}. To make Isabelle |
690 aware of this keyword file, we have to start Isabelle with the option @{text |
756 aware of this keyword file, you have to start Isabelle with the option @{text |
691 "-k foobar"}, i.e. |
757 "-k foobar"}, i.e. |
692 |
758 |
693 |
759 |
694 @{text [display] "$ isabelle -k foobar a_theory_file"} |
760 @{text [display] "$ isabelle -k foobar a_theory_file"} |
695 |
761 |
696 If we now build a theory on top of @{text "Command.thy"}, |
762 If you now build a theory on top of @{text "Command.thy"}, |
697 then we can make use of the command \isacommand{foobar}. |
763 then the command \isacommand{foobar} can be used. |
698 Similarly with any other new command. |
764 Similarly with any other new command. |
699 |
765 |
700 |
766 |
701 At the moment \isacommand{foobar} is not very useful. Let us refine it a bit |
767 At the moment \isacommand{foobar} is not very useful. Let us refine it a bit |
702 next by taking a proposition as argument and printing this proposition inside |
768 next by taking a proposition as argument and printing this proposition inside |