ProgTutorial/Parsing.thy
changeset 222 1dc03eaa7cb9
parent 221 a9eb69749c93
parent 219 98d43270024f
child 227 a00c7721fc3b
equal deleted inserted replaced
221:a9eb69749c93 222:1dc03eaa7cb9
   193   @{ML "Scan.error"}. For example:
   193   @{ML "Scan.error"}. For example:
   194 
   194 
   195   @{ML_response_fake [display,gray] "Scan.error (!! (fn _ => \"foo\") ($$ \"h\"))"
   195   @{ML_response_fake [display,gray] "Scan.error (!! (fn _ => \"foo\") ($$ \"h\"))"
   196                                "Exception Error \"foo\" raised"}
   196                                "Exception Error \"foo\" raised"}
   197 
   197 
   198   This ``prefixing'' is usually done by wrappers such as @{ML "OuterSyntax.command"} 
   198   This ``prefixing'' is usually done by wrappers such as @{ML "OuterSyntax.local_theory"} 
   199   (see Section~\ref{sec:newcommand} which explains this function in more detail). 
   199   (see Section~\ref{sec:newcommand} which explains this function in more detail). 
   200   
   200   
   201   Let us now return to our example of parsing @{ML "(p -- q) || r" for p q
   201   Let us now return to our example of parsing @{ML "(p -- q) || r" for p q
   202   r}. If you want to generate the correct error message for p-followed-by-q,
   202   r}. If you want to generate the correct error message for p-followed-by-q,
   203   then you have to write:
   203   then you have to write:
   348 *}
   348 *}
   349 
   349 
   350 section {* Parsing Theory Syntax *}
   350 section {* Parsing Theory Syntax *}
   351 
   351 
   352 text {*
   352 text {*
   353   (FIXME: context parser)
       
   354 
       
   355   Most of the time, however, Isabelle developers have to deal with parsing
   353   Most of the time, however, Isabelle developers have to deal with parsing
   356   tokens, not strings.  These token parsers have the type:
   354   tokens, not strings.  These token parsers have the type:
   357 *}
   355 *}
   358   
   356   
   359 ML{*type 'a parser = OuterLex.token list -> 'a * OuterLex.token list*}
   357 ML{*type 'a parser = OuterLex.token list -> 'a * OuterLex.token list*}
   618   specifications of function definitions, inductive predicates and so on. In
   616   specifications of function definitions, inductive predicates and so on. In
   619   Chapter~\ref{chp:package}, for example, we will need to parse specifications
   617   Chapter~\ref{chp:package}, for example, we will need to parse specifications
   620   for inductive predicates of the form:
   618   for inductive predicates of the form:
   621 *}
   619 *}
   622 
   620 
       
   621 (*
   623 simple_inductive
   622 simple_inductive
   624   even and odd
   623   even and odd
   625 where
   624 where
   626   even0: "even 0"
   625   even0: "even 0"
   627 | evenS: "odd n \<Longrightarrow> even (Suc n)"
   626 | evenS: "odd n \<Longrightarrow> even (Suc n)"
   628 | oddS: "even n \<Longrightarrow> odd (Suc n)"
   627 | oddS: "even n \<Longrightarrow> odd (Suc n)"
       
   628 *)
   629 
   629 
   630 text {*
   630 text {*
   631   For this we are going to use the parser:
   631   For this we are going to use the parser:
   632 *}
   632 *}
   633 
   633 
   678 @{ML_response [display,gray]
   678 @{ML_response [display,gray]
   679 "let
   679 "let
   680   val input = filtered_input 
   680   val input = filtered_input 
   681         \"foo::\\\"int \<Rightarrow> bool\\\" and bar::nat (\\\"BAR\\\" 100) and blonk\"
   681         \"foo::\\\"int \<Rightarrow> bool\\\" and bar::nat (\\\"BAR\\\" 100) and blonk\"
   682 in
   682 in
   683    parse OuterParse.fixes input
   683   parse OuterParse.fixes input
   684 end"
   684 end"
   685 "([(foo, SOME \"\\^E\\^Ftoken\\^Eint \<Rightarrow> bool\\^E\\^F\\^E\", NoSyn), 
   685 "([(foo, SOME \"\\^E\\^Ftoken\\^Eint \<Rightarrow> bool\\^E\\^F\\^E\", NoSyn), 
   686   (bar, SOME \"\\^E\\^Ftoken\\^Enat\\^E\\^F\\^E\", Mixfix (\"BAR\", [], 100)), 
   686   (bar, SOME \"\\^E\\^Ftoken\\^Enat\\^E\\^F\\^E\", Mixfix (\"BAR\", [], 100)), 
   687   (blonk, NONE, NoSyn)],[])"}  
   687   (blonk, NONE, NoSyn)],[])"}  
   688 *}
   688 *}
   698   \begin{readmore}
   698   \begin{readmore}
   699   The data structure for syntax annotations is defined in @{ML_file "Pure/Syntax/mixfix.ML"}.
   699   The data structure for syntax annotations is defined in @{ML_file "Pure/Syntax/mixfix.ML"}.
   700   \end{readmore}
   700   \end{readmore}
   701 
   701 
   702   Lines 3 to 7 in the function @{ML spec_parser} implement the parser for a
   702   Lines 3 to 7 in the function @{ML spec_parser} implement the parser for a
   703   list of introduction rules, that is propositions with theorem
   703   list of introduction rules, that is propositions with theorem annotations
   704   annotations. The introduction rules are propositions parsed by @{ML
   704   such as rule names and attributes. The introduction rules are propositions
   705   OuterParse.prop}. However, they can include an optional theorem name plus
   705   parsed by @{ML OuterParse.prop}. However, they can include an optional
   706   some attributes. For example
   706   theorem name plus some attributes. For example
   707 
   707 
   708 @{ML_response [display,gray] "let 
   708 @{ML_response [display,gray] "let 
   709   val input = filtered_input \"foo_lemma[intro,dest!]:\"
   709   val input = filtered_input \"foo_lemma[intro,dest!]:\"
   710   val ((name, attrib), _) = parse (SpecParse.thm_name \":\") input 
   710   val ((name, attrib), _) = parse (SpecParse.thm_name \":\") input 
   711 in 
   711 in 
   751 *}
   751 *}
   752 
   752 
   753 section {* New Commands and Keyword Files\label{sec:newcommand} *}
   753 section {* New Commands and Keyword Files\label{sec:newcommand} *}
   754 
   754 
   755 text {*
   755 text {*
   756   (FIXME: update to the right command setup --- is this still needed?)
       
   757 
       
   758   Often new commands, for example for providing new definitional principles,
   756   Often new commands, for example for providing new definitional principles,
   759   need to be implemented. While this is not difficult on the ML-level,
   757   need to be implemented. While this is not difficult on the ML-level,
   760   new commands, in order to be useful, need to be recognised by
   758   new commands, in order to be useful, need to be recognised by
   761   ProofGeneral. This results in some subtle configuration issues, which we
   759   ProofGeneral. This results in some subtle configuration issues, which we
   762   will explain in this section.
   760   will explain in this section.
   765   at all. We shall name this command \isacommand{foobar}. On the ML-level it can be 
   763   at all. We shall name this command \isacommand{foobar}. On the ML-level it can be 
   766   defined as:
   764   defined as:
   767 *}
   765 *}
   768 
   766 
   769 ML{*let
   767 ML{*let
   770   val do_nothing = Scan.succeed (Toplevel.theory I)
   768   val do_nothing = Scan.succeed (LocalTheory.theory I)
   771   val kind = OuterKeyword.thy_decl
   769   val kind = OuterKeyword.thy_decl
   772 in
   770 in
   773   OuterSyntax.command "foobar" "description of foobar" kind do_nothing
   771   OuterSyntax.local_theory "foobar" "description of foobar" kind do_nothing
   774 end *}
   772 end *}
   775 
   773 
   776 text {*
   774 text {*
   777   The crucial function @{ML OuterSyntax.command} expects a name for the command, a
   775   The crucial function @{ML OuterSyntax.local_theory} expects a name for the command, a
   778   short description, a kind indicator (which we will explain later on more thoroughly) and a
   776   short description, a kind indicator (which we will explain later more thoroughly) and a
   779   parser producing a top-level transition function (its purpose will also explained
   777   parser producing a local theory transition (its purpose will also explained
   780   later). 
   778   later). 
   781 
   779 
   782   While this is everything you have to do on the ML-level, you need a keyword
   780   While this is everything you have to do on the ML-level, you need a keyword
   783   file that can be loaded by ProofGeneral. This is to enable ProofGeneral to
   781   file that can be loaded by ProofGeneral. This is to enable ProofGeneral to
   784   recognise \isacommand{foobar} as a command. Such a keyword file can be
   782   recognise \isacommand{foobar} as a command. Such a keyword file can be
   802   \isacommand{imports}~@{text Main}\\
   800   \isacommand{imports}~@{text Main}\\
   803   \isacommand{begin}\\
   801   \isacommand{begin}\\
   804   \isacommand{ML}~@{text "\<verbopen>"}\\
   802   \isacommand{ML}~@{text "\<verbopen>"}\\
   805   @{ML
   803   @{ML
   806 "let
   804 "let
   807   val do_nothing = Scan.succeed (Toplevel.theory I)
   805   val do_nothing = Scan.succeed (LocalTheory.theory I)
   808   val kind = OuterKeyword.thy_decl
   806   val kind = OuterKeyword.thy_decl
   809 in
   807 in
   810   OuterSyntax.command \"foobar\" \"description of foobar\" kind do_nothing
   808   OuterSyntax.local_theory \"foobar\" \"description of foobar\" kind do_nothing
   811 end"}\\
   809 end"}\\
   812   @{text "\<verbclose>"}\\
   810   @{text "\<verbclose>"}\\
   813   \isacommand{end}
   811   \isacommand{end}
   814   \end{graybox}
   812   \end{graybox}
   815   \caption{\small The file @{text "Command.thy"} is necessary for generating a log 
   813   \caption{The file @{text "Command.thy"} is necessary for generating a log 
   816   file. This log file enables Isabelle to generate a keyword file containing 
   814   file. This log file enables Isabelle to generate a keyword file containing 
   817   the command \isacommand{foobar}.\label{fig:commandtheory}}
   815   the command \isacommand{foobar}.\label{fig:commandtheory}}
   818   \end{figure}
   816   \end{figure}
   819   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   817   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   820 
   818 
   908   inside the tracing buffer. 
   906   inside the tracing buffer. 
   909 
   907 
   910   The crucial part of a command is the function that determines the behaviour
   908   The crucial part of a command is the function that determines the behaviour
   911   of the command. In the code above we used a ``do-nothing''-function, which
   909   of the command. In the code above we used a ``do-nothing''-function, which
   912   because of @{ML Scan.succeed} does not parse any argument, but immediately
   910   because of @{ML Scan.succeed} does not parse any argument, but immediately
   913   returns the simple toplevel function @{ML "Toplevel.theory I"}. We can
   911   returns the simple function @{ML "LocalTheory.theory I"}. We can
   914   replace this code by a function that first parses a proposition (using the
   912   replace this code by a function that first parses a proposition (using the
   915   parser @{ML OuterParse.prop}), then prints out the tracing
   913   parser @{ML OuterParse.prop}), then prints out the tracing
   916   information (using a new top-level function @{text trace_top_lvl}) and 
   914   information (using a new function @{text trace_prop}) and 
   917   finally does nothing. For this you can write:
   915   finally does nothing. For this you can write:
   918 *}
   916 *}
   919 
   917 
   920 ML{*let
   918 ML{*let
   921   fun trace_top_lvl str = 
   919   fun trace_prop str = 
   922      Toplevel.theory (fn thy => (tracing str; thy))
   920      LocalTheory.theory (fn lthy => (tracing str; lthy))
   923 
   921 
   924   val trace_prop = OuterParse.prop >> trace_top_lvl
   922   val trace_prop_parser = OuterParse.prop >> trace_prop
   925 
       
   926   val kind = OuterKeyword.thy_decl
   923   val kind = OuterKeyword.thy_decl
   927 in
   924 in
   928   OuterSyntax.command "foobar" "traces a proposition" kind trace_prop
   925   OuterSyntax.local_theory "foobar" "traces a proposition" 
       
   926     kind trace_prop_parser
   929 end *}
   927 end *}
   930 
   928 
   931 text {*
   929 text {*
   932   Now you can type
   930   Now you can type
   933 
   931 
   936   @{text "> \"True \<and> False\""}
   934   @{text "> \"True \<and> False\""}
   937   \end{isabelle}
   935   \end{isabelle}
   938   
   936   
   939   and see the proposition in the tracing buffer.  
   937   and see the proposition in the tracing buffer.  
   940 
   938 
   941   Note that so far we used @{ML thy_decl in OuterKeyword} as the kind indicator
   939   Note that so far we used @{ML thy_decl in OuterKeyword} as the kind
   942   for the command.  This means that the command finishes as soon as the
   940   indicator for the command.  This means that the command finishes as soon as
   943   arguments are processed. Examples of this kind of commands are
   941   the arguments are processed. Examples of this kind of commands are
   944   \isacommand{definition} and \isacommand{declare}.  In other cases,
   942   \isacommand{definition} and \isacommand{declare}.  In other cases, commands
   945   commands are expected to parse some arguments, for example a proposition,
   943   are expected to parse some arguments, for example a proposition, and then
   946   and then ``open up'' a proof in order to prove the proposition (for example
   944   ``open up'' a proof in order to prove the proposition (for example
   947   \isacommand{lemma}) or prove some other properties (for example
   945   \isacommand{lemma}) or prove some other properties (for example
   948   \isacommand{function}). To achieve this kind of behaviour, you have to use the kind
   946   \isacommand{function}). To achieve this kind of behaviour, you have to use
   949   indicator @{ML thy_goal in OuterKeyword}.  Note, however, once you change the 
   947   the kind indicator @{ML thy_goal in OuterKeyword} and the function @{ML
   950   ``kind'' of a command from @{ML thy_decl in OuterKeyword} to @{ML thy_goal in OuterKeyword} 
   948   "local_theory_to_proof" in OuterSyntax} to set up the command.  Note,
   951   then the keyword file needs to be re-created!
   949   however, once you change the ``kind'' of a command from @{ML thy_decl in
       
   950   OuterKeyword} to @{ML thy_goal in OuterKeyword} then the keyword file needs
       
   951   to be re-created!
   952 
   952 
   953   Below we change \isacommand{foobar} so that it takes a proposition as
   953   Below we change \isacommand{foobar} so that it takes a proposition as
   954   argument and then starts a proof in order to prove it. Therefore in Line 13, 
   954   argument and then starts a proof in order to prove it. Therefore in Line 13, 
   955   we set the kind indicator to @{ML thy_goal in OuterKeyword}.
   955   we set the kind indicator to @{ML thy_goal in OuterKeyword}.
   956 *}
   956 *}
   957 
   957 
   958 ML%linenosgray{*let
   958 ML%linenosgray{*let
   959   fun set_up_thm str ctxt =
   959   fun prove_prop str ctxt =
   960     let
   960     let
   961       val prop = Syntax.read_prop ctxt str
   961       val prop = Syntax.read_prop ctxt str
   962     in
   962     in
   963       Proof.theorem_i NONE (K I) [[(prop,[])]] ctxt
   963       Proof.theorem_i NONE (K I) [[(prop,[])]] ctxt
   964     end;
   964     end;
   965   
   965   
   966   val prove_prop = OuterParse.prop >>  
   966   val prove_prop_parser = OuterParse.prop >> prove_prop 
   967       (fn str => Toplevel.print o 
       
   968                     Toplevel.local_theory_to_proof NONE (set_up_thm str))
       
   969   
       
   970   val kind = OuterKeyword.thy_goal
   967   val kind = OuterKeyword.thy_goal
   971 in
   968 in
   972   OuterSyntax.command "foobar" "proving a proposition" kind prove_prop
   969   OuterSyntax.local_theory_to_proof "foobar" "proving a proposition" 
       
   970     kind prove_prop_parser
   973 end *}
   971 end *}
   974 
   972 
   975 text {*
   973 text {*
   976   The function @{text set_up_thm} in Lines 2 to 7 takes a string (the proposition to be
   974   The function @{text prove_prop} in Lines 2 to 7 takes a string (the proposition to be
   977   proved) and a context as argument.  The context is necessary in order to be able to use
   975   proved) and a context as argument.  The context is necessary in order to be able to use
   978   @{ML Syntax.read_prop}, which converts a string into a proper proposition.
   976   @{ML Syntax.read_prop}, which converts a string into a proper proposition.
   979   In Line 6 the function @{ML Proof.theorem_i} starts the proof for the
   977   In Line 6 the function @{ML Proof.theorem_i} starts the proof for the
   980   proposition. Its argument @{ML NONE} stands for a locale (which we chose to
   978   proposition. Its argument @{ML NONE} stands for a locale (which we chose to
   981   omit); the argument @{ML "(K I)"} stands for a function that determines what
   979   omit); the argument @{ML "(K I)"} stands for a function that determines what
   982   should be done with the theorem once it is proved (we chose to just forget
   980   should be done with the theorem once it is proved (we chose to just forget
   983   about it). Lines 9 to 11 contain the parser for the proposition.
   981   about it). Line 9 contains the parser for the proposition.
   984 
   982 
   985   If you now type \isacommand{foobar}~@{text [quotes] "True \<and> True"}, you obtain the following 
   983   If you now type \isacommand{foobar}~@{text [quotes] "True \<and> True"}, you obtain the following 
   986   proof state:
   984   proof state
   987 
   985 
   988   \begin{isabelle}
   986   \begin{isabelle}
   989   \isacommand{foobar}~@{text [quotes] "True \<and> True"}\\
   987   \isacommand{foobar}~@{text [quotes] "True \<and> True"}\\
   990   @{text "goal (1 subgoal):"}\\
   988   @{text "goal (1 subgoal):"}\\
   991   @{text "1. True \<and> True"}
   989   @{text "1. True \<and> True"}
   992   \end{isabelle}
   990   \end{isabelle}
   993 
   991 
   994   and you can build the proof
   992   and you can build the following proof
   995 
   993 
   996   \begin{isabelle}
   994   \begin{isabelle}
   997   \isacommand{foobar}~@{text [quotes] "True \<and> True"}\\
   995   \isacommand{foobar}~@{text [quotes] "True \<and> True"}\\
   998   \isacommand{apply}@{text "(rule conjI)"}\\
   996   \isacommand{apply}@{text "(rule conjI)"}\\
   999   \isacommand{apply}@{text "(rule TrueI)+"}\\
   997   \isacommand{apply}@{text "(rule TrueI)+"}\\
  1000   \isacommand{done}
   998   \isacommand{done}
  1001   \end{isabelle}
   999   \end{isabelle}
  1002 
       
  1003  
       
  1004   
       
  1005   (FIXME What do @{ML "Toplevel.theory"} 
       
  1006   @{ML "Toplevel.print"} 
       
  1007   @{ML Toplevel.local_theory} do?)
       
  1008 
  1000 
  1009   (FIXME read a name and show how to store theorems)
  1001   (FIXME read a name and show how to store theorems)
  1010 *}
  1002 *}
  1011 
  1003 
  1012 section {* Methods (TBD) *}
  1004 section {* Methods (TBD) *}