525 Token ((\"bar\", ({line=8, end_line=8}, {line=8})), (Ident, \"bar\"), \<dots>)]"} |
525 Token ((\"bar\", ({line=8, end_line=8}, {line=8})), (Ident, \"bar\"), \<dots>)]"} |
526 |
526 |
527 in which the @{text [quotes] "\\n"} causes the second token to be in |
527 in which the @{text [quotes] "\\n"} causes the second token to be in |
528 line 8. |
528 line 8. |
529 |
529 |
530 Now by using the parser @{ML OuterParse.position} you can decode the positional |
530 By using the parser @{ML OuterParse.position} you can decode the positional |
531 information and return it as part of the parsed input. For example |
531 information and return it as part of the parsed input. For example |
532 |
532 |
533 @{ML_response_fake [display,gray] |
533 @{ML_response_fake [display,gray] |
534 "let |
534 "let |
535 val input = (filtered_input' \"where\") |
535 val input = (filtered_input' \"where\") |
561 "(\"\\^E\\^Ftoken\\^Efoo\\^E\\^F\\^E\", [])"} |
561 "(\"\\^E\\^Ftoken\\^Efoo\\^E\\^F\\^E\", [])"} |
562 |
562 |
563 The function @{ML OuterParse.prop} is similar, except that it gives a different |
563 The function @{ML OuterParse.prop} is similar, except that it gives a different |
564 error message, when parsing fails. Looking closer at the result string you will |
564 error message, when parsing fails. Looking closer at the result string you will |
565 have noticed that the parser not just returns the parsed string, but also some |
565 have noticed that the parser not just returns the parsed string, but also some |
566 encoded positional information. You can see this better if you replace |
566 encoded information. You can see this better if you replace |
567 @{ML Position.none} by @{ML "(Position.line 42)"}, say. |
567 @{ML Position.none} by @{ML "(Position.line 42)"}, say. |
568 |
568 |
569 @{ML_response [display,gray] |
569 @{ML_response [display,gray] |
570 "let |
570 "let |
571 val input = OuterSyntax.scan (Position.line 42) \"foo\" |
571 val input = OuterSyntax.scan (Position.line 42) \"foo\" |
572 in |
572 in |
573 OuterParse.term input |
573 OuterParse.term input |
574 end" |
574 end" |
575 "(\"\\^E\\^Ftoken\\^Fline=42\\^Fend_line=42\\^Efoo\\^E\\^F\\^E\", [])"} |
575 "(\"\\^E\\^Ftoken\\^Fline=42\\^Fend_line=42\\^Efoo\\^E\\^F\\^E\", [])"} |
576 |
576 |
577 The positional information is stored so that code called later will be |
577 The positional information is stored so that code called later on will be |
578 able to give more precise error messages. |
578 able to give more precise error messages. |
579 |
579 |
580 *} |
580 *} |
581 |
581 |
582 section {* Parsing Specifications\label{sec:parsingspecs} *} |
582 section {* Parsing Specifications\label{sec:parsingspecs} *} |
604 text {* |
604 text {* |
605 For this we are going to use the parser: |
605 For this we are going to use the parser: |
606 *} |
606 *} |
607 |
607 |
608 ML %linenosgray{*val spec_parser = |
608 ML %linenosgray{*val spec_parser = |
609 OuterParse.opt_target -- |
609 OuterParse.opt_target -- |
610 OuterParse.fixes -- |
610 OuterParse.fixes -- |
611 OuterParse.for_fixes -- |
611 OuterParse.for_fixes -- |
612 Scan.optional |
612 Scan.optional |
613 (OuterParse.$$$ "where" |-- |
613 (OuterParse.$$$ "where" |-- |
614 OuterParse.!!! |
614 OuterParse.!!! |
615 (OuterParse.enum1 "|" |
615 (OuterParse.enum1 "|" |
616 (SpecParse.opt_thm_name ":" -- OuterParse.prop))) []*} |
616 (SpecParse.opt_thm_name ":" -- OuterParse.prop))) []*} |
617 |
617 |
618 text {* |
618 text {* |
619 Note that the parser does not parse the ketword \simpleinductive. This |
619 Note that the parser does not parse the keyword \simpleinductive, even if it is |
620 will be done by the infrastructure that will eventually call this parser. |
620 meant to process definitions as shown above. The parser of the keyword |
|
621 will be given by the infrastructure that will eventually calls @{ML spec_parser}. |
|
622 |
|
623 |
621 To see what the parser returns, let us parse the string corresponding to the |
624 To see what the parser returns, let us parse the string corresponding to the |
622 definition of @{term even} and @{term odd}: |
625 definition of @{term even} and @{term odd}: |
623 |
626 |
624 @{ML_response [display,gray] |
627 @{ML_response [display,gray] |
625 "let |
628 "let |
636 [((even0,\<dots>), \"\\^E\\^Ftoken\\^Eeven 0\\^E\\^F\\^E\"), |
639 [((even0,\<dots>), \"\\^E\\^Ftoken\\^Eeven 0\\^E\\^F\\^E\"), |
637 ((evenS,\<dots>), \"\\^E\\^Ftoken\\^Eodd n \<Longrightarrow> even (Suc n)\\^E\\^F\\^E\"), |
640 ((evenS,\<dots>), \"\\^E\\^Ftoken\\^Eodd n \<Longrightarrow> even (Suc n)\\^E\\^F\\^E\"), |
638 ((oddS,\<dots>), \"\\^E\\^Ftoken\\^Eeven n \<Longrightarrow> odd (Suc n)\\^E\\^F\\^E\")]), [])"} |
641 ((oddS,\<dots>), \"\\^E\\^Ftoken\\^Eeven n \<Longrightarrow> odd (Suc n)\\^E\\^F\\^E\")]), [])"} |
639 |
642 |
640 As can be seen, the result is a ``nested'' four-tuple consisting of an |
643 As can be seen, the result is a ``nested'' four-tuple consisting of an |
641 optional locale; a list of variables with optional type-annotation and |
644 optional locale (in this case @{ML NONE}); a list of variables with optional |
642 syntax-annotation; a list of for-fixes (fixed variables); and a list of rules |
645 type-annotation and syntax-annotation; a list of for-fixes (fixed variables; in this |
643 where each rule has optionally a name and an attribute. |
646 case there are none); and a list of rules where every rule has optionally a name and |
|
647 an attribute. |
644 |
648 |
645 In Line 2 of the parser, the function @{ML OuterParse.opt_target} reads a target |
649 In Line 2 of the parser, the function @{ML OuterParse.opt_target} reads a target |
646 in order to indicate a locale in which the specification is made. For example |
650 in order to indicate a locale in which the specification is made. For example |
647 |
651 |
648 @{ML_response [display,gray] |
652 @{ML_response [display,gray] |
649 "parse OuterParse.opt_target (filtered_input \"(in test)\")" "(SOME \"test\",[])"} |
653 "parse OuterParse.opt_target (filtered_input \"(in test)\")" "(SOME \"test\",[])"} |
650 |
654 |
651 returns the locale @{text [quotes] "test"}; if no target is given' like in the |
655 returns the locale @{text [quotes] "test"}; if no target is given, like in the |
652 casde of @{text "even"} and @{text "odd"}, the function returns @{ML NONE}. |
656 case of @{text "even"} and @{text "odd"}, the function returns @{ML NONE}. |
653 |
657 |
654 The function @{ML OuterParse.fixes} in Line 3 reads an \isacommand{and}-separated |
658 The function @{ML OuterParse.fixes} in Line 3 reads an \isacommand{and}-separated |
655 list of variables that can include optional type annotations and syntax translations. |
659 list of variables that can include optional type annotations and syntax translations. |
656 For example:\footnote{Note that in the code we need to write |
660 For example:\footnote{Note that in the code we need to write |
657 @{text "\\\"int \<Rightarrow> bool\\\""} in order to properly escape the double quotes |
661 @{text "\\\"int \<Rightarrow> bool\\\""} in order to properly escape the double quotes |
669 (blonk, NONE, NoSyn)],[])"} |
673 (blonk, NONE, NoSyn)],[])"} |
670 *} |
674 *} |
671 |
675 |
672 text {* |
676 text {* |
673 Whenever types are given, they are stored in the @{ML SOME}s. Since types |
677 Whenever types are given, they are stored in the @{ML SOME}s. Since types |
674 are part of the inner syntax they are strings with some printing directives |
678 are part of the inner syntax they are strings with some encoded information |
675 (see previous section). |
679 (see previous section). |
676 If a syntax translation is present for a variable, then it is |
680 If a syntax translation is present for a variable, then it is |
677 stored in the @{ML Mixfix} datastructure; no syntax translation is |
681 stored in the @{ML Mixfix} datastructure; no syntax translation is |
678 indicated by @{ML NoSyn}. |
682 indicated by @{ML NoSyn}. |
679 |
683 |
699 val ((name, attrib), _) = parse (SpecParse.thm_name \":\") input |
703 val ((name, attrib), _) = parse (SpecParse.thm_name \":\") input |
700 in |
704 in |
701 (name, map Args.dest_src attrib) |
705 (name, map Args.dest_src attrib) |
702 end" "(foo_lemma, [((\"intro\", []), \<dots>), ((\"dest\", [\<dots>]), \<dots>)])"} |
706 end" "(foo_lemma, [((\"intro\", []), \<dots>), ((\"dest\", [\<dots>]), \<dots>)])"} |
703 |
707 |
704 A name of a theorem can be quite complicated, as it can include attrinutes. |
|
705 The function @{ML opt_thm_name in SpecParse} is the ``optional'' variant of |
708 The function @{ML opt_thm_name in SpecParse} is the ``optional'' variant of |
706 @{ML thm_name in SpecParse}. As can be seen each theorem name can contain some |
709 @{ML thm_name in SpecParse}. As can be seen each theorem name can contain some |
707 attributes. If you want to print out all currently known attributes a theorem |
710 attributes. If you want to print out all currently known attributes a theorem |
708 can have, you can use the function: |
711 can have, you can use the function: |
709 |
712 |
712 HOL.dest: declaration of Classical destruction rule |
715 HOL.dest: declaration of Classical destruction rule |
713 HOL.elim: declaration of Classical elimination rule |
716 HOL.elim: declaration of Classical elimination rule |
714 \<dots>"} |
717 \<dots>"} |
715 |
718 |
716 |
719 |
717 For the inductive definitions described above only, the attibutes @{text "[intro]"} and |
720 For the inductive definitions described above only the attibutes @{text "[intro]"} and |
718 @{text "[simp]"} make sense. |
721 @{text "[simp]"} make sense. |
719 |
722 |
720 \begin{readmore} |
723 \begin{readmore} |
721 Attributes and arguments are implemented in the files @{ML_file "Pure/Isar/attrib.ML"} |
724 Attributes and arguments are implemented in the files @{ML_file "Pure/Isar/attrib.ML"} |
722 and @{ML_file "Pure/Isar/args.ML"}. |
725 and @{ML_file "Pure/Isar/args.ML"}. |