ProgTutorial/Parsing.thy
changeset 565 cecd7a941885
parent 563 50d3059de9c6
child 566 6103b0eadbf2
equal deleted inserted replaced
564:6e2479089226 565:cecd7a941885
     2 imports Base "Package/Simple_Inductive_Package"
     2 imports Base "Package/Simple_Inductive_Package"
     3 keywords "foobar" "foobar_trace" :: thy_decl and
     3 keywords "foobar" "foobar_trace" :: thy_decl and
     4          "foobar_goal" "foobar_prove" :: thy_goal
     4          "foobar_goal" "foobar_prove" :: thy_goal
     5 begin
     5 begin
     6 
     6 
     7 chapter {* Parsing\label{chp:parsing} *}
     7 chapter \<open>Parsing\label{chp:parsing}\<close>
     8 
     8 
     9 
     9 
    10 text {*
    10 text \<open>
    11   \begin{flushright}
    11   \begin{flushright}
    12   {\em An important principle underlying the success and popularity of Unix\\ is
    12   {\em An important principle underlying the success and popularity of Unix\\ is
    13   the philosophy of building on the work of others.} \\[1ex]
    13   the philosophy of building on the work of others.} \\[1ex]
    14   Tony Travis in an email about the\\ ``LINUX is obsolete'' debate 
    14   Tony Travis in an email about the\\ ``LINUX is obsolete'' debate 
    15   \end{flushright}
    15   \end{flushright}
    45   "Pure/Isar/parse.ML"}. In addition specific parsers for packages are 
    45   "Pure/Isar/parse.ML"}. In addition specific parsers for packages are 
    46   defined in @{ML_file "Pure/Isar/parse_spec.ML"}. Parsers for method arguments 
    46   defined in @{ML_file "Pure/Isar/parse_spec.ML"}. Parsers for method arguments 
    47   are defined in @{ML_file "Pure/Isar/args.ML"}.
    47   are defined in @{ML_file "Pure/Isar/args.ML"}.
    48   \end{readmore}
    48   \end{readmore}
    49 
    49 
    50 *}
    50 \<close>
    51 
    51 
    52 section {* Building Generic Parsers *}
    52 section \<open>Building Generic Parsers\<close>
    53 
    53 
    54 text {*
    54 text \<open>
    55 
    55 
    56   Let us first have a look at parsing strings using generic parsing
    56   Let us first have a look at parsing strings using generic parsing
    57   combinators. The function @{ML_ind "$$" in Scan} takes a string as argument and will
    57   combinators. The function @{ML_ind "$$" in Scan} takes a string as argument and will
    58   ``consume'' this string from a given input list of strings. ``Consume'' in
    58   ``consume'' this string from a given input list of strings. ``Consume'' in
    59   this context means that it will return a pair consisting of this string and
    59   this context means that it will return a pair consisting of this string and
    64 
    64 
    65   @{ML_response [display,gray] 
    65   @{ML_response [display,gray] 
    66   "($$ \"w\") (Symbol.explode \"world\")" "(\"w\", [\"o\", \"r\", \"l\", \"d\"])"}
    66   "($$ \"w\") (Symbol.explode \"world\")" "(\"w\", [\"o\", \"r\", \"l\", \"d\"])"}
    67 
    67 
    68   The function @{ML "$$"} will either succeed (as in the two examples above)
    68   The function @{ML "$$"} will either succeed (as in the two examples above)
    69   or raise the exception @{text "FAIL"} if no string can be consumed. For
    69   or raise the exception \<open>FAIL\<close> if no string can be consumed. For
    70   example trying to parse
    70   example trying to parse
    71 
    71 
    72   @{ML_response_fake [display,gray] 
    72   @{ML_response_fake [display,gray] 
    73   "($$ \"x\") (Symbol.explode \"world\")" 
    73   "($$ \"x\") (Symbol.explode \"world\")" 
    74   "Exception FAIL raised"}
    74   "Exception FAIL raised"}
    75   
    75   
    76   will raise the exception @{text "FAIL"}. The function @{ML_ind "$$" in Scan} will also
    76   will raise the exception \<open>FAIL\<close>. The function @{ML_ind "$$" in Scan} will also
    77   fail if you try to consume more than a single character.
    77   fail if you try to consume more than a single character.
    78 
    78 
    79   There are three exceptions that are raised by the parsing combinators:
    79   There are three exceptions that are raised by the parsing combinators:
    80 
    80 
    81   \begin{itemize}
    81   \begin{itemize}
    82   \item @{text "FAIL"} indicates that alternative routes of parsing 
    82   \item \<open>FAIL\<close> indicates that alternative routes of parsing 
    83   might be explored. 
    83   might be explored. 
    84   \item @{text "MORE"} indicates that there is not enough input for the parser. For example 
    84   \item \<open>MORE\<close> indicates that there is not enough input for the parser. For example 
    85   in @{text "($$ \"h\") []"}.
    85   in \<open>($$ "h") []\<close>.
    86   \item @{text "ABORT"} indicates that a dead end is reached. 
    86   \item \<open>ABORT\<close> indicates that a dead end is reached. 
    87   It is used for example in the function @{ML "!!"} (see below).
    87   It is used for example in the function @{ML "!!"} (see below).
    88   \end{itemize}
    88   \end{itemize}
    89 
    89 
    90   However, note that these exceptions are private to the parser and cannot be accessed
    90   However, note that these exceptions are private to the parser and cannot be accessed
    91   by the programmer (for example to handle them).
    91   by the programmer (for example to handle them).
    92 
    92 
    93   In the examples above we use the function @{ML_ind explode in Symbol} from the
    93   In the examples above we use the function @{ML_ind explode in Symbol} from the
    94   structure @{ML_struct Symbol}, instead of the more standard library function
    94   structure @{ML_struct Symbol}, instead of the more standard library function
    95   @{ML_ind explode in String}, for obtaining an input list for the parser. The reason is
    95   @{ML_ind explode in String}, for obtaining an input list for the parser. The reason is
    96   that @{ML explode in Symbol} is aware of character
    96   that @{ML explode in Symbol} is aware of character
    97   sequences, for example @{text "\<foo>"}, that have a special meaning in
    97   sequences, for example \<open>\<foo>\<close>, that have a special meaning in
    98   Isabelle. To see the difference consider
    98   Isabelle. To see the difference consider
    99 
    99 
   100 @{ML_response_fake [display,gray]
   100 @{ML_response_fake [display,gray]
   101 "let 
   101 "let 
   102   val input = \"\<foo> bar\"
   102   val input = \"\<foo> bar\"
   122   (hw input1, hw input2)
   122   (hw input1, hw input2)
   123 end"
   123 end"
   124     "((\"h\", [\"e\", \"l\", \"l\", \"o\"]),(\"w\", [\"o\", \"r\", \"l\", \"d\"]))"}
   124     "((\"h\", [\"e\", \"l\", \"l\", \"o\"]),(\"w\", [\"o\", \"r\", \"l\", \"d\"]))"}
   125 
   125 
   126   Two parsers can be connected in sequence by using the function @{ML_ind "--" in Scan}. 
   126   Two parsers can be connected in sequence by using the function @{ML_ind "--" in Scan}. 
   127   For example parsing @{text "h"}, @{text "e"} and @{text "l"} (in this 
   127   For example parsing \<open>h\<close>, \<open>e\<close> and \<open>l\<close> (in this 
   128   order) you can achieve by:
   128   order) you can achieve by:
   129 
   129 
   130   @{ML_response [display,gray] 
   130   @{ML_response [display,gray] 
   131   "($$ \"h\" -- $$ \"e\" -- $$ \"l\") (Symbol.explode \"hello\")"
   131   "($$ \"h\" -- $$ \"e\" -- $$ \"l\") (Symbol.explode \"hello\")"
   132   "(((\"h\", \"e\"), \"l\"), [\"l\", \"o\"])"}
   132   "(((\"h\", \"e\"), \"l\"), [\"l\", \"o\"])"}
   140   "Scan.this_string \"hell\" (Symbol.explode \"hello\")"
   140   "Scan.this_string \"hell\" (Symbol.explode \"hello\")"
   141   "(\"hell\", [\"o\"])"}
   141   "(\"hell\", [\"o\"])"}
   142 
   142 
   143   Parsers that explore alternatives can be constructed using the function 
   143   Parsers that explore alternatives can be constructed using the function 
   144   @{ML_ind  "||" in Scan}. The parser @{ML "(p || q)" for p q} returns the
   144   @{ML_ind  "||" in Scan}. The parser @{ML "(p || q)" for p q} returns the
   145   result of @{text "p"}, in case it succeeds; otherwise it returns the
   145   result of \<open>p\<close>, in case it succeeds; otherwise it returns the
   146   result of @{text "q"}. For example:
   146   result of \<open>q\<close>. For example:
   147 
   147 
   148 
   148 
   149 @{ML_response [display,gray] 
   149 @{ML_response [display,gray] 
   150 "let 
   150 "let 
   151   val hw = $$ \"h\" || $$ \"w\"
   151   val hw = $$ \"h\" || $$ \"w\"
   171   (just_e input, just_h input)
   171   (just_e input, just_h input)
   172 end"
   172 end"
   173   "((\"e\", [\"l\", \"l\", \"o\"]), (\"h\", [\"l\", \"l\", \"o\"]))"}
   173   "((\"e\", [\"l\", \"l\", \"o\"]), (\"h\", [\"l\", \"l\", \"o\"]))"}
   174 
   174 
   175   The parser @{ML "Scan.optional p x" for p x} returns the result of the parser 
   175   The parser @{ML "Scan.optional p x" for p x} returns the result of the parser 
   176   @{text "p"}, in case it succeeds; otherwise it returns 
   176   \<open>p\<close>, in case it succeeds; otherwise it returns 
   177   the default value @{text "x"}. For example:
   177   the default value \<open>x\<close>. For example:
   178 
   178 
   179 @{ML_response [display,gray]
   179 @{ML_response [display,gray]
   180 "let 
   180 "let 
   181   val p = Scan.optional ($$ \"h\") \"x\"
   181   val p = Scan.optional ($$ \"h\") \"x\"
   182   val input1 = Symbol.explode \"hello\"
   182   val input1 = Symbol.explode \"hello\"
   185   (p input1, p input2)
   185   (p input1, p input2)
   186 end" 
   186 end" 
   187  "((\"h\", [\"e\", \"l\", \"l\", \"o\"]), (\"x\", [\"w\", \"o\", \"r\", \"l\", \"d\"]))"}
   187  "((\"h\", [\"e\", \"l\", \"l\", \"o\"]), (\"x\", [\"w\", \"o\", \"r\", \"l\", \"d\"]))"}
   188 
   188 
   189   The function @{ML_ind option in Scan} works similarly, except no default value can
   189   The function @{ML_ind option in Scan} works similarly, except no default value can
   190   be given. Instead, the result is wrapped as an @{text "option"}-type. For example:
   190   be given. Instead, the result is wrapped as an \<open>option\<close>-type. For example:
   191 
   191 
   192 @{ML_response [display,gray]
   192 @{ML_response [display,gray]
   193 "let 
   193 "let 
   194   val p = Scan.option ($$ \"h\")
   194   val p = Scan.option ($$ \"h\")
   195   val input1 = Symbol.explode \"hello\"
   195   val input1 = Symbol.explode \"hello\"
   204   @{ML_response [display,gray]
   204   @{ML_response [display,gray]
   205   "Scan.ahead (Scan.this_string \"foo\") (Symbol.explode \"foo\")" 
   205   "Scan.ahead (Scan.this_string \"foo\") (Symbol.explode \"foo\")" 
   206   "(\"foo\", [\"f\", \"o\", \"o\"])"} 
   206   "(\"foo\", [\"f\", \"o\", \"o\"])"} 
   207 
   207 
   208   The function @{ML_ind "!!" in Scan} helps with producing appropriate error messages
   208   The function @{ML_ind "!!" in Scan} helps with producing appropriate error messages
   209   during parsing. For example if you want to parse @{text p} immediately 
   209   during parsing. For example if you want to parse \<open>p\<close> immediately 
   210   followed by @{text q}, or start a completely different parser @{text r},
   210   followed by \<open>q\<close>, or start a completely different parser \<open>r\<close>,
   211   you might write:
   211   you might write:
   212 
   212 
   213   @{ML [display,gray] "(p -- q) || r" for p q r}
   213   @{ML [display,gray] "(p -- q) || r" for p q r}
   214 
   214 
   215   However, this parser is problematic for producing a useful error
   215   However, this parser is problematic for producing a useful error
   216   message, if the parsing of @{ML "(p -- q)" for p q} fails. Because with the
   216   message, if the parsing of @{ML "(p -- q)" for p q} fails. Because with the
   217   parser above you lose the information that @{text p} should be followed by @{text q}.
   217   parser above you lose the information that \<open>p\<close> should be followed by \<open>q\<close>.
   218   To see this assume that @{text p} is present in the input, but it is not
   218   To see this assume that \<open>p\<close> is present in the input, but it is not
   219   followed by @{text q}. That means @{ML "(p -- q)" for p q} will fail and
   219   followed by \<open>q\<close>. That means @{ML "(p -- q)" for p q} will fail and
   220   hence the alternative parser @{text r} will be tried. However, in many
   220   hence the alternative parser \<open>r\<close> will be tried. However, in many
   221   circumstances this will be the wrong parser for the input ``@{text "p"}-followed-by-something''
   221   circumstances this will be the wrong parser for the input ``\<open>p\<close>-followed-by-something''
   222   and therefore will also fail. The error message is then caused by the failure
   222   and therefore will also fail. The error message is then caused by the failure
   223   of @{text r}, not by the absence of @{text q} in the input. Such
   223   of \<open>r\<close>, not by the absence of \<open>q\<close> in the input. Such
   224   situation can be avoided when using the function @{ML "!!"}.  This function
   224   situation can be avoided when using the function @{ML "!!"}.  This function
   225   aborts the whole process of parsing in case of a failure and prints an error
   225   aborts the whole process of parsing in case of a failure and prints an error
   226   message. For example if you invoke the parser
   226   message. For example if you invoke the parser
   227 
   227 
   228 
   228 
   237   but if you invoke it on @{text [quotes] "world"}
   237   but if you invoke it on @{text [quotes] "world"}
   238 
   238 
   239   @{ML_response_fake [display,gray] "(!! (fn _ => fn _ => \"foo\") ($$ \"h\")) (Symbol.explode \"world\")"
   239   @{ML_response_fake [display,gray] "(!! (fn _ => fn _ => \"foo\") ($$ \"h\")) (Symbol.explode \"world\")"
   240                                "Exception ABORT raised"}
   240                                "Exception ABORT raised"}
   241 
   241 
   242   then the parsing aborts and the error message @{text "foo"} is printed. In order to
   242   then the parsing aborts and the error message \<open>foo\<close> is printed. In order to
   243   see the error message properly, you need to prefix the parser with the function 
   243   see the error message properly, you need to prefix the parser with the function 
   244   @{ML_ind error in Scan}. For example:
   244   @{ML_ind error in Scan}. For example:
   245 
   245 
   246   @{ML_response_fake [display,gray] 
   246   @{ML_response_fake [display,gray] 
   247   "Scan.error (!! (fn _ => fn _ => \"foo\") ($$ \"h\")) (Symbol.explode \"world\")"
   247   "Scan.error (!! (fn _ => fn _ => \"foo\") ($$ \"h\")) (Symbol.explode \"world\")"
   251   such as @{ML_ind local_theory in Outer_Syntax} 
   251   such as @{ML_ind local_theory in Outer_Syntax} 
   252   (see Section~\ref{sec:newcommand} which explains this function in more detail). 
   252   (see Section~\ref{sec:newcommand} which explains this function in more detail). 
   253   
   253   
   254   Let us now return to our example of parsing @{ML "(p -- q) || r" for p q
   254   Let us now return to our example of parsing @{ML "(p -- q) || r" for p q
   255   r}. If you want to generate the correct error message for failure
   255   r}. If you want to generate the correct error message for failure
   256   of parsing @{text "p"}-followed-by-@{text "q"}, then you have to write:
   256   of parsing \<open>p\<close>-followed-by-\<open>q\<close>, then you have to write:
   257 *}
   257 \<close>
   258 
   258 
   259 ML %grayML{*fun p_followed_by_q p q r =
   259 ML %grayML\<open>fun p_followed_by_q p q r =
   260 let 
   260 let 
   261   val err_msg = fn _ => p ^ " is not followed by " ^ q
   261   val err_msg = fn _ => p ^ " is not followed by " ^ q
   262 in
   262 in
   263   ($$ p -- (!! (fn _ => err_msg) ($$ q))) || ($$ r -- $$ r)
   263   ($$ p -- (!! (fn _ => err_msg) ($$ q))) || ($$ r -- $$ r)
   264 end *}
   264 end\<close>
   265 
   265 
   266 
   266 
   267 text {*
   267 text \<open>
   268   Running this parser with the arguments
   268   Running this parser with the arguments
   269   @{text [quotes] "h"}, @{text [quotes] "e"} and @{text [quotes] "w"}, and 
   269   @{text [quotes] "h"}, @{text [quotes] "e"} and @{text [quotes] "w"}, and 
   270   the input @{text [quotes] "holle"} 
   270   the input @{text [quotes] "holle"} 
   271 
   271 
   272   @{ML_response_fake [display,gray] "Scan.error (p_followed_by_q \"h\" \"e\" \"w\") (Symbol.explode \"holle\")"
   272   @{ML_response_fake [display,gray] "Scan.error (p_followed_by_q \"h\" \"e\" \"w\") (Symbol.explode \"holle\")"
   277   @{ML_response [display,gray] "Scan.error (p_followed_by_q \"h\" \"e\" \"w\") (Symbol.explode \"wworld\")"
   277   @{ML_response [display,gray] "Scan.error (p_followed_by_q \"h\" \"e\" \"w\") (Symbol.explode \"wworld\")"
   278                           "((\"w\", \"w\"), [\"o\", \"r\", \"l\", \"d\"])"}
   278                           "((\"w\", \"w\"), [\"o\", \"r\", \"l\", \"d\"])"}
   279   
   279   
   280   yields the expected parsing. 
   280   yields the expected parsing. 
   281 
   281 
   282   The function @{ML "Scan.repeat p" for p} will apply a parser @{text p} as 
   282   The function @{ML "Scan.repeat p" for p} will apply a parser \<open>p\<close> as 
   283   long as it succeeds. For example:
   283   long as it succeeds. For example:
   284   
   284   
   285   @{ML_response [display,gray] "Scan.repeat ($$ \"h\") (Symbol.explode \"hhhhello\")" 
   285   @{ML_response [display,gray] "Scan.repeat ($$ \"h\") (Symbol.explode \"hhhhello\")" 
   286                 "([\"h\", \"h\", \"h\", \"h\"], [\"e\", \"l\", \"l\", \"o\"])"}
   286                 "([\"h\", \"h\", \"h\", \"h\"], [\"e\", \"l\", \"l\", \"o\"])"}
   287   
   287   
   288   Note that @{ML_ind repeat in Scan} stores the parsed items in a list. The function
   288   Note that @{ML_ind repeat in Scan} stores the parsed items in a list. The function
   289   @{ML_ind repeat1 in Scan} is similar, but requires that the parser @{text "p"} 
   289   @{ML_ind repeat1 in Scan} is similar, but requires that the parser \<open>p\<close> 
   290   succeeds at least once.
   290   succeeds at least once.
   291 
   291 
   292   Also note that the parser would have aborted with the exception @{text MORE}, if
   292   Also note that the parser would have aborted with the exception \<open>MORE\<close>, if
   293   you had it run with the string @{text [quotes] "hhhh"}. This can be avoided by using
   293   you had it run with the string @{text [quotes] "hhhh"}. This can be avoided by using
   294   the wrapper @{ML_ind finite in Scan} and the ``stopper-token'' 
   294   the wrapper @{ML_ind finite in Scan} and the ``stopper-token'' 
   295   @{ML_ind stopper in Symbol}. With them you can write:
   295   @{ML_ind stopper in Symbol}. With them you can write:
   296   
   296   
   297   @{ML_response [display,gray] "Scan.finite Symbol.stopper (Scan.repeat ($$ \"h\")) (Symbol.explode \"hhhh\")" 
   297   @{ML_response [display,gray] "Scan.finite Symbol.stopper (Scan.repeat ($$ \"h\")) (Symbol.explode \"hhhh\")" 
   347 
   347 
   348   
   348   
   349   After parsing is done, you almost always want to apply a function to the parsed 
   349   After parsing is done, you almost always want to apply a function to the parsed 
   350   items. One way to do this is the function @{ML_ind ">>" in Scan} where 
   350   items. One way to do this is the function @{ML_ind ">>" in Scan} where 
   351   @{ML "(p >> f)" for p f} runs 
   351   @{ML "(p >> f)" for p f} runs 
   352   first the parser @{text p} and upon successful completion applies the 
   352   first the parser \<open>p\<close> and upon successful completion applies the 
   353   function @{text f} to the result. For example
   353   function \<open>f\<close> to the result. For example
   354 
   354 
   355 @{ML_response [display,gray]
   355 @{ML_response [display,gray]
   356 "let 
   356 "let 
   357   fun double (x, y) = (x ^ x, y ^ y) 
   357   fun double (x, y) = (x ^ x, y ^ y) 
   358   val parser = $$ \"h\" -- $$ \"e\"
   358   val parser = $$ \"h\" -- $$ \"e\"
   381 
   381 
   382 @{ML_response [display,gray]
   382 @{ML_response [display,gray]
   383 "Scan.lift ($$ \"h\" -- $$ \"e\") (1, Symbol.explode \"hello\")"
   383 "Scan.lift ($$ \"h\" -- $$ \"e\") (1, Symbol.explode \"hello\")"
   384 "((\"h\", \"e\"), (1, [\"l\", \"l\", \"o\"]))"}
   384 "((\"h\", \"e\"), (1, [\"l\", \"l\", \"o\"]))"}
   385 
   385 
   386   \footnote{\bf FIXME: In which situations is @{text "lift"} useful? Give examples.} 
   386   \footnote{\bf FIXME: In which situations is \<open>lift\<close> useful? Give examples.} 
   387 
   387 
   388   Be aware of recursive parsers. Suppose you want to read strings separated by
   388   Be aware of recursive parsers. Suppose you want to read strings separated by
   389   commas and by parentheses into a tree datastructure; for example, generating
   389   commas and by parentheses into a tree datastructure; for example, generating
   390   the tree corresponding to the string @{text [quotes] "(A, A), (A, A)"} where
   390   the tree corresponding to the string @{text [quotes] "(A, A), (A, A)"} where
   391   the @{text "A"}s will be the leaves.  We assume the trees are represented by the
   391   the \<open>A\<close>s will be the leaves.  We assume the trees are represented by the
   392   datatype:
   392   datatype:
   393 *}
   393 \<close>
   394 
   394 
   395 ML %grayML{*datatype tree = 
   395 ML %grayML\<open>datatype tree = 
   396     Lf of string 
   396     Lf of string 
   397   | Br of tree * tree*}
   397   | Br of tree * tree\<close>
   398 
   398 
   399 text {*
   399 text \<open>
   400   Since nested parentheses should be treated in a meaningful way---for example
   400   Since nested parentheses should be treated in a meaningful way---for example
   401   the string @{text [quotes] "((A))"} should be read into a single 
   401   the string @{text [quotes] "((A))"} should be read into a single 
   402   leaf---you might implement the following parser.
   402   leaf---you might implement the following parser.
   403 *}
   403 \<close>
   404 
   404 
   405 ML %grayML{*fun parse_basic s = 
   405 ML %grayML\<open>fun parse_basic s = 
   406   $$ s >> Lf || $$ "(" |-- parse_tree s --| $$ ")"  
   406   $$ s >> Lf || $$ "(" |-- parse_tree s --| $$ ")"  
   407 
   407 
   408 and parse_tree s = 
   408 and parse_tree s = 
   409   parse_basic s --| $$ "," -- parse_tree s >> Br || parse_basic s*}
   409   parse_basic s --| $$ "," -- parse_tree s >> Br || parse_basic s\<close>
   410 
   410 
   411 text {*
   411 text \<open>
   412   This parser corresponds to the grammar:
   412   This parser corresponds to the grammar:
   413 
   413 
   414   \begin{center}
   414   \begin{center}
   415   \begin{tabular}{lcl}
   415   \begin{tabular}{lcl}
   416   @{text "<Basic>"}  & @{text "::="} & @{text "<String> | (<Tree>)"}\\
   416   \<open><Basic>\<close>  & \<open>::=\<close> & \<open><String> | (<Tree>)\<close>\\
   417   @{text "<Tree>"}   & @{text "::="} & @{text "<Basic>, <Tree> | <Basic>"}\\
   417   \<open><Tree>\<close>   & \<open>::=\<close> & \<open><Basic>, <Tree> | <Basic>\<close>\\
   418   \end{tabular}
   418   \end{tabular}
   419   \end{center}
   419   \end{center}
   420 
   420 
   421   The parameter @{text "s"} is the string over which the tree is parsed. The
   421   The parameter \<open>s\<close> is the string over which the tree is parsed. The
   422   parser @{ML parse_basic} reads either a leaf or a tree enclosed in
   422   parser @{ML parse_basic} reads either a leaf or a tree enclosed in
   423   parentheses. The parser @{ML parse_tree} reads either a pair of trees
   423   parentheses. The parser @{ML parse_tree} reads either a pair of trees
   424   separated by a comma, or acts like @{ML parse_basic}. Unfortunately,
   424   separated by a comma, or acts like @{ML parse_basic}. Unfortunately,
   425   because of the mutual recursion, this parser will immediately run into a
   425   because of the mutual recursion, this parser will immediately run into a
   426   loop, even if it is called without any input. For example
   426   loop, even if it is called without any input. For example
   433   looping parser are not useful, because of ML's strict evaluation of
   433   looping parser are not useful, because of ML's strict evaluation of
   434   arguments. Therefore we need to delay the execution of the
   434   arguments. Therefore we need to delay the execution of the
   435   parser until an input is given. This can be done by adding the parsed
   435   parser until an input is given. This can be done by adding the parsed
   436   string as an explicit argument. So the parser above should be implemented
   436   string as an explicit argument. So the parser above should be implemented
   437   as follows.
   437   as follows.
   438 *}
   438 \<close>
   439 
   439 
   440 ML %grayML{*fun parse_basic s xs = 
   440 ML %grayML\<open>fun parse_basic s xs = 
   441   ($$ s >> Lf || $$ "(" |-- parse_tree s --| $$ ")") xs 
   441   ($$ s >> Lf || $$ "(" |-- parse_tree s --| $$ ")") xs 
   442 
   442 
   443 and parse_tree s xs = 
   443 and parse_tree s xs = 
   444   (parse_basic s --| $$ "," -- parse_tree s >> Br || parse_basic s) xs*}
   444   (parse_basic s --| $$ "," -- parse_tree s >> Br || parse_basic s) xs\<close>
   445 
   445 
   446 text {*
   446 text \<open>
   447   While the type of the parser is unchanged by the addition, its behaviour 
   447   While the type of the parser is unchanged by the addition, its behaviour 
   448   changed: with this version of the parser the execution is delayed until 
   448   changed: with this version of the parser the execution is delayed until 
   449   some string is  applied for the argument @{text "xs"}. This gives us 
   449   some string is  applied for the argument \<open>xs\<close>. This gives us 
   450   exactly the parser what we wanted. An example is as follows:
   450   exactly the parser what we wanted. An example is as follows:
   451 
   451 
   452   @{ML_response [display, gray]
   452   @{ML_response [display, gray]
   453   "let
   453   "let
   454   val input = Symbol.explode \"(A,((A))),A\"
   454   val input = Symbol.explode \"(A,((A))),A\"
   458   "(Br (Br (Lf \"A\", Lf \"A\"), Lf \"A\"), [])"}
   458   "(Br (Br (Lf \"A\", Lf \"A\"), Lf \"A\"), [])"}
   459 
   459 
   460 
   460 
   461   \begin{exercise}\label{ex:scancmts}
   461   \begin{exercise}\label{ex:scancmts}
   462   Write a parser that parses an input string so that any comment enclosed
   462   Write a parser that parses an input string so that any comment enclosed
   463   within @{text "(*\<dots>*)"} is replaced by the same comment but enclosed within
   463   within \<open>(*\<dots>*)\<close> is replaced by the same comment but enclosed within
   464   @{text "(**\<dots>**)"} in the output string. To enclose a string, you can use the
   464   \<open>(**\<dots>**)\<close> in the output string. To enclose a string, you can use the
   465   function @{ML "enclose s1 s2 s" for s1 s2 s} which produces the string @{ML
   465   function @{ML "enclose s1 s2 s" for s1 s2 s} which produces the string @{ML
   466   "s1 ^ s ^ s2" for s1 s2 s}. Hint: To simplify the task ignore the proper 
   466   "s1 ^ s ^ s2" for s1 s2 s}. Hint: To simplify the task ignore the proper 
   467   nesting of comments.
   467   nesting of comments.
   468   \end{exercise}
   468   \end{exercise}
   469 *}
   469 \<close>
   470 
   470 
   471 section {* Parsing Theory Syntax *}
   471 section \<open>Parsing Theory Syntax\<close>
   472 
   472 
   473 text {*
   473 text \<open>
   474   Most of the time, however, Isabelle developers have to deal with parsing
   474   Most of the time, however, Isabelle developers have to deal with parsing
   475   tokens, not strings.  These token parsers have the type:
   475   tokens, not strings.  These token parsers have the type:
   476 *}
   476 \<close>
   477   
   477   
   478 ML %grayML{*type 'a parser = Token.T list -> 'a * Token.T list*}
   478 ML %grayML\<open>type 'a parser = Token.T list -> 'a * Token.T list\<close>
   479 ML "Thy_Header.get_keywords'"
   479 ML "Thy_Header.get_keywords'"
   480 text {*
   480 text \<open>
   481   {\bf REDO!!}
   481   {\bf REDO!!}
   482 
   482 
   483 
   483 
   484   The reason for using token parsers is that theory syntax, as well as the
   484   The reason for using token parsers is that theory syntax, as well as the
   485   parsers for the arguments of proof methods, use the type @{ML_type
   485   parsers for the arguments of proof methods, use the type @{ML_type
   512   @{text [quotes] "hello"} and @{text [quotes] "world"} do not match any
   512   @{text [quotes] "hello"} and @{text [quotes] "world"} do not match any
   513   other syntactic category. The second indicates a space.
   513   other syntactic category. The second indicates a space.
   514 
   514 
   515   We can easily change what is recognised as a keyword with the function
   515   We can easily change what is recognised as a keyword with the function
   516   @{ML_ind add_keywords in Thy_Header}. For example calling it with 
   516   @{ML_ind add_keywords in Thy_Header}. For example calling it with 
   517 *}
   517 \<close>
   518 
   518 
   519 
   519 
   520 
   520 
   521 setup {* Thy_Header.add_keywords [(("hello", Position.none),Keyword.no_spec)] *}
   521 setup \<open>Thy_Header.add_keywords [(("hello", Position.none),Keyword.no_spec)]\<close>
   522 
   522 
   523 
   523 
   524 text {*
   524 text \<open>
   525   then lexing @{text [quotes] "hello world"} will produce
   525   then lexing @{text [quotes] "hello world"} will produce
   526 
   526 
   527   @{ML_response_fake [display,gray] "Token.explode 
   527   @{ML_response_fake [display,gray] "Token.explode 
   528   (Thy_Header.get_keywords' @{context}) Position.none \"hello world\"" 
   528   (Thy_Header.get_keywords' @{context}) Position.none \"hello world\"" 
   529 "[Token (\<dots>,(Keyword, \"hello\"),\<dots>), 
   529 "[Token (\<dots>,(Keyword, \"hello\"),\<dots>), 
   542    filter Token.is_proper input
   542    filter Token.is_proper input
   543 end" 
   543 end" 
   544 "[Token (\<dots>,(Ident, \"hello\"), \<dots>), Token (\<dots>,(Ident, \"world\"), \<dots>)]"}
   544 "[Token (\<dots>,(Ident, \"hello\"), \<dots>), Token (\<dots>,(Ident, \"world\"), \<dots>)]"}
   545 
   545 
   546   For convenience we define the function:
   546   For convenience we define the function:
   547 *}
   547 \<close>
   548 
   548 
   549 ML %grayML{*fun filtered_input str = 
   549 ML %grayML\<open>fun filtered_input str = 
   550   filter Token.is_proper (Token.explode (Thy_Header.get_keywords' @{context}) Position.none str) *}
   550   filter Token.is_proper (Token.explode (Thy_Header.get_keywords' @{context}) Position.none str)\<close>
   551 
   551 
   552 ML \<open>filtered_input "inductive | for"\<close>
   552 ML \<open>filtered_input "inductive | for"\<close>
   553 text {* 
   553 text \<open>
   554   If you now parse
   554   If you now parse
   555 
   555 
   556 @{ML_response_fake [display,gray] 
   556 @{ML_response_fake [display,gray] 
   557 "filtered_input \"inductive | for\"" 
   557 "filtered_input \"inductive | for\"" 
   558 "[Token (\<dots>,(Command, \"inductive\"),\<dots>), 
   558 "[Token (\<dots>,(Command, \"inductive\"),\<dots>), 
   561 
   561 
   562   you obtain a list consisting of only one command and two keyword tokens.
   562   you obtain a list consisting of only one command and two keyword tokens.
   563   If you want to see which keywords and commands are currently known to Isabelle, 
   563   If you want to see which keywords and commands are currently known to Isabelle, 
   564   use the function @{ML_ind get_keywords' in Thy_Header}:
   564   use the function @{ML_ind get_keywords' in Thy_Header}:
   565 
   565 
   566   You might have to adjust the @{text ML_print_depth} in order to
   566   You might have to adjust the \<open>ML_print_depth\<close> in order to
   567   see the complete list.
   567   see the complete list.
   568 
   568 
   569   The parser @{ML_ind "$$$" in Parse} parses a single keyword. For example:
   569   The parser @{ML_ind "$$$" in Parse} parses a single keyword. For example:
   570 
   570 
   571 @{ML_response [display,gray]
   571 @{ML_response [display,gray]
   598   (Parse.$$$ \"|\" -- Parse.$$$ \"in\") input
   598   (Parse.$$$ \"|\" -- Parse.$$$ \"in\") input
   599 end"
   599 end"
   600 "((\"|\", \"in\"), [])"}
   600 "((\"|\", \"in\"), [])"}
   601 
   601 
   602   The parser @{ML "Parse.enum s p" for s p} parses a possibly empty 
   602   The parser @{ML "Parse.enum s p" for s p} parses a possibly empty 
   603   list of items recognised by the parser @{text p}, where the items being parsed
   603   list of items recognised by the parser \<open>p\<close>, where the items being parsed
   604   are separated by the string @{text s}. For example:
   604   are separated by the string \<open>s\<close>. For example:
   605 
   605 
   606 @{ML_response [display,gray]
   606 @{ML_response [display,gray]
   607 "let 
   607 "let 
   608   val input = filtered_input \"in | in | in foo\"
   608   val input = filtered_input \"in | in | in foo\"
   609 in 
   609 in 
   612 "([\"in\", \"in\", \"in\"], [\<dots>])"}
   612 "([\"in\", \"in\", \"in\"], [\<dots>])"}
   613 
   613 
   614   The function @{ML_ind enum1 in Parse} works similarly, except that the
   614   The function @{ML_ind enum1 in Parse} works similarly, except that the
   615   parsed list must be non-empty. Note that we had to add a string @{text
   615   parsed list must be non-empty. Note that we had to add a string @{text
   616   [quotes] "foo"} at the end of the parsed string, otherwise the parser would
   616   [quotes] "foo"} at the end of the parsed string, otherwise the parser would
   617   have consumed all tokens and then failed with the exception @{text
   617   have consumed all tokens and then failed with the exception \<open>MORE\<close>. Like in the previous section, we can avoid this exception using the
   618   "MORE"}. Like in the previous section, we can avoid this exception using the
       
   619   wrapper @{ML Scan.finite}. This time, however, we have to use the
   618   wrapper @{ML Scan.finite}. This time, however, we have to use the
   620   ``stopper-token'' @{ML Token.stopper}. We can write:
   619   ``stopper-token'' @{ML Token.stopper}. We can write:
   621 
   620 
   622 @{ML_response [display,gray]
   621 @{ML_response [display,gray]
   623 "let 
   622 "let 
   627   Scan.finite Token.stopper p input
   626   Scan.finite Token.stopper p input
   628 end" 
   627 end" 
   629 "([\"in\", \"in\", \"in\"], [])"}
   628 "([\"in\", \"in\", \"in\"], [])"}
   630 
   629 
   631   The following function will help to run examples.
   630   The following function will help to run examples.
   632 *}
   631 \<close>
   633 
   632 
   634 ML %grayML{*fun parse p input = Scan.finite Token.stopper (Scan.error p) input *}
   633 ML %grayML\<open>fun parse p input = Scan.finite Token.stopper (Scan.error p) input\<close>
   635 
   634 
   636 text {*
   635 text \<open>
   637   The function @{ML_ind "!!!" in Parse} can be used to force termination
   636   The function @{ML_ind "!!!" in Parse} can be used to force termination
   638   of the parser in case of a dead end, just like @{ML "Scan.!!"} (see previous
   637   of the parser in case of a dead end, just like @{ML "Scan.!!"} (see previous
   639   section). A difference, however, is that the error message of @{ML
   638   section). A difference, however, is that the error message of @{ML
   640   "Parse.!!!"} is fixed to be @{text [quotes] "Outer syntax error"}
   639   "Parse.!!!"} is fixed to be @{text [quotes] "Outer syntax error"}
   641   together with a relatively precise description of the failure. For example:
   640   together with a relatively precise description of the failure. For example:
   662   Whenever there is a possibility that the processing of user input can fail, 
   661   Whenever there is a possibility that the processing of user input can fail, 
   663   it is a good idea to give all available information about where the error 
   662   it is a good idea to give all available information about where the error 
   664   occurred. For this Isabelle can attach positional information to tokens
   663   occurred. For this Isabelle can attach positional information to tokens
   665   and then thread this information up the ``processing chain''. To see this,
   664   and then thread this information up the ``processing chain''. To see this,
   666   modify the function @{ML filtered_input}, described earlier, as follows 
   665   modify the function @{ML filtered_input}, described earlier, as follows 
   667 *}
   666 \<close>
   668 
   667 
   669 ML %grayML{*fun filtered_input' str = 
   668 ML %grayML\<open>fun filtered_input' str = 
   670        filter Token.is_proper (Token.explode (Thy_Header.get_keywords' @{context}) (Position.line 7) str) *}
   669        filter Token.is_proper (Token.explode (Thy_Header.get_keywords' @{context}) (Position.line 7) str)\<close>
   671 
   670 
   672 text {*
   671 text \<open>
   673   where we pretend the parsed string starts on line 7. An example is
   672   where we pretend the parsed string starts on line 7. An example is
   674 
   673 
   675 @{ML_response_fake [display,gray]
   674 @{ML_response_fake [display,gray]
   676 "filtered_input' \"foo \\n bar\""
   675 "filtered_input' \"foo \\n bar\""
   677 "[Token ((\"foo\", ({line=7, end_line=7}, {line=7})), (Ident, \"foo\"), \<dots>),
   676 "[Token ((\"foo\", ({line=7, end_line=7}, {line=7})), (Ident, \"foo\"), \<dots>),
   702   binds stronger than addition, and both of them nest to the right. 
   701   binds stronger than addition, and both of them nest to the right. 
   703   The context-free grammar is defined as:
   702   The context-free grammar is defined as:
   704 
   703 
   705   \begin{center}
   704   \begin{center}
   706   \begin{tabular}{lcl}
   705   \begin{tabular}{lcl}
   707   @{text "<Basic>"}  & @{text "::="} & @{text "<Number> | (<Expr>)"}\\
   706   \<open><Basic>\<close>  & \<open>::=\<close> & \<open><Number> | (<Expr>)\<close>\\
   708   @{text "<Factor>"} & @{text "::="} & @{text "<Basic> * <Factor> | <Basic>"}\\
   707   \<open><Factor>\<close> & \<open>::=\<close> & \<open><Basic> * <Factor> | <Basic>\<close>\\
   709   @{text "<Expr>"}   & @{text "::="} & @{text "<Factor> + <Expr>  | <Factor>"}\\
   708   \<open><Expr>\<close>   & \<open>::=\<close> & \<open><Factor> + <Expr>  | <Factor>\<close>\\
   710   \end{tabular}
   709   \end{tabular}
   711   \end{center}
   710   \end{center}
   712 
   711 
   713   Hint: Be careful with recursive parsers.
   712   Hint: Be careful with recursive parsers.
   714   \end{exercise}
   713   \end{exercise}
   715 *}
   714 \<close>
   716 
   715 
   717 section {* Parsers for ML-Code (TBD) *}
   716 section \<open>Parsers for ML-Code (TBD)\<close>
   718 
   717 
   719 text {*
   718 text \<open>
   720   @{ML_ind ML_source in Parse}
   719   @{ML_ind ML_source in Parse}
   721 *}
   720 \<close>
   722 
   721 
   723 section {* Context Parser (TBD) *}
   722 section \<open>Context Parser (TBD)\<close>
   724 
   723 
   725 text {*
   724 text \<open>
   726   @{ML_ind Args.context}
   725   @{ML_ind Args.context}
   727 *}
   726 \<close>
   728 (*
   727 (*
   729 ML {*
   728 ML {*
   730 let
   729 let
   731    val parser = Args.context -- Scan.lift Args.name_inner_syntax
   730    val parser = Args.context -- Scan.lift Args.name_inner_syntax
   732    
   731    
   737   |> fst
   736   |> fst
   738 end
   737 end
   739 *}
   738 *}
   740 *)
   739 *)
   741 
   740 
   742 text {*
   741 text \<open>
   743   @{ML_ind Args.context}
   742   @{ML_ind Args.context}
   744 
   743 
   745   Used for example in \isacommand{attribute\_setup} and \isacommand{method\_setup}.
   744   Used for example in \isacommand{attribute\_setup} and \isacommand{method\_setup}.
   746 *}
   745 \<close>
   747 
   746 
   748 section {* Argument and Attribute Parsers (TBD) *}
   747 section \<open>Argument and Attribute Parsers (TBD)\<close>
   749 
   748 
   750 section {* Parsing Inner Syntax *}
   749 section \<open>Parsing Inner Syntax\<close>
   751 
   750 
   752 text {*
   751 text \<open>
   753   There is usually no need to write your own parser for parsing inner syntax, that is 
   752   There is usually no need to write your own parser for parsing inner syntax, that is 
   754   for terms and  types: you can just call the predefined parsers. Terms can 
   753   for terms and  types: you can just call the predefined parsers. Terms can 
   755   be parsed using the function @{ML_ind term in Parse}. For example:
   754   be parsed using the function @{ML_ind term in Parse}. For example:
   756 
   755 
   757 @{ML_response_fake [display,gray]
   756 @{ML_response_fake [display,gray]
   790   @{ML_ind parse_term in Syntax} @{ML_ind check_term in Syntax}
   789   @{ML_ind parse_term in Syntax} @{ML_ind check_term in Syntax}
   791   @{ML_ind parse_typ in Syntax} @{ML_ind check_typ in Syntax}
   790   @{ML_ind parse_typ in Syntax} @{ML_ind check_typ in Syntax}
   792   @{ML_ind read_term in Syntax} @{ML_ind read_term in Syntax}
   791   @{ML_ind read_term in Syntax} @{ML_ind read_term in Syntax}
   793 
   792 
   794 
   793 
   795 *}
   794 \<close>
   796 
   795 
   797 section {* Parsing Specifications\label{sec:parsingspecs} *}
   796 section \<open>Parsing Specifications\label{sec:parsingspecs}\<close>
   798 
   797 
   799 
   798 
   800 text {*
   799 text \<open>
   801   There are a number of special purpose parsers that help with parsing
   800   There are a number of special purpose parsers that help with parsing
   802   specifications of function definitions, inductive predicates and so on. In
   801   specifications of function definitions, inductive predicates and so on. In
   803   Chapter~\ref{chp:package}, for example, we will need to parse specifications
   802   Chapter~\ref{chp:package}, for example, we will need to parse specifications
   804   for inductive predicates of the form:
   803   for inductive predicates of the form:
   805 *}
   804 \<close>
   806 
   805 
   807 
   806 
   808 simple_inductive
   807 simple_inductive
   809   even and odd
   808   even and odd
   810 where
   809 where
   811   even0: "even 0"
   810   even0: "even 0"
   812 | evenS: "odd n \<Longrightarrow> even (Suc n)"
   811 | evenS: "odd n \<Longrightarrow> even (Suc n)"
   813 | oddS: "even n \<Longrightarrow> odd (Suc n)"
   812 | oddS: "even n \<Longrightarrow> odd (Suc n)"
   814 
   813 
   815 text {*
   814 text \<open>
   816   For this we are going to use the parser:
   815   For this we are going to use the parser:
   817 *}
   816 \<close>
   818 
   817 
   819 ML %linenosgray{*val spec_parser = 
   818 ML %linenosgray\<open>val spec_parser = 
   820      Parse.vars -- 
   819      Parse.vars -- 
   821      Scan.optional 
   820      Scan.optional 
   822        (Parse.$$$ "where" |--
   821        (Parse.$$$ "where" |--
   823           Parse.!!! 
   822           Parse.!!! 
   824             (Parse.enum1 "|" 
   823             (Parse.enum1 "|" 
   825                (Parse_Spec.opt_thm_name ":" -- Parse.prop))) []*}
   824                (Parse_Spec.opt_thm_name ":" -- Parse.prop))) []\<close>
   826 
   825 
   827 text {*
   826 text \<open>
   828   Note that the parser must not parse the keyword \simpleinductive, even if it is
   827   Note that the parser must not parse the keyword \simpleinductive, even if it is
   829   meant to process definitions as shown above. The parser of the keyword 
   828   meant to process definitions as shown above. The parser of the keyword 
   830   will be given by the infrastructure that will eventually call @{ML spec_parser}.
   829   will be given by the infrastructure that will eventually call @{ML spec_parser}.
   831   
   830   
   832 
   831 
   846 end"
   845 end"
   847 "(([(even, NONE, NoSyn), (odd, NONE, NoSyn)],
   846 "(([(even, NONE, NoSyn), (odd, NONE, NoSyn)],
   848    [((even0,\<dots>),\<dots>),
   847    [((even0,\<dots>),\<dots>),
   849     ((evenS,\<dots>),\<dots>),
   848     ((evenS,\<dots>),\<dots>),
   850     ((oddS,\<dots>),\<dots>)]), [])"}
   849     ((oddS,\<dots>),\<dots>)]), [])"}
   851 *}
   850 \<close>
   852 
   851 
   853 ML \<open>let
   852 ML \<open>let
   854   val input = filtered_input 
   853   val input = filtered_input 
   855         "foo::\"int \<Rightarrow> bool\" and bar::nat (\"BAR\" 100) and blonk"
   854         "foo::\"int \<Rightarrow> bool\" and bar::nat (\"BAR\" 100) and blonk"
   856 in
   855 in
   857   parse Parse.vars input
   856   parse Parse.vars input
   858 end\<close>
   857 end\<close>
   859 
   858 
   860 text {*
   859 text \<open>
   861   As you see, the result is a pair consisting of a list of
   860   As you see, the result is a pair consisting of a list of
   862   variables with optional type-annotation and syntax-annotation, and a list of
   861   variables with optional type-annotation and syntax-annotation, and a list of
   863   rules where every rule has optionally a name and an attribute.
   862   rules where every rule has optionally a name and an attribute.
   864 
   863 
   865   The function @{ML_ind "vars" in Parse} in Line 2 of the parser reads an 
   864   The function @{ML_ind "vars" in Parse} in Line 2 of the parser reads an 
   866   \isacommand{and}-separated 
   865   \isacommand{and}-separated 
   867   list of variables that can include optional type annotations and syntax translations. 
   866   list of variables that can include optional type annotations and syntax translations. 
   868   For example:\footnote{Note that in the code we need to write 
   867   For example:\footnote{Note that in the code we need to write 
   869   @{text "\\\"int \<Rightarrow> bool\\\""} in order to properly escape the double quotes
   868   \<open>\"int \<Rightarrow> bool\"\<close> in order to properly escape the double quotes
   870   in the compound type.}
   869   in the compound type.}
   871 
   870 
   872 @{ML_response_fake [display,gray]
   871 @{ML_response_fake [display,gray]
   873 "let
   872 "let
   874   val input = filtered_input 
   873   val input = filtered_input 
   877   parse Parse.vars input
   876   parse Parse.vars input
   878 end"
   877 end"
   879 "([(foo, SOME \<dots>, NoSyn), 
   878 "([(foo, SOME \<dots>, NoSyn), 
   880   (bar, SOME \<dots>, Mixfix (Source {text=\"BAR\",...}, [], 100, \<dots>)), 
   879   (bar, SOME \<dots>, Mixfix (Source {text=\"BAR\",...}, [], 100, \<dots>)), 
   881   (blonk, NONE, NoSyn)],[])"}  
   880   (blonk, NONE, NoSyn)],[])"}  
   882 *}
   881 \<close>
   883 
   882 
   884 text {*
   883 text \<open>
   885   Whenever types are given, they are stored in the @{ML SOME}s. The types are
   884   Whenever types are given, they are stored in the @{ML SOME}s. The types are
   886   not yet used to type the variables: this must be done by type-inference later
   885   not yet used to type the variables: this must be done by type-inference later
   887   on. Since types are part of the inner syntax they are strings with some
   886   on. Since types are part of the inner syntax they are strings with some
   888   encoded information (see previous section). If a mixfix-syntax is
   887   encoded information (see previous section). If a mixfix-syntax is
   889   present for a variable, then it is stored in the 
   888   present for a variable, then it is stored in the 
   914 
   913 
   915   \begin{readmore}
   914   \begin{readmore}
   916   Attributes and arguments are implemented in the files @{ML_file "Pure/Isar/attrib.ML"} 
   915   Attributes and arguments are implemented in the files @{ML_file "Pure/Isar/attrib.ML"} 
   917   and @{ML_file "Pure/Isar/args.ML"}.
   916   and @{ML_file "Pure/Isar/args.ML"}.
   918   \end{readmore}
   917   \end{readmore}
   919 *}
   918 \<close>
   920 
   919 
   921 text_raw {*
   920 text_raw \<open>
   922   \begin{exercise}
   921   \begin{exercise}
   923   Have a look at how the parser @{ML Parse_Spec.where_multi_specs} is implemented
   922   Have a look at how the parser @{ML Parse_Spec.where_multi_specs} is implemented
   924   in file @{ML_file "Pure/Isar/parse_spec.ML"}. This parser corresponds
   923   in file @{ML_file "Pure/Isar/parse_spec.ML"}. This parser corresponds
   925   to the ``where-part'' of the introduction rules given above. Below
   924   to the ``where-part'' of the introduction rules given above. Below
   926   we paraphrase the code of @{ML_ind where_multi_specs in Parse_Spec} adapted to our
   925   we paraphrase the code of @{ML_ind where_multi_specs in Parse_Spec} adapted to our
   927   purposes. 
   926   purposes. 
   928   \begin{isabelle}
   927   \begin{isabelle}
   929 *}
   928 \<close>
   930 ML %linenosgray{*val spec_parser' = 
   929 ML %linenosgray\<open>val spec_parser' = 
   931      Parse.vars -- 
   930      Parse.vars -- 
   932      Scan.optional
   931      Scan.optional
   933      (Parse.$$$ "where" |-- 
   932      (Parse.$$$ "where" |-- 
   934         Parse.!!! 
   933         Parse.!!! 
   935           (Parse.enum1 "|" 
   934           (Parse.enum1 "|" 
   936              ((Parse_Spec.opt_thm_name ":" -- Parse.prop) --| 
   935              ((Parse_Spec.opt_thm_name ":" -- Parse.prop) --| 
   937                   Scan.option (Scan.ahead (Parse.name || 
   936                   Scan.option (Scan.ahead (Parse.name || 
   938                   Parse.$$$ "[") -- 
   937                   Parse.$$$ "[") -- 
   939                   Parse.!!! (Parse.$$$ "|"))))) [] *}
   938                   Parse.!!! (Parse.$$$ "|"))))) []\<close>
   940 text_raw {*
   939 text_raw \<open>
   941   \end{isabelle}
   940   \end{isabelle}
   942   Both parsers accept the same input% that's not true:
   941   Both parsers accept the same input% that's not true:
   943   % spec_parser accepts input that is refuted by spec_parser'
   942   % spec_parser accepts input that is refuted by spec_parser'
   944   , but if you look closely, you can notice 
   943   , but if you look closely, you can notice 
   945   an additional  ``tail'' (Lines 8 to 10) in @{ML spec_parser'}. What is the purpose of 
   944   an additional  ``tail'' (Lines 8 to 10) in @{ML spec_parser'}. What is the purpose of 
   946   this additional ``tail''?
   945   this additional ``tail''?
   947   \end{exercise}
   946   \end{exercise}
   948 *}
   947 \<close>
   949 
   948 
   950 text {*
   949 text \<open>
   951   (FIXME: @{ML Parse.type_args}, @{ML Parse.typ}, @{ML Parse.opt_mixfix})
   950   (FIXME: @{ML Parse.type_args}, @{ML Parse.typ}, @{ML Parse.opt_mixfix})
   952 *}
   951 \<close>
   953 
   952 
   954 
   953 
   955 section {* New Commands\label{sec:newcommand} *}
   954 section \<open>New Commands\label{sec:newcommand}\<close>
   956 
   955 
   957 text {*
   956 text \<open>
   958   Often new commands, for example for providing new definitional principles,
   957   Often new commands, for example for providing new definitional principles,
   959   need to be implemented. While this is not difficult on the ML-level and for
   958   need to be implemented. While this is not difficult on the ML-level and for
   960   jEdit, in order to be backwards compatible, new commands need also to be recognised 
   959   jEdit, in order to be backwards compatible, new commands need also to be recognised 
   961   by Proof-General. This results in some subtle configuration issues, which we will 
   960   by Proof-General. This results in some subtle configuration issues, which we will 
   962   explain in the next section. Here we just describe how to define new commands
   961   explain in the next section. Here we just describe how to define new commands
   967   implement any new command, you have to ``announce'' it in the
   966   implement any new command, you have to ``announce'' it in the
   968   \isacommand{keywords}-section of your theory header. For \isacommand{foobar}
   967   \isacommand{keywords}-section of your theory header. For \isacommand{foobar}
   969   we need to write something like
   968   we need to write something like
   970 
   969 
   971   \begin{graybox}
   970   \begin{graybox}
   972   \isacommand{theory}~@{text Foo}\\
   971   \isacommand{theory}~\<open>Foo\<close>\\
   973   \isacommand{imports}~@{text Main}\\
   972   \isacommand{imports}~\<open>Main\<close>\\
   974   \isacommand{keywords} @{text [quotes] "foobar"} @{text "::"} @{text "thy_decl"}\\
   973   \isacommand{keywords} @{text [quotes] "foobar"} \<open>::\<close> \<open>thy_decl\<close>\\
   975   ...
   974   ...
   976   \end{graybox}
   975   \end{graybox}
   977 
   976 
   978   where @{ML_ind "thy_decl" in Keyword} indicates the kind of the
   977   where @{ML_ind "thy_decl" in Keyword} indicates the kind of the
   979   command.  Another possible kind is @{text "thy_goal"}, or you can
   978   command.  Another possible kind is \<open>thy_goal\<close>, or you can
   980   also omit the kind entirely, in which case you declare a keyword
   979   also omit the kind entirely, in which case you declare a keyword
   981   (something that is part of a command).
   980   (something that is part of a command).
   982 
   981 
   983   Now you can implement \isacommand{foobar} as follows.
   982   Now you can implement \isacommand{foobar} as follows.
   984 *}
   983 \<close>
   985 
   984 
   986 ML %grayML{*let
   985 ML %grayML\<open>let
   987   val do_nothing = Scan.succeed (Local_Theory.background_theory I)
   986   val do_nothing = Scan.succeed (Local_Theory.background_theory I)
   988 in
   987 in
   989   Outer_Syntax.local_theory @{command_keyword "foobar"} 
   988   Outer_Syntax.local_theory @{command_keyword "foobar"} 
   990     "description of foobar" 
   989     "description of foobar" 
   991       do_nothing
   990       do_nothing
   992 end *}
   991 end\<close>
   993 
   992 
   994 text {*
   993 text \<open>
   995   The crucial function @{ML_ind local_theory in Outer_Syntax} expects
   994   The crucial function @{ML_ind local_theory in Outer_Syntax} expects
   996   the name for the command, a kind indicator, a short description and 
   995   the name for the command, a kind indicator, a short description and 
   997   a parser producing a local theory transition (explained later). For the
   996   a parser producing a local theory transition (explained later). For the
   998   name and the kind, you can use the ML-antiquotation @{text "@{command_spec ...}"}.
   997   name and the kind, you can use the ML-antiquotation \<open>@{command_spec ...}\<close>.
   999   You can now write in your theory 
   998   You can now write in your theory 
  1000 *}
   999 \<close>
  1001 
  1000 
  1002 foobar
  1001 foobar
  1003 
  1002 
  1004 text {*
  1003 text \<open>
  1005   but of course you will not see anything since \isacommand{foobar} is
  1004   but of course you will not see anything since \isacommand{foobar} is
  1006   not intended to do anything.  Remember, however, that this only
  1005   not intended to do anything.  Remember, however, that this only
  1007   works in jEdit. In order to enable also Proof-General recognise this
  1006   works in jEdit. In order to enable also Proof-General recognise this
  1008   command, a keyword file needs to be generated (see next section).
  1007   command, a keyword file needs to be generated (see next section).
  1009 
  1008 
  1011   us refine it a bit next by letting it take a proposition as argument
  1010   us refine it a bit next by letting it take a proposition as argument
  1012   and printing this proposition inside the tracing buffer. We announce
  1011   and printing this proposition inside the tracing buffer. We announce
  1013   the command \isacommand{foobar\_trace} in the theory header as
  1012   the command \isacommand{foobar\_trace} in the theory header as
  1014 
  1013 
  1015   \begin{graybox}
  1014   \begin{graybox}
  1016   \isacommand{keywords} @{text [quotes] "foobar_trace"} @{text "::"} @{text "thy_decl"}
  1015   \isacommand{keywords} @{text [quotes] "foobar_trace"} \<open>::\<close> \<open>thy_decl\<close>
  1017   \end{graybox}
  1016   \end{graybox}
  1018 
  1017 
  1019   The crucial part of a command is the function that determines the
  1018   The crucial part of a command is the function that determines the
  1020   behaviour of the command. In the code above we used a
  1019   behaviour of the command. In the code above we used a
  1021   ``do-nothing''-function, which because of the parser @{ML_ind succeed in Scan}
  1020   ``do-nothing''-function, which because of the parser @{ML_ind succeed in Scan}
  1022   does not parse any argument, but immediately returns the simple
  1021   does not parse any argument, but immediately returns the simple
  1023   function @{ML "Local_Theory.background_theory I"}. We can replace
  1022   function @{ML "Local_Theory.background_theory I"}. We can replace
  1024   this code by a function that first parses a proposition (using the
  1023   this code by a function that first parses a proposition (using the
  1025   parser @{ML Parse.prop}), then prints out some tracing information
  1024   parser @{ML Parse.prop}), then prints out some tracing information
  1026   (using the function @{text trace_prop}) and finally does
  1025   (using the function \<open>trace_prop\<close>) and finally does
  1027   nothing. For this you can write:
  1026   nothing. For this you can write:
  1028 *}
  1027 \<close>
  1029 
  1028 
  1030 ML %grayML{*let
  1029 ML %grayML\<open>let
  1031   fun trace_prop str = 
  1030   fun trace_prop str = 
  1032     Local_Theory.background_theory (fn ctxt => (tracing str; ctxt))
  1031     Local_Theory.background_theory (fn ctxt => (tracing str; ctxt))
  1033 in
  1032 in
  1034   Outer_Syntax.local_theory @{command_keyword "foobar_trace"} 
  1033   Outer_Syntax.local_theory @{command_keyword "foobar_trace"} 
  1035     "traces a proposition" 
  1034     "traces a proposition" 
  1036       (Parse.prop >> trace_prop)
  1035       (Parse.prop >> trace_prop)
  1037 end *}
  1036 end\<close>
  1038 
  1037 
  1039 text {*
  1038 text \<open>
  1040   This command can now be used to 
  1039   This command can now be used to 
  1041   see the proposition in the tracing buffer.
  1040   see the proposition in the tracing buffer.
  1042 *}
  1041 \<close>
  1043 
  1042 
  1044 foobar_trace "True \<and> False"
  1043 foobar_trace "True \<and> False"
  1045 
  1044 
  1046 text {*
  1045 text \<open>
  1047   Note that so far we used @{ML_ind thy_decl in Keyword} as the kind
  1046   Note that so far we used @{ML_ind thy_decl in Keyword} as the kind
  1048   indicator for the new command.  This means that the command finishes as soon as
  1047   indicator for the new command.  This means that the command finishes as soon as
  1049   the arguments are processed. Examples of this kind of commands are
  1048   the arguments are processed. Examples of this kind of commands are
  1050   \isacommand{definition} and \isacommand{declare}.  In other cases, commands
  1049   \isacommand{definition} and \isacommand{declare}.  In other cases, commands
  1051   are expected to parse some arguments, for example a proposition, and then
  1050   are expected to parse some arguments, for example a proposition, and then
  1055   the kind indicator @{ML_ind thy_goal in Keyword} and the function @{ML
  1054   the kind indicator @{ML_ind thy_goal in Keyword} and the function @{ML
  1056   "local_theory_to_proof" in Outer_Syntax} to set up the command. 
  1055   "local_theory_to_proof" in Outer_Syntax} to set up the command. 
  1057   Below we show the command \isacommand{foobar\_goal} which takes a
  1056   Below we show the command \isacommand{foobar\_goal} which takes a
  1058   proposition as argument and then starts a proof in order to prove
  1057   proposition as argument and then starts a proof in order to prove
  1059   it. Therefore, we need to announce this command in the header 
  1058   it. Therefore, we need to announce this command in the header 
  1060   as @{text "thy_goal"}.
  1059   as \<open>thy_goal\<close>.
  1061 
  1060 
  1062   \begin{graybox}
  1061   \begin{graybox}
  1063   \isacommand{keywords} @{text [quotes] "foobar_goal"} @{text "::"} @{text "thy_goal"}
  1062   \isacommand{keywords} @{text [quotes] "foobar_goal"} \<open>::\<close> \<open>thy_goal\<close>
  1064   \end{graybox}
  1063   \end{graybox}
  1065 
  1064 
  1066   Then we can write:
  1065   Then we can write:
  1067 *}
  1066 \<close>
  1068 
  1067 
  1069 ML%linenosgray{*let
  1068 ML%linenosgray\<open>let
  1070   fun goal_prop str ctxt =
  1069   fun goal_prop str ctxt =
  1071     let
  1070     let
  1072       val prop = Syntax.read_prop ctxt str
  1071       val prop = Syntax.read_prop ctxt str
  1073     in
  1072     in
  1074       Proof.theorem NONE (K I) [[(prop, [])]] ctxt
  1073       Proof.theorem NONE (K I) [[(prop, [])]] ctxt
  1075     end
  1074     end
  1076 in
  1075 in
  1077   Outer_Syntax.local_theory_to_proof @{command_keyword "foobar_goal"}
  1076   Outer_Syntax.local_theory_to_proof @{command_keyword "foobar_goal"}
  1078     "proves a proposition" 
  1077     "proves a proposition" 
  1079       (Parse.prop >> goal_prop)
  1078       (Parse.prop >> goal_prop)
  1080 end *}
  1079 end\<close>
  1081 
  1080 
  1082 text {*
  1081 text \<open>
  1083   The function @{text goal_prop} in Lines 2 to 7 takes a string (the proposition to be
  1082   The function \<open>goal_prop\<close> in Lines 2 to 7 takes a string (the proposition to be
  1084   proved) and a context as argument.  The context is necessary in order to be able to use
  1083   proved) and a context as argument.  The context is necessary in order to be able to use
  1085   @{ML_ind read_prop in Syntax}, which converts a string into a proper proposition.
  1084   @{ML_ind read_prop in Syntax}, which converts a string into a proper proposition.
  1086   In Line 6 the function @{ML_ind theorem in Proof} starts the proof for the
  1085   In Line 6 the function @{ML_ind theorem in Proof} starts the proof for the
  1087   proposition. Its argument @{ML NONE} stands for a locale (which we chose to
  1086   proposition. Its argument @{ML NONE} stands for a locale (which we chose to
  1088   omit); the argument @{ML "(K I)"} stands for a function that determines what
  1087   omit); the argument @{ML "(K I)"} stands for a function that determines what
  1089   should be done with the theorem once it is proved (we chose to just forget
  1088   should be done with the theorem once it is proved (we chose to just forget
  1090   about it). 
  1089   about it). 
  1091 
  1090 
  1092   If you now type \isacommand{foobar\_goal}~@{text [quotes] "True \<and> True"},
  1091   If you now type \isacommand{foobar\_goal}~@{text [quotes] "True \<and> True"},
  1093   you obtain the following proof state:
  1092   you obtain the following proof state:
  1094 *}
  1093 \<close>
  1095 
  1094 
  1096 foobar_goal "True \<and> True"
  1095 foobar_goal "True \<and> True"
  1097 txt {*
  1096 txt \<open>
  1098   \begin{minipage}{\textwidth}
  1097   \begin{minipage}{\textwidth}
  1099   @{subgoals [display]}
  1098   @{subgoals [display]}
  1100   \end{minipage}\medskip
  1099   \end{minipage}\medskip
  1101 
  1100 
  1102   and can prove the proposition as follows.
  1101   and can prove the proposition as follows.
  1103 *}
  1102 \<close>
  1104 apply(rule conjI)
  1103 apply(rule conjI)
  1105 apply(rule TrueI)+
  1104 apply(rule TrueI)+
  1106 done
  1105 done
  1107 
  1106 
  1108 text {*
  1107 text \<open>
  1109   The last command we describe here is
  1108   The last command we describe here is
  1110   \isacommand{foobar\_proof}. Like \isacommand{foobar\_goal}, its purpose is
  1109   \isacommand{foobar\_proof}. Like \isacommand{foobar\_goal}, its purpose is
  1111   to take a proposition and open a corresponding proof-state that
  1110   to take a proposition and open a corresponding proof-state that
  1112   allows us to give a proof for it. However, unlike
  1111   allows us to give a proof for it. However, unlike
  1113   \isacommand{foobar\_goal}, the proposition will be given as a
  1112   \isacommand{foobar\_goal}, the proposition will be given as a
  1120   text as ML-source and then interpret it as an Isabelle term using
  1119   text as ML-source and then interpret it as an Isabelle term using
  1121   the ML-runtime.  For the parsing part, we can use the function
  1120   the ML-runtime.  For the parsing part, we can use the function
  1122   @{ML_ind "ML_source" in Parse} in the structure @{ML_struct
  1121   @{ML_ind "ML_source" in Parse} in the structure @{ML_struct
  1123   Parse}. For running the ML-interpreter we need the following
  1122   Parse}. For running the ML-interpreter we need the following
  1124   scaffolding code.
  1123   scaffolding code.
  1125 *}
  1124 \<close>
  1126 
  1125 
  1127 ML %grayML{*
  1126 ML %grayML\<open>
  1128 structure Result = Proof_Data 
  1127 structure Result = Proof_Data 
  1129   (type T = unit -> term
  1128   (type T = unit -> term
  1130    fun init thy () = error "Result")
  1129    fun init thy () = error "Result")
  1131 
  1130 
  1132 val result_cookie = (Result.get, Result.put, "Result.put") *}
  1131 val result_cookie = (Result.get, Result.put, "Result.put")\<close>
  1133 
  1132 
  1134 text {*
  1133 text \<open>
  1135   With this in place, we can implement the code for \isacommand{foobar\_prove} 
  1134   With this in place, we can implement the code for \isacommand{foobar\_prove} 
  1136   as follows.
  1135   as follows.
  1137 *}
  1136 \<close>
  1138 
  1137 
  1139 ML %linenosgray{*let
  1138 ML %linenosgray\<open>let
  1140    fun after_qed thm_name thms lthy =
  1139    fun after_qed thm_name thms lthy =
  1141         Local_Theory.note (thm_name, (flat thms)) lthy |> snd
  1140         Local_Theory.note (thm_name, (flat thms)) lthy |> snd
  1142 
  1141 
  1143    fun setup_proof (thm_name, src) lthy =
  1142    fun setup_proof (thm_name, src) lthy =
  1144      let
  1143      let
  1151    val parser = Parse_Spec.opt_thm_name ":" -- Parse.ML_source
  1150    val parser = Parse_Spec.opt_thm_name ":" -- Parse.ML_source
  1152 in
  1151 in
  1153    Outer_Syntax.local_theory_to_proof @{command_keyword "foobar_prove"}
  1152    Outer_Syntax.local_theory_to_proof @{command_keyword "foobar_prove"}
  1154      "proving a proposition" 
  1153      "proving a proposition" 
  1155        (parser >> setup_proof)
  1154        (parser >> setup_proof)
  1156 end*}
  1155 end\<close>
  1157 
  1156 
  1158 text {*
  1157 text \<open>
  1159   In Line 12, we implement a parser that first reads in an optional lemma name (terminated 
  1158   In Line 12, we implement a parser that first reads in an optional lemma name (terminated 
  1160   by ``:'') and then some ML-code. The function in Lines 5 to 10 takes the ML-text
  1159   by ``:'') and then some ML-code. The function in Lines 5 to 10 takes the ML-text
  1161   and lets the ML-runtime evaluate it using the function @{ML_ind value in Code_Runtime}
  1160   and lets the ML-runtime evaluate it using the function @{ML_ind value in Code_Runtime}
  1162   in the structure @{ML_struct Code_Runtime}.  Once the ML-text has been turned into a term, 
  1161   in the structure @{ML_struct Code_Runtime}.  Once the ML-text has been turned into a term, 
  1163   the function @{ML theorem in Proof} opens a corresponding proof-state. This function takes the
  1162   the function @{ML theorem in Proof} opens a corresponding proof-state. This function takes the
  1164   function @{text "after_qed"} as argument, whose purpose is to store the theorem
  1163   function \<open>after_qed\<close> as argument, whose purpose is to store the theorem
  1165   (once it is proven) under the given name @{text "thm_name"}.
  1164   (once it is proven) under the given name \<open>thm_name\<close>.
  1166 
  1165 
  1167   You can now define a term, for example
  1166   You can now define a term, for example
  1168 *}
  1167 \<close>
  1169 
  1168 
  1170 ML %grayML{*val prop_true = @{prop "True"}*}
  1169 ML %grayML\<open>val prop_true = @{prop "True"}\<close>
  1171 
  1170 
  1172 text {*
  1171 text \<open>
  1173   and give it a proof using \isacommand{foobar\_prove}:
  1172   and give it a proof using \isacommand{foobar\_prove}:
  1174 *}
  1173 \<close>
  1175 
  1174 
  1176 foobar_prove test: prop_true
  1175 foobar_prove test: prop_true
  1177 apply(rule TrueI)
  1176 apply(rule TrueI)
  1178 done
  1177 done
  1179 
  1178 
  1180 text {*
  1179 text \<open>
  1181   Finally you can test whether the lemma has been stored under the given name.
  1180   Finally you can test whether the lemma has been stored under the given name.
  1182   
  1181   
  1183   \begin{isabelle}
  1182   \begin{isabelle}
  1184   \isacommand{thm}~@{text "test"}\\
  1183   \isacommand{thm}~\<open>test\<close>\\
  1185   @{text "> "}~@{thm TrueI}
  1184   \<open>> \<close>~@{thm TrueI}
  1186   \end{isabelle}
  1185   \end{isabelle}
  1187 
  1186 
  1188 *}
  1187 \<close>
  1189 
  1188 
  1190 
  1189 
  1191 (*
  1190 (*
  1192 text {*
  1191 text {*
  1193   {\bf TBD below}
  1192   {\bf TBD below}
  1322 ML {*
  1321 ML {*
  1323 Context.set_thread_data (SOME (let fun tactic (facts: thm list) : tactic =  (atac 1)   in Context.map_proof (Method.set_tactic tactic) end (ML_Context.the_generic_context ())));
  1322 Context.set_thread_data (SOME (let fun tactic (facts: thm list) : tactic =  (atac 1)   in Context.map_proof (Method.set_tactic tactic) end (ML_Context.the_generic_context ())));
  1324 *}
  1323 *}
  1325 *)
  1324 *)
  1326 
  1325 
  1327 section {* Methods (TBD) *}
  1326 section \<open>Methods (TBD)\<close>
  1328 
  1327 
  1329 text {*
  1328 text \<open>
  1330   (FIXME: maybe move to after the tactic section)
  1329   (FIXME: maybe move to after the tactic section)
  1331 
  1330 
  1332   Methods are central to Isabelle. You use them, for example,
  1331   Methods are central to Isabelle. You use them, for example,
  1333   in \isacommand{apply}. To print out all currently known methods you can use the 
  1332   in \isacommand{apply}. To print out all currently known methods you can use the 
  1334   Isabelle command:
  1333   Isabelle command:
  1335 
  1334 
  1336   \begin{isabelle}
  1335   \begin{isabelle}
  1337   \isacommand{print\_methods}\\
  1336   \isacommand{print\_methods}\\
  1338   @{text "> methods:"}\\
  1337   \<open>> methods:\<close>\\
  1339   @{text ">   -:  do nothing (insert current facts only)"}\\
  1338   \<open>>   -:  do nothing (insert current facts only)\<close>\\
  1340   @{text ">   HOL.default:  apply some intro/elim rule (potentially classical)"}\\
  1339   \<open>>   HOL.default:  apply some intro/elim rule (potentially classical)\<close>\\
  1341   @{text ">   ..."}
  1340   \<open>>   ...\<close>
  1342   \end{isabelle}
  1341   \end{isabelle}
  1343 
  1342 
  1344   An example of a very simple method is:
  1343   An example of a very simple method is:
  1345 *}
  1344 \<close>
  1346 
  1345 
  1347 method_setup %gray foo = 
  1346 method_setup %gray foo = 
  1348  {* Scan.succeed
  1347  \<open>Scan.succeed
  1349       (fn ctxt => (SIMPLE_METHOD ((eresolve_tac ctxt [@{thm conjE}] THEN' resolve_tac ctxt [@{thm conjI}]) 1))) *}
  1348       (fn ctxt => (SIMPLE_METHOD ((eresolve_tac ctxt [@{thm conjE}] THEN' resolve_tac ctxt [@{thm conjI}]) 1)))\<close>
  1350          "foo method for conjE and conjI"
  1349          "foo method for conjE and conjI"
  1351 
  1350 
  1352 text {*
  1351 text \<open>
  1353   It defines the method @{text foo}, which takes no arguments (therefore the
  1352   It defines the method \<open>foo\<close>, which takes no arguments (therefore the
  1354   parser @{ML Scan.succeed}) and only applies a single tactic, namely the tactic which 
  1353   parser @{ML Scan.succeed}) and only applies a single tactic, namely the tactic which 
  1355   applies @{thm [source] conjE} and then @{thm [source] conjI}. The function 
  1354   applies @{thm [source] conjE} and then @{thm [source] conjI}. The function 
  1356   @{ML_ind SIMPLE_METHOD in Method}
  1355   @{ML_ind SIMPLE_METHOD in Method}
  1357   turns such a tactic into a method. The method @{text "foo"} can be used as follows
  1356   turns such a tactic into a method. The method \<open>foo\<close> can be used as follows
  1358 *}
  1357 \<close>
  1359 
  1358 
  1360 lemma shows "A \<and> B \<Longrightarrow> C \<and> D"
  1359 lemma shows "A \<and> B \<Longrightarrow> C \<and> D"
  1361 apply(foo)
  1360 apply(foo)
  1362 txt {*
  1361 txt \<open>
  1363   where it results in the goal state
  1362   where it results in the goal state
  1364 
  1363 
  1365   \begin{minipage}{\textwidth}
  1364   \begin{minipage}{\textwidth}
  1366   @{subgoals}
  1365   @{subgoals}
  1367   \end{minipage} *}
  1366   \end{minipage}\<close>
  1368 (*<*)oops(*>*)
  1367 (*<*)oops(*>*)
  1369 
  1368 
  1370 method_setup test = {* 
  1369 method_setup test = \<open>
  1371   Scan.lift (Scan.succeed (K Method.succeed)) *} {* bla *}
  1370   Scan.lift (Scan.succeed (K Method.succeed))\<close> \<open>bla\<close>
  1372 
  1371 
  1373 lemma "True"
  1372 lemma "True"
  1374 apply(test)
  1373 apply(test)
  1375 oops
  1374 oops
  1376 
  1375 
  1377 method_setup joker = {* 
  1376 method_setup joker = \<open>
  1378   Scan.lift (Scan.succeed (fn ctxt => Method.cheating true)) *} {* bla *}
  1377   Scan.lift (Scan.succeed (fn ctxt => Method.cheating true))\<close> \<open>bla\<close>
  1379 
  1378 
  1380 lemma "False"
  1379 lemma "False"
  1381 apply(joker)
  1380 apply(joker)
  1382 oops
  1381 oops
  1383 
  1382 
  1384 text {* if true is set then always works *}
  1383 text \<open>if true is set then always works\<close>
  1385 
  1384 
  1386 ML {* assume_tac *} 
  1385 ML \<open>assume_tac\<close> 
  1387 
  1386 
  1388 method_setup first_atac = {* Scan.lift (Scan.succeed (fn ctxt => (SIMPLE_METHOD (assume_tac ctxt 1)))) *} {* bla *}
  1387 method_setup first_atac = \<open>Scan.lift (Scan.succeed (fn ctxt => (SIMPLE_METHOD (assume_tac ctxt 1))))\<close> \<open>bla\<close>
  1389 
  1388 
  1390 ML {* HEADGOAL *}
  1389 ML \<open>HEADGOAL\<close>
  1391 
  1390 
  1392 lemma "A \<Longrightarrow> A"
  1391 lemma "A \<Longrightarrow> A"
  1393 apply(first_atac)
  1392 apply(first_atac)
  1394 oops
  1393 oops
  1395 
  1394 
  1396 method_setup my_atac = {* Scan.lift (Scan.succeed (fn ctxt => (SIMPLE_METHOD' (assume_tac ctxt)))) *} {* bla *}
  1395 method_setup my_atac = \<open>Scan.lift (Scan.succeed (fn ctxt => (SIMPLE_METHOD' (assume_tac ctxt))))\<close> \<open>bla\<close>
  1397 
  1396 
  1398 lemma "A \<Longrightarrow> A"
  1397 lemma "A \<Longrightarrow> A"
  1399 apply(my_atac)
  1398 apply(my_atac)
  1400 oops
  1399 oops
  1401 
  1400 
  1410 ML {* METHOD *}
  1409 ML {* METHOD *}
  1411 ML {* K (SIMPLE_METHOD ((etac @{thm conjE} THEN' rtac @{thm conjI}) 1)) *}
  1410 ML {* K (SIMPLE_METHOD ((etac @{thm conjE} THEN' rtac @{thm conjI}) 1)) *}
  1412 ML {* Scan.succeed  *}
  1411 ML {* Scan.succeed  *}
  1413 *)
  1412 *)
  1414 
  1413 
  1415 ML {* resolve_tac *}
  1414 ML \<open>resolve_tac\<close>
  1416 
  1415 
  1417 method_setup myrule =
  1416 method_setup myrule =
  1418   {* Scan.lift (Scan.succeed (fn ctxt => (METHOD (fn thms => resolve_tac ctxt thms 1)))) *}
  1417   \<open>Scan.lift (Scan.succeed (fn ctxt => (METHOD (fn thms => resolve_tac ctxt thms 1))))\<close>
  1419   {* bla *}
  1418   \<open>bla\<close>
  1420 
  1419 
  1421 lemma
  1420 lemma
  1422   assumes a: "A \<Longrightarrow> B \<Longrightarrow> C"
  1421   assumes a: "A \<Longrightarrow> B \<Longrightarrow> C"
  1423   shows "C"
  1422   shows "C"
  1424 using a
  1423 using a
  1425 apply(myrule)
  1424 apply(myrule)
  1426 oops
  1425 oops
  1427 
  1426 
  1428 
  1427 
  1429 
  1428 
  1430 text {*
  1429 text \<open>
  1431   (********************************************************)
  1430   (********************************************************)
  1432   (FIXME: explain a version of rule-tac)
  1431   (FIXME: explain a version of rule-tac)
  1433 *}
  1432 \<close>
  1434 
  1433 
  1435 end
  1434 end