equal
deleted
inserted
replaced
200 Let us now return to our example of parsing @{ML "(p -- q) || r" for p q r}. If we want |
200 Let us now return to our example of parsing @{ML "(p -- q) || r" for p q r}. If we want |
201 to generate the correct error message for p-followed-by-q, then |
201 to generate the correct error message for p-followed-by-q, then |
202 we have to write: |
202 we have to write: |
203 *} |
203 *} |
204 |
204 |
205 ML {* |
205 ML{*fun p_followed_by_q p q r = |
206 fun p_followed_by_q p q r = |
|
207 let |
206 let |
208 val err_msg = (fn _ => p ^ " is not followed by " ^ q) |
207 val err_msg = (fn _ => p ^ " is not followed by " ^ q) |
209 in |
208 in |
210 ($$ p -- (!! err_msg ($$ q))) || ($$ r -- $$ r) |
209 ($$ p -- (!! err_msg ($$ q))) || ($$ r -- $$ r) |
211 end |
210 end *} |
212 *} |
|
213 |
211 |
214 |
212 |
215 text {* |
213 text {* |
216 Running this parser with the @{text [quotes] "h"} and @{text [quotes] "e"}, and |
214 Running this parser with the @{text [quotes] "h"} and @{text [quotes] "e"}, and |
217 the input @{text [quotes] "holle"} |
215 the input @{text [quotes] "holle"} |
393 |
391 |
394 For convenience we define the function |
392 For convenience we define the function |
395 |
393 |
396 *} |
394 *} |
397 |
395 |
398 ML {* |
396 ML{*fun filtered_input str = |
399 fun filtered_input str = |
397 filter OuterLex.is_proper (OuterSyntax.scan Position.none str) *} |
400 filter OuterLex.is_proper (OuterSyntax.scan Position.none str) |
|
401 *} |
|
402 |
398 |
403 text {* |
399 text {* |
404 |
400 |
405 If we parse |
401 If we parse |
406 |
402 |
475 |
471 |
476 The following function will help us later to run examples |
472 The following function will help us later to run examples |
477 |
473 |
478 *} |
474 *} |
479 |
475 |
480 ML {* |
476 ML{*fun parse p input = Scan.finite OuterLex.stopper (Scan.error p) input *} |
481 fun parse p input = Scan.finite OuterLex.stopper (Scan.error p) input |
|
482 *} |
|
483 |
477 |
484 text {* |
478 text {* |
485 |
479 |
486 The function @{ML "OuterParse.!!!"} can be used to force termination of the |
480 The function @{ML "OuterParse.!!!"} can be used to force termination of the |
487 parser in case of a dead end, just like @{ML "Scan.!!"} (see previous section), |
481 parser in case of a dead end, just like @{ML "Scan.!!"} (see previous section), |
518 |
512 |
519 @{ML OuterParse.position} |
513 @{ML OuterParse.position} |
520 |
514 |
521 *} |
515 *} |
522 |
516 |
523 ML {* |
517 ML{* |
524 OuterParse.position |
518 OuterParse.position |
525 *} |
519 *} |
526 |
520 |
527 |
521 |
528 section {* Parsing Inner Syntax *} |
522 section {* Parsing Inner Syntax *} |
529 |
523 |
530 ML {* |
524 ML{* |
531 let |
525 let |
532 val input = OuterSyntax.scan Position.none "0" |
526 val input = OuterSyntax.scan Position.none "0" |
533 in |
527 in |
534 OuterParse.prop input |
528 OuterParse.prop input |
535 end |
529 end |
536 |
530 |
537 *} |
531 *} |
538 |
532 |
539 ML {* |
533 ML{* |
540 OuterParse.opt_target |
534 OuterParse.opt_target |
541 *} |
535 *} |
542 |
536 |
543 text {* (FIXME funny output for a proposition) *} |
537 text {* (FIXME funny output for a proposition) *} |
544 |
538 |
545 ML {* |
539 ML{* |
546 OuterParse.opt_target -- |
540 OuterParse.opt_target -- |
547 OuterParse.fixes -- |
541 OuterParse.fixes -- |
548 OuterParse.for_fixes -- |
542 OuterParse.for_fixes -- |
549 Scan.optional (OuterParse.$$$ "where" |-- |
543 Scan.optional (OuterParse.$$$ "where" |-- |
550 OuterParse.!!! (OuterParse.enum1 "|" (SpecParse.opt_thm_name ":" -- OuterParse.prop))) [] |
544 OuterParse.!!! (OuterParse.enum1 "|" (SpecParse.opt_thm_name ":" -- OuterParse.prop))) [] |
551 |
545 |
552 *} |
546 *} |
553 |
547 |
554 ML {* OuterSyntax.command *} |
548 ML{* OuterSyntax.command *} |
555 |
549 |
556 section {* New Commands and Creating Keyword Files *} |
550 section {* New Commands and Creating Keyword Files *} |
557 |
551 |
558 text {* |
552 text {* |
559 Often new commands, for example for providing new definitional principles, |
553 Often new commands, for example for providing new definitional principles, |
564 |
558 |
565 Let us start with a ``silly'' command, which we call \isacommand{foobar} in what follows. |
559 Let us start with a ``silly'' command, which we call \isacommand{foobar} in what follows. |
566 To keep things simple this command does nothing at all. On the ML-level it can be defined as |
560 To keep things simple this command does nothing at all. On the ML-level it can be defined as |
567 *} |
561 *} |
568 |
562 |
569 ML {* |
563 ML{*let |
570 let |
|
571 val do_nothing = Scan.succeed (Toplevel.theory I) |
564 val do_nothing = Scan.succeed (Toplevel.theory I) |
572 val kind = OuterKeyword.thy_decl |
565 val kind = OuterKeyword.thy_decl |
573 in |
566 in |
574 OuterSyntax.command "foobar" "description of foobar" kind do_nothing |
567 OuterSyntax.command "foobar" "description of foobar" kind do_nothing |
575 end |
568 end *} |
576 *} |
|
577 |
569 |
578 text {* |
570 text {* |
579 The function @{ML OuterSyntax.command} expects a name for the command, a |
571 The function @{ML OuterSyntax.command} expects a name for the command, a |
580 short description, a kind indicator (which we will explain later on more thoroughly) and a |
572 short description, a kind indicator (which we will explain later on more thoroughly) and a |
581 parser for a top-level transition function (its purpose will also explained |
573 parser for a top-level transition function (its purpose will also explained |
598 complete code. |
590 complete code. |
599 |
591 |
600 |
592 |
601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
602 \begin{figure}[t] |
594 \begin{figure}[t] |
603 \begin{boxedminipage}{\textwidth}\small |
595 \begin{graybox}\small |
604 \isacommand{theory}~@{text Command}\\ |
596 \isacommand{theory}~@{text Command}\\ |
605 \isacommand{imports}~@{text Main}\\ |
597 \isacommand{imports}~@{text Main}\\ |
606 \isacommand{begin}\\ |
598 \isacommand{begin}\\ |
607 \isacommand{ML}~\isa{\isacharverbatimopen}\\ |
599 \isacommand{ML}~\isa{\isacharverbatimopen}\\ |
608 @{ML |
600 @{ML |
612 in |
604 in |
613 OuterSyntax.command \"foobar\" \"description of foobar\" kind do_nothing |
605 OuterSyntax.command \"foobar\" \"description of foobar\" kind do_nothing |
614 end"}\\ |
606 end"}\\ |
615 \isa{\isacharverbatimclose}\\ |
607 \isa{\isacharverbatimclose}\\ |
616 \isacommand{end} |
608 \isacommand{end} |
617 \end{boxedminipage} |
609 \end{graybox} |
618 \caption{The file @{text "Command.thy"} is necessary for generating a log |
610 \caption{The file @{text "Command.thy"} is necessary for generating a log |
619 file. This log file enables Isabelle to generate a keyword file containing |
611 file. This log file enables Isabelle to generate a keyword file containing |
620 the command \isacommand{foobar}.\label{fig:commandtheory}} |
612 the command \isacommand{foobar}.\label{fig:commandtheory}} |
621 \end{figure} |
613 \end{figure} |
622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
614 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
696 @{text [display] "$ isabelle -k foobar a-theory-file"} |
688 @{text [display] "$ isabelle -k foobar a-theory-file"} |
697 |
689 |
698 If we now run the original code |
690 If we now run the original code |
699 *} |
691 *} |
700 |
692 |
701 ML {* |
693 ML{*let |
702 let |
|
703 val do_nothing = Scan.succeed (Toplevel.theory I) |
694 val do_nothing = Scan.succeed (Toplevel.theory I) |
704 val kind = OuterKeyword.thy_decl |
695 val kind = OuterKeyword.thy_decl |
705 in |
696 in |
706 OuterSyntax.command "foobar" "description of foobar" kind do_nothing |
697 OuterSyntax.command "foobar" "description of foobar" kind do_nothing |
707 end |
698 end *} |
708 *} |
|
709 |
699 |
710 text {* |
700 text {* |
711 then we can make use of \isacommand{foobar}! Similarly with any other new command. |
701 then we can make use of \isacommand{foobar}! Similarly with any other new command. |
712 |
702 |
713 In the example above, we built the theories on top of the HOL-logic. If you |
703 In the example above, we built the theories on top of the HOL-logic. If you |
725 @{ML "Toplevel.theory I"}. We can replace this code by a function that first |
715 @{ML "Toplevel.theory I"}. We can replace this code by a function that first |
726 parses a proposition (using the parser @{ML OuterParse.prop}), then prints out |
716 parses a proposition (using the parser @{ML OuterParse.prop}), then prints out |
727 the tracing information and finally does nothing. For this we can write |
717 the tracing information and finally does nothing. For this we can write |
728 *} |
718 *} |
729 |
719 |
730 ML {* |
720 ML{*let |
731 let |
|
732 val trace_prop = |
721 val trace_prop = |
733 OuterParse.prop >> (fn str => (tracing str; (Toplevel.theory I))) |
722 OuterParse.prop >> (fn str => (tracing str; (Toplevel.theory I))) |
734 val kind = OuterKeyword.thy_decl |
723 val kind = OuterKeyword.thy_decl |
735 in |
724 in |
736 OuterSyntax.command "foobar" "traces a proposition" kind trace_prop |
725 OuterSyntax.command "foobar" "traces a proposition" kind trace_prop |
737 end |
726 end *} |
738 *} |
|
739 |
727 |
740 text {* |
728 text {* |
741 Now we can type for example |
729 Now we can type for example |
742 |
730 |
743 @{ML_response_fake_both [display] "foobar \"True \<and> False\"" "True \<and> False"} |
731 @{ML_response_fake_both [display] "foobar \"True \<and> False\"" "True \<and> False"} |
757 Below we change \isacommand{foobar} is such a way that an proposition as |
745 Below we change \isacommand{foobar} is such a way that an proposition as |
758 argument and then start a proof in order to prove it. Therefore in Line 13 |
746 argument and then start a proof in order to prove it. Therefore in Line 13 |
759 below, we set the kind indicator to @{ML thy_goal in OuterKeyword}. |
747 below, we set the kind indicator to @{ML thy_goal in OuterKeyword}. |
760 *} |
748 *} |
761 |
749 |
762 ML %linenumbers {*let |
750 ML%linenumbers{*let |
763 fun set_up_thm str ctxt = |
751 fun set_up_thm str ctxt = |
764 let |
752 let |
765 val prop = Syntax.read_prop ctxt str |
753 val prop = Syntax.read_prop ctxt str |
766 in |
754 in |
767 Proof.theorem_i NONE (K I) [[(Syntax.read_prop ctxt str,[])]] ctxt |
755 Proof.theorem_i NONE (K I) [[(Syntax.read_prop ctxt str,[])]] ctxt |
772 Toplevel.local_theory_to_proof NONE (set_up_thm str)) |
760 Toplevel.local_theory_to_proof NONE (set_up_thm str)) |
773 |
761 |
774 val kind = OuterKeyword.thy_goal |
762 val kind = OuterKeyword.thy_goal |
775 in |
763 in |
776 OuterSyntax.command "foobar" "proving a proposition" kind prove_prop |
764 OuterSyntax.command "foobar" "proving a proposition" kind prove_prop |
777 end |
765 end *} |
778 *} |
|
779 |
766 |
780 text {* |
767 text {* |
781 The function @{text set_up_thm} takes a string (the proposition) and a context. |
768 The function @{text set_up_thm} takes a string (the proposition) and a context. |
782 The context is necessary in order to convert the string into a proper proposition |
769 The context is necessary in order to convert the string into a proper proposition |
783 using the function @{ML Syntax.read_prop}. In Line 6 we use the function |
770 using the function @{ML Syntax.read_prop}. In Line 6 we use the function |
1032 *} |
1019 *} |
1033 |
1020 |
1034 |
1021 |
1035 |
1022 |
1036 |
1023 |
1037 ML {* |
1024 ML{* |
1038 val toks = OuterSyntax.scan Position.none |
1025 val toks = OuterSyntax.scan Position.none |
1039 "theory,imports;begin x.y.z apply ?v1 ?'a 'a -- || 44 simp (* xx *) { * fff * }" ; |
1026 "theory,imports;begin x.y.z apply ?v1 ?'a 'a -- || 44 simp (* xx *) { * fff * }" ; |
1040 *} |
1027 *} |
1041 |
1028 |
1042 ML {* |
1029 ML{* |
1043 print_depth 20 ; |
1030 print_depth 20 ; |
1044 *} |
1031 *} |
1045 |
1032 |
1046 ML {* |
1033 ML{* |
1047 map OuterLex.text_of toks ; |
1034 map OuterLex.text_of toks ; |
1048 *} |
1035 *} |
1049 |
1036 |
1050 ML {* |
1037 ML{* |
1051 val proper_toks = filter OuterLex.is_proper toks ; |
1038 val proper_toks = filter OuterLex.is_proper toks ; |
1052 *} |
1039 *} |
1053 |
1040 |
1054 ML {* |
1041 ML{* |
1055 map OuterLex.kind_of proper_toks |
1042 map OuterLex.kind_of proper_toks |
1056 *} |
1043 *} |
1057 |
1044 |
1058 ML {* |
1045 ML{* |
1059 map OuterLex.unparse proper_toks ; |
1046 map OuterLex.unparse proper_toks ; |
1060 *} |
1047 *} |
1061 |
1048 |
1062 ML {* |
1049 ML{* |
1063 OuterLex.stopper |
1050 OuterLex.stopper |
1064 *} |
1051 *} |
1065 |
1052 |
1066 text {* |
1053 text {* |
1067 |
1054 |