ProgTutorial/Parsing.thy
changeset 559 ffa5c4ec9611
parent 558 84aef87b348a
child 563 50d3059de9c6
equal deleted inserted replaced
558:84aef87b348a 559:ffa5c4ec9611
    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"} is used to indicate that alternative routes of parsing 
    82   \item @{text "FAIL"} 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 @{text "MORE"} indicates that there is not enough input for the parser. For example 
    85   in @{text "($$ \"h\") []"}.
    85   in @{text "($$ \"h\") []"}.
    86   \item @{text "ABORT"} is the exception that is raised when a dead end is reached. 
    86   \item @{text "ABORT"} 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).
   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 @{text "p"}, in case it succeeds; otherwise it returns the
   146   result of @{text "q"}. For example:
   146   result of @{text "q"}. For example:
   147 
   147 
   148 
   148 
   149 @{ML_response [display,gray] 
   149 @{ML_response [display,gray] 
   150 "let 
   150 "let 
   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"}, if it succeeds; otherwise it returns 
   176   @{text "p"}, in case it succeeds; otherwise it returns 
   177   the default value @{text "x"}. For example:
   177   the default value @{text "x"}. 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\"
   218   To see this assume that @{text p} is present in the input, but it is not
   218   To see this assume that @{text p} 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 @{text q}. 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 @{text r} 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 ``@{text "p"}-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. This kind of
   223   of @{text r}, not by the absence of @{text q} 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 
   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 @{text p} as 
   283   often 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
   968   \isacommand{imports}~@{text Main}\\
   968   \isacommand{imports}~@{text Main}\\
   969   \isacommand{keywords} @{text [quotes] "foobar"} @{text "::"} @{text "thy_decl"}\\
   969   \isacommand{keywords} @{text [quotes] "foobar"} @{text "::"} @{text "thy_decl"}\\
   970   ...
   970   ...
   971   \end{graybox}
   971   \end{graybox}
   972 
   972 
   973   whereby @{ML_ind "thy_decl" in Keyword} indicates the kind of the
   973   where @{ML_ind "thy_decl" in Keyword} indicates the kind of the
   974   command.  Another possible kind is @{text "thy_goal"}, or you can
   974   command.  Another possible kind is @{text "thy_goal"}, or you can
   975   also omit the kind entirely, in which case you declare a keyword
   975   also omit the kind entirely, in which case you declare a keyword
   976   (something that is part of a command).
   976   (something that is part of a command).
   977 
   977 
   978   Now you can implement \isacommand{foobar} as follows.
   978   Now you can implement \isacommand{foobar} as follows.
  1188 section {* Proof-General and Keyword Files *}
  1188 section {* Proof-General and Keyword Files *}
  1189 
  1189 
  1190 text {*
  1190 text {*
  1191   In order to use a new command in Emacs and Proof-General, you need a keyword
  1191   In order to use a new command in Emacs and Proof-General, you need a keyword
  1192   file that can be loaded by ProofGeneral. To keep things simple we take as
  1192   file that can be loaded by ProofGeneral. To keep things simple we take as
  1193   running example the command \isacommand{foobar} from the previous section. 
  1193   a running example the command \isacommand{foobar} from the previous section. 
  1194 
  1194 
  1195   A keyword file can be generated with the command-line:
  1195   A keyword file can be generated with the command-line:
  1196 
  1196 
  1197   @{text [display] "$ isabelle keywords -k foobar some_log_files"}
  1197   @{text [display] "$ isabelle keywords -k foobar some_log_files"}
  1198 
  1198 
  1228   be used to generate a keyword file containing the command \isacommand{foobar}.
  1228   be used to generate a keyword file containing the command \isacommand{foobar}.
  1229   \label{fig:commandtheory}}
  1229   \label{fig:commandtheory}}
  1230   \end{figure}
  1230   \end{figure}
  1231   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1231   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1232 
  1232 
       
  1233 
  1233   For our purposes it is sufficient to use the log files of the theories
  1234   For our purposes it is sufficient to use the log files of the theories
  1234   @{text "Pure"}, @{text "HOL"} and @{text "Pure-ProofGeneral"}, as well as
  1235   @{text "Pure"}, @{text "HOL"} and @{text "Pure-ProofGeneral"}, as well as
  1235   the log file for the theory @{text "Command.thy"}, which contains the new
  1236   the log file for the theory @{text "Command.thy"}, which contains the new
  1236   \isacommand{foobar}-command. If you target other logics besides HOL, such
  1237   \isacommand{foobar}-command. If you target other logics besides HOL, such
  1237   as Nominal or ZF, then you need to adapt the log files appropriately.
  1238   as Nominal or ZF, then you need to adapt the log files appropriately.
  1238   
  1239   
  1239   @{text Pure} and @{text HOL} are usually compiled during the installation of
  1240   @{text Pure} and @{text HOL} are usually compiled during the installation of
  1240   Isabelle. So log files for them should be already available. If not, then
  1241   Isabelle. So log files for them should be already available. If not, then
  1241   they can be conveniently compiled with the help of the build-script from the Isabelle
  1242   they can be easily compiled with the build-script from the Isabelle
  1242   distribution.
  1243   distribution.
  1243 
  1244 
  1244   @{text [display] 
  1245   @{text [display] 
  1245 "$ ./build -m \"Pure\"
  1246 "$ ./build -m \"Pure\"
  1246 $ ./build -m \"HOL\""}
  1247 $ ./build -m \"HOL\""}
  1249 
  1250 
  1250   @{text [display] "$ ./build -m \"Pure-ProofGeneral\" \"Pure\""}
  1251   @{text [display] "$ ./build -m \"Pure-ProofGeneral\" \"Pure\""}
  1251 
  1252 
  1252   For the theory @{text "Command.thy"}, you first need to create a ``managed'' subdirectory 
  1253   For the theory @{text "Command.thy"}, you first need to create a ``managed'' subdirectory 
  1253   with:
  1254   with:
  1254 
  1255  
  1255   @{text [display] "$ isabelle mkdir FoobarCommand"}
  1256   @{text [display] "$ isabelle mkroot -d FoobarCommand"}
  1256 
  1257 
  1257   This generates a directory containing the files: 
  1258   This generates a directory containing the files: 
  1258 
  1259   
  1259   @{text [display] 
  1260   @{text [display] 
  1260 "./IsaMakefile
  1261 "./FoobarCommand/ROOT
  1261 ./FoobarCommand/ROOT.ML
       
  1262 ./FoobarCommand/document
  1262 ./FoobarCommand/document
  1263 ./FoobarCommand/document/root.tex"}
  1263 ./FoobarCommand/document/root.tex"}
  1264 
  1264  
  1265 
       
  1266   You need to copy the file @{text "Command.thy"} into the directory @{text "FoobarCommand"}
  1265   You need to copy the file @{text "Command.thy"} into the directory @{text "FoobarCommand"}
  1267   and add the line 
  1266   and add the line 
  1268 
  1267 
  1269   @{text [display] "no_document use_thy \"Command\";"} 
  1268   @{text [display] "no_document use_thy \"Command\";"} 
  1270   
  1269   
  1271   to the file @{text "./FoobarCommand/ROOT.ML"}. You can now compile the theory by just typing:
  1270   to the file @{text "./FoobarCommand/ROOT"}. You can now compile the theory by just typing:
  1272 
  1271 
  1273   @{text [display] "$ isabelle make"}
  1272   @{text [display] "$ isabelle build"}
  1274 
  1273 
  1275   If the compilation succeeds, you have finally created all the necessary log files. 
  1274   If the compilation succeeds, you have finally created all the necessary log files. 
  1276   They are stored in the directory 
  1275   They are stored in the directory 
  1277   
  1276   
  1278   @{text [display]  "~/.isabelle/heaps/Isabelle2012/polyml-5.2.1_x86-linux/log"}
  1277   @{text [display]  "~/.isabelle/heaps/Isabelle2012/polyml-5.2.1_x86-linux/log"}
  1467 section {* Methods (TBD) *}
  1466 section {* Methods (TBD) *}
  1468 
  1467 
  1469 text {*
  1468 text {*
  1470   (FIXME: maybe move to after the tactic section)
  1469   (FIXME: maybe move to after the tactic section)
  1471 
  1470 
  1472   Methods are central to Isabelle. They are the ones you use for example
  1471   Methods are central to Isabelle. You use them, for example,
  1473   in \isacommand{apply}. To print out all currently known methods you can use the 
  1472   in \isacommand{apply}. To print out all currently known methods you can use the 
  1474   Isabelle command:
  1473   Isabelle command:
  1475 
  1474 
  1476   \begin{isabelle}
  1475   \begin{isabelle}
  1477   \isacommand{print\_methods}\\
  1476   \isacommand{print\_methods}\\