18 val is_digit: symbol -> bool |
18 val is_digit: symbol -> bool |
19 val is_quasi_letter: symbol -> bool |
19 val is_quasi_letter: symbol -> bool |
20 val is_letdig: symbol -> bool |
20 val is_letdig: symbol -> bool |
21 val is_blank: symbol -> bool |
21 val is_blank: symbol -> bool |
22 val is_printable: symbol -> bool |
22 val is_printable: symbol -> bool |
|
23 val length: symbol list -> int |
23 val beginning: symbol list -> string |
24 val beginning: symbol list -> string |
24 val scan: string list -> symbol * string list |
25 val scan: string list -> symbol * string list |
25 val explode: string -> symbol list |
|
26 val length: symbol list -> int |
|
27 val size: string -> int |
|
28 val input: string -> string |
|
29 val output: string -> string |
|
30 val source: bool -> (string, 'a) Source.source -> |
26 val source: bool -> (string, 'a) Source.source -> |
31 (symbol, (string, 'a) Source.source) Source.source |
27 (symbol, (string, 'a) Source.source) Source.source |
|
28 val explode: string -> symbol list |
|
29 val input: string -> string |
32 val use: Path.T -> unit |
30 val use: Path.T -> unit |
|
31 val add_mode: string -> (string -> string * real) -> unit |
|
32 val output: string -> string |
|
33 val output_width: string -> string * real |
33 end; |
34 end; |
34 |
35 |
35 structure Symbol: SYMBOL = |
36 structure Symbol: SYMBOL = |
36 struct |
37 struct |
37 |
38 |
38 |
39 |
39 (** encoding table (isabelle-0) **) |
40 (** generalized characters **) |
|
41 |
|
42 (*symbols, which are considered the smallest entities of any Isabelle |
|
43 string, may be of the following form: |
|
44 (a) ASCII symbols: a |
|
45 (b) printable symbols: \<ident> |
|
46 (c) control symbols: \<^ident> |
|
47 |
|
48 input may include non-ASCII characters according to isabelle-0 encoding; |
|
49 output is subject to the print_mode variable (default: verbatim); |
|
50 *) |
|
51 |
|
52 type symbol = string; |
|
53 |
|
54 val space = " "; |
|
55 val eof = ""; |
|
56 |
|
57 |
|
58 (* kinds *) |
|
59 |
|
60 fun is_eof s = s = eof; |
|
61 fun not_eof s = s <> eof; |
|
62 val stopper = (eof, is_eof); |
|
63 |
|
64 fun is_ascii s = size s = 1 andalso ord s < 128; |
|
65 |
|
66 fun is_letter s = |
|
67 size s = 1 andalso |
|
68 (ord "A" <= ord s andalso ord s <= ord "Z" orelse |
|
69 ord "a" <= ord s andalso ord s <= ord "z"); |
|
70 |
|
71 fun is_digit s = |
|
72 size s = 1 andalso ord "0" <= ord s andalso ord s <= ord "9"; |
|
73 |
|
74 fun is_quasi_letter "_" = true |
|
75 | is_quasi_letter "'" = true |
|
76 | is_quasi_letter s = is_letter s; |
|
77 |
|
78 val is_blank = |
|
79 fn " " => true | "\t" => true | "\n" => true | "\^L" => true |
|
80 | "\160" => true | "\\<spacespace>" => true |
|
81 | _ => false; |
|
82 |
|
83 val is_letdig = is_quasi_letter orf is_digit; |
|
84 |
|
85 fun is_printable s = |
|
86 size s = 1 andalso ord space <= ord s andalso ord s <= ord "~" orelse |
|
87 size s > 2 andalso nth_elem (2, explode s) <> "^"; |
|
88 |
|
89 fun sym_length ss = foldl (fn (n, s) => if is_printable s then n + 1 else n) (0, ss); |
|
90 |
|
91 |
|
92 (* beginning *) |
|
93 |
|
94 val smash_blanks = map (fn s => if is_blank s then space else s); |
|
95 |
|
96 fun beginning raw_ss = |
|
97 let |
|
98 val (all_ss, _) = take_suffix is_blank raw_ss; |
|
99 val dots = if length all_ss > 10 then " ..." else ""; |
|
100 val (ss, _) = take_suffix is_blank (take (10, all_ss)); |
|
101 in implode (smash_blanks ss) ^ dots end; |
|
102 |
|
103 |
|
104 |
|
105 (** isabelle-0 encoding table **) |
40 |
106 |
41 val enc_start = 160; |
107 val enc_start = 160; |
42 val enc_end = 255; |
108 val enc_end = 255; |
43 |
109 |
44 val enc_vector = |
110 val enc_vector = |
163 None => c |
229 None => c |
164 | Some s => "\\" ^ s); |
230 | Some s => "\\" ^ s); |
165 |
231 |
166 |
232 |
167 |
233 |
168 (** type symbol **) |
234 (** symbol input **) |
169 |
|
170 type symbol = string; |
|
171 |
|
172 val space = " "; |
|
173 val eof = ""; |
|
174 |
|
175 |
|
176 (* kinds *) |
|
177 |
|
178 fun is_eof s = s = eof; |
|
179 fun not_eof s = s <> eof; |
|
180 val stopper = (eof, is_eof); |
|
181 |
|
182 fun is_ascii s = size s = 1 andalso ord s < 128; |
|
183 |
|
184 fun is_letter s = |
|
185 size s = 1 andalso |
|
186 (ord "A" <= ord s andalso ord s <= ord "Z" orelse |
|
187 ord "a" <= ord s andalso ord s <= ord "z"); |
|
188 |
|
189 fun is_digit s = |
|
190 size s = 1 andalso ord "0" <= ord s andalso ord s <= ord "9"; |
|
191 |
|
192 fun is_quasi_letter "_" = true |
|
193 | is_quasi_letter "'" = true |
|
194 | is_quasi_letter s = is_letter s; |
|
195 |
|
196 val is_blank = |
|
197 fn " " => true | "\t" => true | "\n" => true | "\^L" => true |
|
198 | "\160" => true | "\\<spacespace>" => true |
|
199 | _ => false; |
|
200 |
|
201 val is_letdig = is_quasi_letter orf is_digit; |
|
202 |
|
203 fun is_printable s = |
|
204 size s = 1 andalso ord space <= ord s andalso ord s <= ord "~" orelse |
|
205 size s > 2 andalso nth_elem (2, explode s) <> "^"; |
|
206 |
|
207 |
|
208 (* beginning *) |
|
209 |
|
210 val smash_blanks = map (fn s => if is_blank s then space else s); |
|
211 |
|
212 fun beginning raw_ss = |
|
213 let |
|
214 val (all_ss, _) = take_suffix is_blank raw_ss; |
|
215 val dots = if length all_ss > 10 then " ..." else ""; |
|
216 val (ss, _) = take_suffix is_blank (take (10, all_ss)); |
|
217 in implode (smash_blanks ss) ^ dots end; |
|
218 |
|
219 |
235 |
220 (* scan *) |
236 (* scan *) |
221 |
237 |
222 val scan_id = Scan.one is_letter ^^ (Scan.any is_letdig >> implode); |
238 val scan_id = Scan.one is_letter ^^ (Scan.any is_letdig >> implode); |
223 |
239 |
247 if no_syms chs then chs (*tune trivial case*) |
263 if no_syms chs then chs (*tune trivial case*) |
248 else map symbol (the (Scan.read stopper (Scan.repeat scan) chs)) |
264 else map symbol (the (Scan.read stopper (Scan.repeat scan) chs)) |
249 end; |
265 end; |
250 |
266 |
251 |
267 |
252 (* printable length *) |
268 (* input *) |
253 |
|
254 fun sym_length ss = foldl (fn (n, c) => if is_printable c then n + 1 else n) (0, ss); |
|
255 val sym_size = sym_length o sym_explode; |
|
256 |
|
257 |
|
258 (* input / output *) |
|
259 |
269 |
260 fun input str = |
270 fun input str = |
261 let val chs = explode str in |
271 let val chs = explode str in |
262 if forall (fn c => ord c < enc_start) chs then str |
272 if forall (fn c => ord c < enc_start) chs then str |
263 else implode (map symbol' chs) |
273 else implode (map symbol' chs) |
264 end; |
274 end; |
265 |
275 |
266 fun char' s = if size s > 1 then "\\" ^ s else s; |
|
267 fun output s = let val chr = (* if "isabelle_font" mem_string !print_mode *) |
|
268 (* FIXME: does not work yet, because of static calls to output in printer.ML *) |
|
269 (* then *) char (* else char'*) |
|
270 in (implode o map chr o sym_explode) s end; |
|
271 |
|
272 |
276 |
273 (* version of 'use' with input filtering *) |
277 (* version of 'use' with input filtering *) |
274 |
278 |
275 val use = |
279 val use = |
276 if not needs_filtered_use then File.use |
280 if not needs_filtered_use then File.use (*ML system (wrongly!) accepts non-ASCII*) |
277 else |
281 else |
278 fn path => |
282 fn path => |
279 let |
283 let |
280 val txt = File.read path; |
284 val txt = File.read path; |
281 val txt_out = input txt; |
285 val txt_out = input txt; |
288 File.rm tmp_path |
292 File.rm tmp_path |
289 end |
293 end |
290 end; |
294 end; |
291 |
295 |
292 |
296 |
|
297 |
|
298 (** symbol output **) |
|
299 |
|
300 (* default_output *) |
|
301 |
|
302 fun string_size s = (s, real (size s)); |
|
303 |
|
304 fun default_output s = |
|
305 let val cs = explode s in (*sic!*) |
|
306 if not (exists (equal "\\") cs) then string_size s |
|
307 else string_size (implode (map (fn "\\" => "\\\\" | c => c) cs)) |
|
308 end; |
|
309 |
|
310 |
|
311 (* isabelle_font_output *) |
|
312 |
|
313 fun isabelle_font_output s = |
|
314 let val cs = sym_explode s |
|
315 in (implode (map char cs), real (sym_length cs)) end; |
|
316 |
|
317 |
|
318 (* maintain modes *) |
|
319 |
|
320 val modes = ref (Symtab.make [("isabelle_font", isabelle_font_output)]); |
|
321 |
|
322 fun lookup_mode name = Symtab.lookup (! modes, name); |
|
323 |
|
324 fun add_mode name f = |
|
325 (if is_none (lookup_mode name) then () |
|
326 else warning ("Duplicate declaration of symbol print mode " ^ quote name); |
|
327 modes := Symtab.update ((name, f), ! modes)); |
|
328 |
|
329 |
|
330 (* mode output *) |
|
331 |
|
332 fun output_width s = |
|
333 (case get_first lookup_mode (! print_mode) of |
|
334 None => default_output s |
|
335 | Some f => f s); |
|
336 |
|
337 val output = #1 o output_width; |
|
338 |
|
339 |
293 (*final declarations of this structure!*) |
340 (*final declarations of this structure!*) |
|
341 val length = sym_length; |
294 val explode = sym_explode; |
342 val explode = sym_explode; |
295 val length = sym_length; |
343 |
296 val size = sym_size; |
|
297 |
344 |
298 end; |
345 end; |