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