4
|
1 |
theory Parsing
|
|
2 |
imports Main
|
|
3 |
|
|
4 |
begin
|
|
5 |
|
|
6 |
chapter {* Parsing *}
|
|
7 |
|
|
8 |
text {*
|
|
9 |
|
|
10 |
Lots of Standard ML code is given in this document, for various reasons,
|
|
11 |
including:
|
|
12 |
\begin{itemize}
|
|
13 |
\item direct quotation of code found in the Isabelle source files,
|
|
14 |
or simplified versions of such code
|
|
15 |
\item identifiers found in the Isabelle source code, with their types
|
|
16 |
(or specialisations of their types)
|
|
17 |
\item code examples, which can be run by the reader, to help illustrate the
|
|
18 |
behaviour of functions found in the Isabelle source code
|
|
19 |
\item ancillary functions, not from the Isabelle source code,
|
|
20 |
which enable the reader to run relevant code examples
|
|
21 |
\item type abbreviations, which help explain the uses of certain functions
|
|
22 |
\end{itemize}
|
|
23 |
|
|
24 |
*}
|
|
25 |
|
|
26 |
section {* Parsing Isar input *}
|
|
27 |
|
|
28 |
text {*
|
|
29 |
|
|
30 |
The typical parsing function has the type
|
|
31 |
\texttt{'src -> 'res * 'src}, with input
|
|
32 |
of type \texttt{'src}, returning a result
|
|
33 |
of type \texttt{'res}, which is (or is derived from) the first part of the
|
|
34 |
input, and also returning the remainder of the input.
|
|
35 |
(In the common case, when it is clear what the ``remainder of the input''
|
|
36 |
means, we will just say that the functions ``returns'' the
|
|
37 |
value of type \texttt{'res}).
|
|
38 |
An exception is raised if an appropriate value
|
|
39 |
cannot be produced from the input.
|
|
40 |
A range of exceptions can be used to identify different reasons
|
|
41 |
for the failure of a parse.
|
|
42 |
|
|
43 |
This contrasts the standard parsing function in Standard ML,
|
|
44 |
which is of type
|
|
45 |
\texttt{type ('res, 'src) reader = 'src -> ('res * 'src) option};
|
|
46 |
(for example, \texttt{List.getItem} and \texttt{Substring.getc}).
|
|
47 |
However, much of the discussion at
|
|
48 |
FIX file:/home/jeremy/html/ml/SMLBasis/string-cvt.html
|
|
49 |
is relevant.
|
|
50 |
|
|
51 |
Naturally one may convert between the two different sorts of parsing functions
|
|
52 |
as follows:
|
|
53 |
\begin{verbatim}
|
|
54 |
open StringCvt ;
|
|
55 |
type ('res, 'src) ex_reader = 'src -> 'res * 'src
|
|
56 |
(* ex_reader : ('res, 'src) reader -> ('res, 'src) ex_reader *)
|
|
57 |
fun ex_reader rdr src = Option.valOf (rdr src) ;
|
|
58 |
(* reader : ('res, 'src) ex_reader -> ('res, 'src) reader *)
|
|
59 |
fun reader exrdr src = SOME (exrdr src) handle _ => NONE ;
|
|
60 |
\end{verbatim}
|
|
61 |
|
|
62 |
*}
|
|
63 |
|
|
64 |
section{* The \texttt{Scan} structure *}
|
|
65 |
|
|
66 |
text {*
|
|
67 |
The source file is \texttt{src/General/scan.ML}.
|
|
68 |
This structure provides functions for using and combining parsing functions
|
|
69 |
of the type \texttt{'src -> 'res * 'src}.
|
|
70 |
Three exceptions are used:
|
|
71 |
\begin{verbatim}
|
|
72 |
exception MORE of string option; (*need more input (prompt)*)
|
|
73 |
exception FAIL of string option; (*try alternatives (reason of failure)*)
|
|
74 |
exception ABORT of string; (*dead end*)
|
|
75 |
\end{verbatim}
|
|
76 |
Many functions in this structure (generally those with names composed of
|
|
77 |
symbols) are declared as infix.
|
|
78 |
|
|
79 |
Some functions from that structure are
|
|
80 |
\begin{verbatim}
|
|
81 |
|-- : ('src -> 'res1 * 'src') * ('src' -> 'res2 * 'src'') ->
|
|
82 |
'src -> 'res2 * 'src''
|
|
83 |
--| : ('src -> 'res1 * 'src') * ('src' -> 'res2 * 'src'') ->
|
|
84 |
'src -> 'res1 * 'src''
|
|
85 |
-- : ('src -> 'res1 * 'src') * ('src' -> 'res2 * 'src'') ->
|
|
86 |
'src -> ('res1 * 'res2) * 'src''
|
|
87 |
^^ : ('src -> string * 'src') * ('src' -> string * 'src'') ->
|
|
88 |
'src -> string * 'src''
|
|
89 |
\end{verbatim}
|
|
90 |
These functions parse a result off the input source twice.
|
|
91 |
|
|
92 |
\texttt{|--} and \texttt{--|}
|
|
93 |
return the first result and the second result, respectively.
|
|
94 |
|
|
95 |
\texttt{--} returns both.
|
|
96 |
|
|
97 |
\verb|^^| returns the result of concatenating the two results
|
|
98 |
(which must be strings).
|
|
99 |
|
|
100 |
Note how, although the types
|
|
101 |
\texttt{'src}, \texttt{'src'} and \texttt{'src''} will normally be the same,
|
|
102 |
the types as shown help suggest the behaviour of the functions.
|
|
103 |
\begin{verbatim}
|
|
104 |
:-- : ('src -> 'res1 * 'src') * ('res1 -> 'src' -> 'res2 * 'src'') ->
|
|
105 |
'src -> ('res1 * 'res2) * 'src''
|
|
106 |
:|-- : ('src -> 'res1 * 'src') * ('res1 -> 'src' -> 'res2 * 'src'') ->
|
|
107 |
'src -> 'res2 * 'src''
|
|
108 |
\end{verbatim}
|
|
109 |
These are similar to \texttt{|--} and \texttt{--|},
|
|
110 |
except that the second parsing function can depend on the result of the first.
|
|
111 |
\begin{verbatim}
|
|
112 |
>> : ('src -> 'res1 * 'src') * ('res1 -> 'res2) -> 'src -> 'res2 * 'src'
|
|
113 |
|| : ('src -> 'res_src) * ('src -> 'res_src) -> 'src -> 'res_src
|
|
114 |
\end{verbatim}
|
|
115 |
\texttt{p >> f} applies a function \texttt{f} to the result of a parse.
|
|
116 |
|
|
117 |
\texttt{||} tries a second parsing function if the first one
|
|
118 |
fails by raising an exception of the form \texttt{FAIL \_}.
|
|
119 |
|
|
120 |
\begin{verbatim}
|
|
121 |
succeed : 'res -> ('src -> 'res * 'src) ;
|
|
122 |
fail : ('src -> 'res_src) ;
|
|
123 |
!! : ('src * string option -> string) ->
|
|
124 |
('src -> 'res_src) -> ('src -> 'res_src) ;
|
|
125 |
\end{verbatim}
|
|
126 |
\texttt{succeed r} returns \texttt{r}, with the input unchanged.
|
|
127 |
\texttt{fail} always fails, raising exception \texttt{FAIL NONE}.
|
|
128 |
\texttt{!! f} only affects the failure mode, turning a failure that
|
|
129 |
raises \texttt{FAIL \_} into a failure that raises \texttt{ABORT ...}.
|
|
130 |
This is used to prevent recovery from the failure ---
|
|
131 |
thus, in \texttt{!! parse1 || parse2}, if \texttt{parse1} fails,
|
|
132 |
it won't recover by trying \texttt{parse2}.
|
|
133 |
|
|
134 |
\begin{verbatim}
|
|
135 |
one : ('si -> bool) -> ('si list -> 'si * 'si list) ;
|
|
136 |
some : ('si -> 'res option) -> ('si list -> 'res * 'si list) ;
|
|
137 |
\end{verbatim}
|
|
138 |
These require the input to be a list of items:
|
|
139 |
they fail, raising \texttt{MORE NONE} if the list is empty.
|
|
140 |
On other failures they raise \texttt{FAIL NONE}
|
|
141 |
|
|
142 |
\texttt{one p} takes the first
|
|
143 |
item from the list if it satisfies \texttt{p}, otherwise fails.
|
|
144 |
|
|
145 |
\texttt{some f} takes the first
|
|
146 |
item from the list and applies \texttt{f} to it, failing if this returns
|
|
147 |
\texttt{NONE}.
|
|
148 |
|
|
149 |
\begin{verbatim}
|
|
150 |
many : ('si -> bool) -> 'si list -> 'si list * 'si list ;
|
|
151 |
\end{verbatim}
|
|
152 |
\texttt{many p} takes items from the input until it encounters one
|
|
153 |
which does not satisfy \texttt{p}. If it reaches the end of the input
|
|
154 |
it fails, raising \texttt{MORE NONE}.
|
|
155 |
|
|
156 |
\texttt{many1} (with the same type) fails if the first item
|
|
157 |
does not satisfy \texttt{p}.
|
|
158 |
|
|
159 |
\begin{verbatim}
|
|
160 |
option : ('src -> 'res * 'src) -> ('src -> 'res option * 'src)
|
|
161 |
optional : ('src -> 'res * 'src) -> 'res -> ('src -> 'res * 'src)
|
|
162 |
\end{verbatim}
|
|
163 |
\texttt{option}:
|
|
164 |
where the parser \texttt{f} succeeds with result \texttt{r}
|
|
165 |
or raises \texttt{FAIL \_},
|
|
166 |
\texttt{option f} gives the result \texttt{SOME r} or \texttt{NONE}.
|
|
167 |
|
|
168 |
\texttt{optional}: if parser \texttt{f} fails by raising \texttt{FAIL \_},
|
|
169 |
\texttt{optional f default} provides the result \texttt{default}.
|
|
170 |
|
|
171 |
\begin{verbatim}
|
|
172 |
repeat : ('src -> 'res * 'src) -> 'src -> 'res list * 'src
|
|
173 |
repeat1 : ('src -> 'res * 'src) -> 'src -> 'res list * 'src
|
|
174 |
bulk : ('src -> 'res * 'src) -> 'src -> 'res list * 'src
|
|
175 |
\end{verbatim}
|
|
176 |
\texttt{repeat f} repeatedly parses an item off the remaining input until
|
|
177 |
\texttt{f} fails with \texttt{FAIL \_}
|
|
178 |
|
|
179 |
\texttt{repeat1} is as for \texttt{repeat}, but requires at least one
|
|
180 |
successful parse.
|
|
181 |
|
|
182 |
\begin{verbatim}
|
|
183 |
lift : ('src -> 'res * 'src) -> ('ex * 'src -> 'res * ('ex * 'src))
|
|
184 |
\end{verbatim}
|
|
185 |
\texttt{lift} changes the source type of a parser by putting in an extra
|
|
186 |
component \texttt{'ex}, which is ignored in the parsing.
|
|
187 |
|
|
188 |
The \texttt{Scan} structure also provides the type \texttt{lexicon},
|
|
189 |
HOW DO THEY WORK ?? TO BE COMPLETED
|
|
190 |
\begin{verbatim}
|
|
191 |
dest_lexicon: lexicon -> string list ;
|
|
192 |
make_lexicon: string list list -> lexicon ;
|
|
193 |
empty_lexicon: lexicon ;
|
|
194 |
extend_lexicon: string list list -> lexicon -> lexicon ;
|
|
195 |
merge_lexicons: lexicon -> lexicon -> lexicon ;
|
|
196 |
is_literal: lexicon -> string list -> bool ;
|
|
197 |
literal: lexicon -> string list -> string list * string list ;
|
|
198 |
\end{verbatim}
|
|
199 |
Two lexicons, for the commands and keywords, are stored and can be retrieved
|
|
200 |
by:
|
|
201 |
\begin{verbatim}
|
|
202 |
val (command_lexicon, keyword_lexicon) = OuterSyntax.get_lexicons () ;
|
|
203 |
val commands = Scan.dest_lexicon command_lexicon ;
|
|
204 |
val keywords = Scan.dest_lexicon keyword_lexicon ;
|
|
205 |
\end{verbatim}
|
|
206 |
*}
|
|
207 |
|
|
208 |
section{* The \texttt{OuterLex} structure *}
|
|
209 |
|
|
210 |
text {*
|
|
211 |
The source file is @{text "src/Pure/Isar/outer_lex.ML"}.
|
|
212 |
In some other source files its name is abbreviated:
|
|
213 |
\begin{verbatim}
|
|
214 |
structure T = OuterLex;
|
|
215 |
\end{verbatim}
|
|
216 |
This structure defines the type \texttt{token}.
|
|
217 |
(The types
|
|
218 |
\texttt{OuterLex.token},
|
|
219 |
\texttt{OuterParse.token} and
|
|
220 |
\texttt{SpecParse.token} are all the same).
|
|
221 |
|
|
222 |
Input text is split up into tokens, and the input source type for many parsing
|
|
223 |
functions is \texttt{token list}.
|
|
224 |
|
|
225 |
The datatype definition (which is not published in the signature) is
|
|
226 |
\begin{verbatim}
|
|
227 |
datatype token = Token of Position.T * (token_kind * string);
|
|
228 |
\end{verbatim}
|
|
229 |
but here are some runnable examples for viewing tokens:
|
|
230 |
|
|
231 |
*}
|
|
232 |
|
|
233 |
text {*
|
|
234 |
FIXME
|
|
235 |
|
|
236 |
@{text "
|
|
237 |
begin{verbatim}
|
|
238 |
type token = T.token ;
|
|
239 |
val toks : token list = OuterSyntax.scan ``theory,imports;begin x.y.z apply ?v1 ?'a 'a -- || 44 simp (* xx *) { * fff * }'' ;
|
|
240 |
print_depth 20 ;
|
|
241 |
List.map T.text_of toks ;
|
|
242 |
val proper_toks = List.filter T.is_proper toks ;
|
|
243 |
List.map T.kind_of proper_toks ;
|
|
244 |
List.map T.unparse proper_toks ;
|
|
245 |
List.map T.val_of proper_toks ;
|
|
246 |
end{verbatim}"}
|
|
247 |
|
|
248 |
*}
|
|
249 |
|
|
250 |
text {*
|
|
251 |
|
|
252 |
The function \texttt{is\_proper : token -> bool} identifies tokens which are
|
|
253 |
not white space or comments: many parsing functions assume require spaces or
|
|
254 |
comments to have been filtered out.
|
|
255 |
|
|
256 |
There is a special end-of-file token:
|
|
257 |
\begin{verbatim}
|
|
258 |
val (tok_eof : token, is_eof : token -> bool) = T.stopper ;
|
|
259 |
(* end of file token *)
|
|
260 |
\end{verbatim}
|
|
261 |
|
|
262 |
*}
|
|
263 |
|
|
264 |
section {* The \texttt{OuterParse} structure *}
|
|
265 |
|
|
266 |
text {*
|
|
267 |
The source file is \texttt{src/Pure/Isar/outer\_parse.ML}.
|
|
268 |
In some other source files its name is abbreviated:
|
|
269 |
\begin{verbatim}
|
|
270 |
structure P = OuterParse;
|
|
271 |
\end{verbatim}
|
|
272 |
Here the parsers use \texttt{token list} as the input source type.
|
|
273 |
|
|
274 |
Some of the parsers simply select the first token, provided that it is of the
|
|
275 |
right kind (as returned by \texttt{T.kind\_of}): these are
|
|
276 |
\texttt{ command, keyword, short\_ident, long\_ident, sym\_ident, term\_var,
|
|
277 |
type\_ident, type\_var, number, string, alt\_string, verbatim, sync, eof}
|
|
278 |
Others select the first token, provided that it is one of several kinds,
|
|
279 |
(eg, \texttt{name, xname, text, typ}).
|
|
280 |
|
|
281 |
\begin{verbatim}
|
|
282 |
type 'a tlp = token list -> 'a * token list ; (* token list parser *)
|
|
283 |
$$$ : string -> string tlp
|
|
284 |
nat : int tlp ;
|
|
285 |
maybe : 'a tlp -> 'a option tlp ;
|
|
286 |
\end{verbatim}
|
|
287 |
|
|
288 |
\texttt{\$\$\$ s} returns the first token,
|
|
289 |
if it equals \texttt{s} \emph{and} \texttt{s} is a keyword.
|
|
290 |
|
|
291 |
\texttt{nat} returns the first token, if it is a number, and evaluates it.
|
|
292 |
|
|
293 |
\texttt{maybe}: if \texttt{p} returns \texttt{r},
|
|
294 |
then \texttt{maybe p} returns \texttt{SOME r} ;
|
|
295 |
if the first token is an underscore, it returns \texttt{NONE}.
|
|
296 |
|
|
297 |
A few examples:
|
|
298 |
\begin{verbatim}
|
|
299 |
P.list : 'a tlp -> 'a list tlp ; (* likewise P.list1 *)
|
|
300 |
P.and_list : 'a tlp -> 'a list tlp ; (* likewise P.and_list1 *)
|
|
301 |
val toks : token list = OuterSyntax.scan "44 ,_, 66,77" ;
|
|
302 |
val proper_toks = List.filter T.is_proper toks ;
|
|
303 |
P.list P.nat toks ; (* OK, doesn't recognize white space *)
|
|
304 |
P.list P.nat proper_toks ; (* fails, doesn't recognize what follows ',' *)
|
|
305 |
P.list (P.maybe P.nat) proper_toks ; (* fails, end of input *)
|
|
306 |
P.list (P.maybe P.nat) (proper_toks @ [tok_eof]) ; (* OK *)
|
|
307 |
val toks : token list = OuterSyntax.scan "44 and 55 and 66 and 77" ;
|
|
308 |
P.and_list P.nat (List.filter T.is_proper toks @ [tok_eof]) ; (* ??? *)
|
|
309 |
\end{verbatim}
|
|
310 |
|
|
311 |
The following code helps run examples:
|
|
312 |
\begin{verbatim}
|
|
313 |
fun parse_str tlp str =
|
|
314 |
let val toks : token list = OuterSyntax.scan str ;
|
|
315 |
val proper_toks = List.filter T.is_proper toks @ [tok_eof] ;
|
|
316 |
val (res, rem_toks) = tlp proper_toks ;
|
|
317 |
val rem_str = String.concat
|
|
318 |
(Library.separate " " (List.map T.unparse rem_toks)) ;
|
|
319 |
in (res, rem_str) end ;
|
|
320 |
\end{verbatim}
|
|
321 |
|
|
322 |
Some examples from \texttt{src/Pure/Isar/outer\_parse.ML}
|
|
323 |
\begin{verbatim}
|
|
324 |
val type_args =
|
|
325 |
type_ident >> Library.single ||
|
|
326 |
$$$ "(" |-- !!! (list1 type_ident --| $$$ ")") ||
|
|
327 |
Scan.succeed [];
|
|
328 |
\end{verbatim}
|
|
329 |
There are three ways parsing a list of type arguments can succeed.
|
|
330 |
The first line reads a single type argument, and turns it into a singleton
|
|
331 |
list.
|
|
332 |
The second line reads "(", and then the remainder, ignoring the "(" ;
|
|
333 |
the remainder consists of a list of type identifiers (at least one),
|
|
334 |
and then a ")" which is also ignored.
|
|
335 |
The \texttt{!!!} ensures that if the parsing proceeds this far and then fails,
|
|
336 |
it won't try the third line (see the description of \texttt{Scan.!!}).
|
|
337 |
The third line consumes no input and returns the empty list.
|
|
338 |
|
|
339 |
\begin{verbatim}
|
|
340 |
fun triple2 (x, (y, z)) = (x, y, z);
|
|
341 |
val arity = xname -- ($$$ "::" |-- !!! (
|
|
342 |
Scan.optional ($$$ "(" |-- !!! (list1 sort --| $$$ ")")) []
|
|
343 |
-- sort)) >> triple2;
|
|
344 |
\end{verbatim}
|
|
345 |
The parser \texttt{arity} reads a typename $t$, then ``\texttt{::}'' (which is
|
|
346 |
ignored), then optionally a list $ss$ of sorts and then another sort $s$.
|
|
347 |
The result $(t, (ss, s))$ is transformed by \texttt{triple2} to $(t, ss, s)$.
|
|
348 |
The second line reads the optional list of sorts:
|
|
349 |
it reads first ``\texttt{(}'' and last ``\texttt{)}'', which are both ignored,
|
|
350 |
and between them a comma-separated list of sorts.
|
|
351 |
If this list is absent, the default \texttt{[]} provides the list of sorts.
|
|
352 |
|
|
353 |
\begin{verbatim}
|
|
354 |
parse_str P.type_args "('a, 'b) ntyp" ;
|
|
355 |
parse_str P.type_args "'a ntyp" ;
|
|
356 |
parse_str P.type_args "ntyp" ;
|
|
357 |
parse_str P.arity "ty :: tycl" ;
|
|
358 |
parse_str P.arity "ty :: (tycl1, tycl2) tycl" ;
|
|
359 |
\end{verbatim}
|
|
360 |
|
|
361 |
*}
|
|
362 |
|
|
363 |
section {* The \texttt{SpecParse} structure *}
|
|
364 |
|
|
365 |
text {*
|
|
366 |
The source file is \texttt{src/Pure/Isar/spec\_parse.ML}.
|
|
367 |
This structure contains token list parsers for more complicated values.
|
|
368 |
For example,
|
|
369 |
\begin{verbatim}
|
|
370 |
open SpecParse ;
|
|
371 |
attrib : Attrib.src tok_rdr ;
|
|
372 |
attribs : Attrib.src list tok_rdr ;
|
|
373 |
opt_attribs : Attrib.src list tok_rdr ;
|
|
374 |
xthm : (thmref * Attrib.src list) tok_rdr ;
|
|
375 |
xthms1 : (thmref * Attrib.src list) list tok_rdr ;
|
|
376 |
|
|
377 |
parse_str attrib "simp" ;
|
|
378 |
parse_str opt_attribs "hello" ;
|
|
379 |
val (ass, "") = parse_str attribs "[standard, xxxx, simp, intro, OF sym]" ;
|
|
380 |
map Args.dest_src ass ;
|
|
381 |
val (asrc, "") = parse_str attrib "THEN trans [THEN sym]" ;
|
|
382 |
|
|
383 |
parse_str xthm "mythm [attr]" ;
|
|
384 |
parse_str xthms1 "thm1 [attr] thms2" ;
|
|
385 |
\end{verbatim}
|
|
386 |
|
|
387 |
As you can see, attributes are described using types of the \texttt{Args}
|
|
388 |
structure, described below.
|
|
389 |
*}
|
|
390 |
|
|
391 |
section{* The \texttt{Args} structure *}
|
|
392 |
|
|
393 |
text {*
|
|
394 |
The source file is \texttt{src/Pure/Isar/args.ML}.
|
|
395 |
The primary type of this structure is the \texttt{src} datatype;
|
|
396 |
the single constructors not published in the signature, but
|
|
397 |
\texttt{Args.src} and \texttt{Args.dest\_src}
|
|
398 |
are in fact the constructor and destructor functions.
|
|
399 |
Note that the types \texttt{Attrib.src} and \texttt{Method.src}
|
|
400 |
are in fact \texttt{Args.src}.
|
|
401 |
|
|
402 |
\begin{verbatim}
|
|
403 |
src : (string * Args.T list) * Position.T -> Args.src ;
|
|
404 |
dest_src : Args.src -> (string * Args.T list) * Position.T ;
|
|
405 |
Args.pretty_src : Proof.context -> Args.src -> Pretty.T ;
|
|
406 |
fun pr_src ctxt src = Pretty.string_of (Args.pretty_src ctxt src) ;
|
|
407 |
|
|
408 |
val thy = ML_Context.the_context () ;
|
|
409 |
val ctxt = ProofContext.init thy ;
|
|
410 |
map (pr_src ctxt) ass ;
|
|
411 |
\end{verbatim}
|
|
412 |
|
|
413 |
So an \texttt{Args.src} consists of the first word, then a list of further
|
|
414 |
``arguments'', of type \texttt{Args.T}, with information about position in the
|
|
415 |
input.
|
|
416 |
\begin{verbatim}
|
|
417 |
(* how an Args.src is parsed *)
|
|
418 |
P.position : 'a tlp -> ('a * Position.T) tlp ;
|
|
419 |
P.arguments : Args.T list tlp ;
|
|
420 |
|
|
421 |
val parse_src : Args.src tlp =
|
|
422 |
P.position (P.xname -- P.arguments) >> Args.src ;
|
|
423 |
\end{verbatim}
|
|
424 |
|
|
425 |
\begin{verbatim}
|
|
426 |
val ((first_word, args), pos) = Args.dest_src asrc ;
|
|
427 |
map Args.string_of args ;
|
|
428 |
\end{verbatim}
|
|
429 |
|
|
430 |
The \texttt{Args} structure contains more parsers and parser transformers
|
|
431 |
for which the input source type is \texttt{Args.T list}. For example,
|
|
432 |
\begin{verbatim}
|
|
433 |
type 'a atlp = Args.T list -> 'a * Args.T list ;
|
|
434 |
open Args ;
|
|
435 |
nat : int atlp ; (* also Args.int *)
|
|
436 |
thm_sel : PureThy.interval list atlp ;
|
|
437 |
list : 'a atlp -> 'a list atlp ;
|
|
438 |
attribs : (string -> string) -> Args.src list atlp ;
|
|
439 |
opt_attribs : (string -> string) -> Args.src list atlp ;
|
|
440 |
|
|
441 |
(* parse_atl_str : 'a atlp -> (string -> 'a * string) ;
|
|
442 |
given an Args.T list parser, to get a string parser *)
|
|
443 |
fun parse_atl_str atlp str =
|
|
444 |
let val (ats, rem_str) = parse_str P.arguments str ;
|
|
445 |
val (res, rem_ats) = atlp ats ;
|
|
446 |
in (res, String.concat (Library.separate " "
|
|
447 |
(List.map Args.string_of rem_ats @ [rem_str]))) end ;
|
|
448 |
|
|
449 |
parse_atl_str Args.int "-1-," ;
|
|
450 |
parse_atl_str (Scan.option Args.int) "x1-," ;
|
|
451 |
parse_atl_str Args.thm_sel "(1-,4,13-22)" ;
|
|
452 |
|
|
453 |
val (ats as atsrc :: _, "") = parse_atl_str (Args.attribs I)
|
|
454 |
"[THEN trans [THEN sym], simp, OF sym]" ;
|
|
455 |
\end{verbatim}
|
|
456 |
|
|
457 |
From here, an attribute is interpreted using \texttt{Attrib.attribute}.
|
|
458 |
|
|
459 |
\texttt{Args} has a large number of functions which parse an \texttt{Args.src}
|
|
460 |
and also refer to a generic context.
|
|
461 |
Note the use of \texttt{Scan.lift} for this.
|
|
462 |
(as does \texttt{Attrib} - RETHINK THIS)
|
|
463 |
|
|
464 |
(\texttt{Args.syntax} shown below has type specialised)
|
|
465 |
|
|
466 |
\begin{verbatim}
|
|
467 |
type ('res, 'src) parse_fn = 'src -> 'res * 'src ;
|
|
468 |
type 'a cgatlp = ('a, Context.generic * Args.T list) parse_fn ;
|
|
469 |
Scan.lift : 'a atlp -> 'a cgatlp ;
|
|
470 |
term : term cgatlp ;
|
|
471 |
typ : typ cgatlp ;
|
|
472 |
|
|
473 |
Args.syntax : string -> 'res cgatlp -> src -> ('res, Context.generic) parse_fn ;
|
|
474 |
Attrib.thm : thm cgatlp ;
|
|
475 |
Attrib.thms : thm list cgatlp ;
|
|
476 |
Attrib.multi_thm : thm list cgatlp ;
|
|
477 |
|
|
478 |
(* parse_cgatl_str : 'a cgatlp -> (string -> 'a * string) ;
|
|
479 |
given a (Context.generic * Args.T list) parser, to get a string parser *)
|
|
480 |
fun parse_cgatl_str cgatlp str =
|
|
481 |
let
|
|
482 |
(* use the current generic context *)
|
|
483 |
val generic = Context.Theory thy ;
|
|
484 |
val (ats, rem_str) = parse_str P.arguments str ;
|
|
485 |
(* ignore any change to the generic context *)
|
|
486 |
val (res, (_, rem_ats)) = cgatlp (generic, ats) ;
|
|
487 |
in (res, String.concat (Library.separate " "
|
|
488 |
(List.map Args.string_of rem_ats @ [rem_str]))) end ;
|
|
489 |
\end{verbatim}
|
|
490 |
*}
|
|
491 |
|
|
492 |
section{* Attributes, and the \texttt{Attrib} structure *}
|
|
493 |
|
|
494 |
text {*
|
|
495 |
The type \texttt{attribute} is declared in \texttt{src/Pure/thm.ML}.
|
|
496 |
The source file for the \texttt{Attrib} structure is
|
|
497 |
\texttt{src/Pure/Isar/attrib.ML}.
|
|
498 |
Most attributes use a theorem to change a generic context (for example,
|
|
499 |
by declaring that the theorem should be used, by default, in simplification),
|
|
500 |
or change a theorem (which most often involves referring to the current
|
|
501 |
theory).
|
|
502 |
The functions \texttt{Thm.rule\_attribute} and
|
|
503 |
\texttt{Thm.declaration\_attribute} create attributes of these kinds.
|
|
504 |
|
|
505 |
\begin{verbatim}
|
|
506 |
type attribute = Context.generic * thm -> Context.generic * thm;
|
|
507 |
type 'a trf = 'a -> 'a ; (* transformer of a given type *)
|
|
508 |
Thm.rule_attribute : (Context.generic -> thm -> thm) -> attribute ;
|
|
509 |
Thm.declaration_attribute : (thm -> Context.generic trf) -> attribute ;
|
|
510 |
|
|
511 |
Attrib.print_attributes : theory -> unit ;
|
|
512 |
Attrib.pretty_attribs : Proof.context -> src list -> Pretty.T list ;
|
|
513 |
|
|
514 |
List.app Pretty.writeln (Attrib.pretty_attribs ctxt ass) ;
|
|
515 |
\end{verbatim}
|
|
516 |
|
|
517 |
An attribute is stored in a theory as indicated by:
|
|
518 |
\begin{verbatim}
|
|
519 |
Attrib.add_attributes :
|
|
520 |
(bstring * (src -> attribute) * string) list -> theory trf ;
|
|
521 |
(*
|
|
522 |
Attrib.add_attributes [("THEN", THEN_att, "resolution with rule")] ;
|
|
523 |
*)
|
|
524 |
\end{verbatim}
|
|
525 |
where the first and third arguments are name and description of the attribute,
|
|
526 |
and the second is a function which parses the attribute input text
|
|
527 |
(including the attribute name, which has necessarily already been parsed).
|
|
528 |
Here, \texttt{THEN\_att} is a function declared in the code for the
|
|
529 |
structure \texttt{Attrib}, but not published in its signature.
|
|
530 |
The source file \texttt{src/Pure/Isar/attrib.ML} shows the use of
|
|
531 |
\texttt{Attrib.add\_attributes} to add a number of attributes.
|
|
532 |
|
|
533 |
\begin{verbatim}
|
|
534 |
FullAttrib.THEN_att : src -> attribute ;
|
|
535 |
FullAttrib.THEN_att atsrc (generic, ML_Context.thm "sym") ;
|
|
536 |
FullAttrib.THEN_att atsrc (generic, ML_Context.thm "all_comm") ;
|
|
537 |
\end{verbatim}
|
|
538 |
|
|
539 |
\begin{verbatim}
|
|
540 |
Attrib.syntax : attribute cgatlp -> src -> attribute ;
|
|
541 |
Attrib.no_args : attribute -> src -> attribute ;
|
|
542 |
\end{verbatim}
|
|
543 |
When this is called as \texttt{syntax scan src (gc, th)}
|
|
544 |
the generic context \texttt{gc} is used
|
|
545 |
(and potentially changed to \texttt{gc'})
|
|
546 |
by \texttt{scan} in parsing to obtain an attribute \texttt{attr} which would
|
|
547 |
then be applied to \texttt{(gc', th)}.
|
|
548 |
The source for parsing the attribute is the arguments part of \texttt{src},
|
|
549 |
which must all be consumed by the parse.
|
|
550 |
|
|
551 |
For example, for \texttt{Attrib.no\_args attr src}, the attribute parser
|
|
552 |
simply returns \texttt{attr}, requiring that the arguments part of
|
|
553 |
\texttt{src} must be empty.
|
|
554 |
|
|
555 |
Some examples from \texttt{src/Pure/Isar/attrib.ML}, modified:
|
|
556 |
\begin{verbatim}
|
|
557 |
fun rot_att_n n (gc, th) = (gc, rotate_prems n th) ;
|
|
558 |
rot_att_n : int -> attribute ;
|
|
559 |
val rot_arg = Scan.lift (Scan.optional Args.int 1 : int atlp) : int cgatlp ;
|
|
560 |
val rotated_att : src -> attribute =
|
|
561 |
Attrib.syntax (rot_arg >> rot_att_n : attribute cgatlp) ;
|
|
562 |
|
|
563 |
val THEN_arg : int cgatlp = Scan.lift
|
|
564 |
(Scan.optional (Args.bracks Args.nat : int atlp) 1 : int atlp) ;
|
|
565 |
|
|
566 |
Attrib.thm : thm cgatlp ;
|
|
567 |
|
|
568 |
THEN_arg -- Attrib.thm : (int * thm) cgatlp ;
|
|
569 |
|
|
570 |
fun THEN_att_n (n, tht) (gc, th) = (gc, th RSN (n, tht)) ;
|
|
571 |
THEN_att_n : int * thm -> attribute ;
|
|
572 |
|
|
573 |
val THEN_att : src -> attribute = Attrib.syntax
|
|
574 |
(THEN_arg -- Attrib.thm >> THEN_att_n : attribute cgatlp);
|
|
575 |
\end{verbatim}
|
|
576 |
The functions I've called \texttt{rot\_arg} and \texttt{THEN\_arg}
|
|
577 |
read an optional argument, which for \texttt{rotated} is an integer,
|
|
578 |
and for \texttt{THEN} is a natural enclosed in square brackets;
|
|
579 |
the default, if the argument is absent, is 1 in each case.
|
|
580 |
Functions \texttt{rot\_att\_n} and \texttt{THEN\_att\_n} turn these into
|
|
581 |
attributes, where \texttt{THEN\_att\_n} also requires a theorem, which is
|
|
582 |
parsed by \texttt{Attrib.thm}.
|
|
583 |
Infix operators \texttt{--} and \texttt{>>} are in the structure \texttt{Scan}.
|
|
584 |
|
|
585 |
*}
|
|
586 |
|
|
587 |
section{* Methods, and the \texttt{Method} structure *}
|
|
588 |
|
|
589 |
text {*
|
|
590 |
The source file is \texttt{src/Pure/Isar/method.ML}.
|
|
591 |
The type \texttt{method} is defined by the datatype declaration
|
|
592 |
\begin{verbatim}
|
|
593 |
(* datatype method = Meth of thm list -> cases_tactic; *)
|
|
594 |
RuleCases.NO_CASES : tactic -> cases_tactic ;
|
|
595 |
\end{verbatim}
|
|
596 |
In fact \texttt{RAW\_METHOD\_CASES} (below) is exactly the constructor
|
|
597 |
\texttt{Meth}.
|
|
598 |
A \texttt{cases\_tactic} is an elaborated version of a tactic.
|
|
599 |
\texttt{NO\_CASES tac} is a \texttt{cases\_tactic} which consists of a
|
|
600 |
\texttt{cases\_tactic} without any further case information.
|
|
601 |
For further details see the description of structure \texttt{RuleCases} below.
|
|
602 |
The list of theorems to be passed to a method consists of the current
|
|
603 |
\emph{facts} in the proof.
|
|
604 |
|
|
605 |
\begin{verbatim}
|
|
606 |
RAW_METHOD : (thm list -> tactic) -> method ;
|
|
607 |
METHOD : (thm list -> tactic) -> method ;
|
|
608 |
|
|
609 |
SIMPLE_METHOD : tactic -> method ;
|
|
610 |
SIMPLE_METHOD' : (int -> tactic) -> method ;
|
|
611 |
SIMPLE_METHOD'' : ((int -> tactic) -> tactic) -> (int -> tactic) -> method ;
|
|
612 |
|
|
613 |
RAW_METHOD_CASES : (thm list -> cases_tactic) -> method ;
|
|
614 |
METHOD_CASES : (thm list -> cases_tactic) -> method ;
|
|
615 |
\end{verbatim}
|
|
616 |
A method is, in its simplest form, a tactic; applying the method is to apply
|
|
617 |
the tactic to the current goal state.
|
|
618 |
|
|
619 |
Applying \texttt{RAW\_METHOD tacf} creates a tactic by applying
|
|
620 |
\texttt{tacf} to the current {facts}, and applying that tactic to the
|
|
621 |
goal state.
|
|
622 |
|
|
623 |
\texttt{METHOD} is similar but also first applies
|
|
624 |
\texttt{Goal.conjunction\_tac} to all subgoals.
|
|
625 |
|
|
626 |
\texttt{SIMPLE\_METHOD tac} inserts the facts into all subgoals and then
|
|
627 |
applies \texttt{tacf}.
|
|
628 |
|
|
629 |
\texttt{SIMPLE\_METHOD' tacf} inserts the facts and then
|
|
630 |
applies \texttt{tacf} to subgoal 1.
|
|
631 |
|
|
632 |
\texttt{SIMPLE\_METHOD'' quant tacf} does this for subgoal(s) selected by
|
|
633 |
\texttt{quant}, which may be, for example,
|
|
634 |
\texttt{ALLGOALS} (all subgoals),
|
|
635 |
\texttt{TRYALL} (try all subgoals, failure is OK),
|
|
636 |
\texttt{FIRSTGOAL} (try subgoals until it succeeds once),
|
|
637 |
\texttt{(fn tacf => tacf 4)} (subgoal 4), etc
|
|
638 |
(see the \texttt{Tactical} structure, \cite[Chapter 4]{ref}).
|
|
639 |
|
|
640 |
A method is stored in a theory as indicated by:
|
|
641 |
\begin{verbatim}
|
|
642 |
Method.add_method :
|
|
643 |
(bstring * (src -> Proof.context -> method) * string) -> theory trf ;
|
|
644 |
( *
|
|
645 |
* )
|
|
646 |
\end{verbatim}
|
|
647 |
where the first and third arguments are name and description of the method,
|
|
648 |
and the second is a function which parses the method input text
|
|
649 |
(including the method name, which has necessarily already been parsed).
|
|
650 |
|
|
651 |
Here, \texttt{xxx} is a function declared in the code for the
|
|
652 |
structure \texttt{Method}, but not published in its signature.
|
|
653 |
The source file \texttt{src/Pure/Isar/method.ML} shows the use of
|
|
654 |
\texttt{Method.add\_method} to add a number of methods.
|
|
655 |
|
|
656 |
|
|
657 |
*}
|
|
658 |
|
|
659 |
|
|
660 |
end |