author | wenzelm |
Wed, 20 Feb 2002 00:53:53 +0100 | |
changeset 12902 | a23dc0b7566f |
parent 12116 | 4027b15377a5 |
child 12904 | c208d71702d1 |
permissions | -rw-r--r-- |
6118 | 1 |
(* Title: Pure/General/symbol.ML |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
2 |
ID: $Id$ |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
3 |
Author: Markus Wenzel, TU Muenchen |
8806 | 4 |
License: GPL (GNU GENERAL PUBLIC LICENSE) |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
5 |
|
12116 | 6 |
Generalized characters with infinitely many named symbols. |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
7 |
*) |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
8 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
9 |
signature SYMBOL = |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
10 |
sig |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
11 |
type symbol |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
12 |
val space: symbol |
10953 | 13 |
val spaces: int -> symbol |
6857 | 14 |
val sync: symbol |
15 |
val is_sync: symbol -> bool |
|
16 |
val not_sync: symbol -> bool |
|
10747 | 17 |
val malformed: symbol |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
18 |
val eof: symbol |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
19 |
val is_eof: symbol -> bool |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
20 |
val not_eof: symbol -> bool |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
21 |
val stopper: symbol * (symbol -> bool) |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
22 |
val is_ascii: symbol -> bool |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
23 |
val is_letter: symbol -> bool |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
24 |
val is_digit: symbol -> bool |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
25 |
val is_quasi_letter: symbol -> bool |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
26 |
val is_letdig: symbol -> bool |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
27 |
val is_blank: symbol -> bool |
8230 | 28 |
val is_symbolic: symbol -> bool |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
29 |
val is_printable: symbol -> bool |
6272 | 30 |
val length: symbol list -> int |
11010 | 31 |
val strip_blanks: string -> string |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
32 |
val beginning: symbol list -> string |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
33 |
val scan: string list -> symbol * string list |
6640 | 34 |
val scanner: string -> (symbol list -> 'a * symbol list) -> symbol list -> 'a |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
35 |
val source: bool -> (string, 'a) Source.source -> |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
36 |
(symbol, (string, 'a) Source.source) Source.source |
6272 | 37 |
val explode: string -> symbol list |
10953 | 38 |
val default_indent: string * int -> string |
39 |
val add_mode: string -> (string -> string * real) * (string * int -> string) -> unit |
|
6692 | 40 |
val symbolsN: string |
41 |
val xsymbolsN: string |
|
10923 | 42 |
val plain_output: string -> string |
6272 | 43 |
val output: string -> string |
44 |
val output_width: string -> string * real |
|
10953 | 45 |
val indent: string * int -> string |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
46 |
end; |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
47 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
48 |
structure Symbol: SYMBOL = |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
49 |
struct |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
50 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
51 |
|
6272 | 52 |
(** generalized characters **) |
53 |
||
54 |
(*symbols, which are considered the smallest entities of any Isabelle |
|
55 |
string, may be of the following form: |
|
56 |
(a) ASCII symbols: a |
|
57 |
(b) printable symbols: \<ident> |
|
58 |
(c) control symbols: \<^ident> |
|
59 |
||
12116 | 60 |
output is subject to the print_mode variable (default: verbatim), |
61 |
actual interpretation in display is up to front-end tools; |
|
6272 | 62 |
*) |
63 |
||
64 |
type symbol = string; |
|
65 |
||
66 |
val space = " "; |
|
10953 | 67 |
fun spaces k = Library.replicate_string k space; |
6857 | 68 |
val sync = "\\<^sync>"; |
10747 | 69 |
val malformed = "\\<^malformed>"; |
6272 | 70 |
val eof = ""; |
71 |
||
72 |
||
73 |
(* kinds *) |
|
74 |
||
6857 | 75 |
fun is_sync s = s = sync; |
76 |
fun not_sync s = s <> sync; |
|
77 |
||
6272 | 78 |
fun is_eof s = s = eof; |
79 |
fun not_eof s = s <> eof; |
|
80 |
val stopper = (eof, is_eof); |
|
81 |
||
82 |
fun is_ascii s = size s = 1 andalso ord s < 128; |
|
83 |
||
84 |
fun is_letter s = |
|
85 |
size s = 1 andalso |
|
86 |
(ord "A" <= ord s andalso ord s <= ord "Z" orelse |
|
87 |
ord "a" <= ord s andalso ord s <= ord "z"); |
|
88 |
||
89 |
fun is_digit s = |
|
90 |
size s = 1 andalso ord "0" <= ord s andalso ord s <= ord "9"; |
|
91 |
||
92 |
fun is_quasi_letter "_" = true |
|
93 |
| is_quasi_letter "'" = true |
|
94 |
| is_quasi_letter s = is_letter s; |
|
95 |
||
96 |
val is_blank = |
|
97 |
fn " " => true | "\t" => true | "\n" => true | "\^L" => true |
|
98 |
| "\160" => true | "\\<spacespace>" => true |
|
99 |
| _ => false; |
|
100 |
||
101 |
val is_letdig = is_quasi_letter orf is_digit; |
|
102 |
||
8230 | 103 |
fun is_symbolic s = |
104 |
size s > 2 andalso nth_elem_string (2, s) <> "^"; |
|
105 |
||
6272 | 106 |
fun is_printable s = |
107 |
size s = 1 andalso ord space <= ord s andalso ord s <= ord "~" orelse |
|
8230 | 108 |
is_symbolic s; |
109 |
||
6272 | 110 |
|
10738 | 111 |
fun sym_length ss = foldl (fn (n, s) => |
112 |
(if not (is_printable s) then 0 else |
|
113 |
(case Library.try String.substring (s, 2, 4) of |
|
114 |
Some s' => if s' = "long" orelse s' = "Long" then 2 else 1 |
|
115 |
| None => 1)) + n) (0, ss); |
|
6272 | 116 |
|
11010 | 117 |
fun strip_blanks s = |
118 |
implode (#1 (Library.take_suffix is_blank (#2 (Library.take_prefix is_blank (explode s))))); |
|
119 |
||
6272 | 120 |
|
121 |
(* beginning *) |
|
122 |
||
123 |
val smash_blanks = map (fn s => if is_blank s then space else s); |
|
124 |
||
125 |
fun beginning raw_ss = |
|
126 |
let |
|
127 |
val (all_ss, _) = take_suffix is_blank raw_ss; |
|
128 |
val dots = if length all_ss > 10 then " ..." else ""; |
|
129 |
val (ss, _) = take_suffix is_blank (take (10, all_ss)); |
|
130 |
in implode (smash_blanks ss) ^ dots end; |
|
131 |
||
132 |
||
133 |
||
8998 | 134 |
(** scanning through symbols **) |
6640 | 135 |
|
136 |
fun scanner msg scan chs = |
|
137 |
let |
|
138 |
fun err_msg cs = msg ^ ": " ^ beginning cs; |
|
139 |
val fin_scan = Scan.error (Scan.finite stopper (!! (fn (cs, _) => err_msg cs) scan)); |
|
140 |
in |
|
141 |
(case fin_scan chs of |
|
142 |
(result, []) => result |
|
143 |
| (_, rest) => error (err_msg rest)) |
|
144 |
end; |
|
145 |
||
146 |
||
147 |
||
6272 | 148 |
(** symbol input **) |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
149 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
150 |
(* scan *) |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
151 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
152 |
val scan_id = Scan.one is_letter ^^ (Scan.any is_letdig >> implode); |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
153 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
154 |
val scan = |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
155 |
($$ "\\" --| Scan.optional ($$ "\\") "") ^^ $$ "<" ^^ |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
156 |
!! (fn (cs, _) => "Malformed symbolic character specification: \\" ^ "<" ^ beginning cs) |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
157 |
(Scan.optional ($$ "^") "" ^^ scan_id ^^ $$ ">") || |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
158 |
Scan.one not_eof; |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
159 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
160 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
161 |
(* source *) |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
162 |
|
10747 | 163 |
val recover = Scan.any ((not o is_blank) andf not_eof) >> K [malformed]; |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
164 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
165 |
fun source do_recover src = |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
166 |
Source.source stopper (Scan.bulk scan) (if do_recover then Some recover else None) src; |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
167 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
168 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
169 |
(* explode *) |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
170 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
171 |
fun no_syms [] = true |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
172 |
| no_syms ("\\" :: "<" :: _) = false |
12116 | 173 |
| no_syms (_ :: cs) = no_syms cs; |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
174 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
175 |
fun sym_explode str = |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
176 |
let val chs = explode str in |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
177 |
if no_syms chs then chs (*tune trivial case*) |
12116 | 178 |
else the (Scan.read stopper (Scan.repeat scan) chs) |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
179 |
end; |
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
180 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
181 |
|
6272 | 182 |
|
183 |
(** symbol output **) |
|
184 |
||
10953 | 185 |
(* default *) |
6272 | 186 |
|
187 |
fun string_size s = (s, real (size s)); |
|
188 |
||
189 |
fun default_output s = |
|
6320 | 190 |
if not (exists_string (equal "\\") s) then string_size s |
10738 | 191 |
else string_size (implode (map (fn "\\" => "\\\\" | c => c) (explode s))); (*sic!*) |
6272 | 192 |
|
10953 | 193 |
fun default_indent (_: string, k) = spaces k; |
6272 | 194 |
|
10953 | 195 |
|
6272 | 196 |
(* maintain modes *) |
197 |
||
6692 | 198 |
val symbolsN = "symbols"; |
199 |
val xsymbolsN = "xsymbols"; |
|
200 |
||
12116 | 201 |
val modes = |
202 |
ref (Symtab.empty: ((string -> string * real) * (string * int -> string)) Symtab.table); |
|
6272 | 203 |
|
204 |
fun lookup_mode name = Symtab.lookup (! modes, name); |
|
205 |
||
10953 | 206 |
fun add_mode name m = |
6272 | 207 |
(if is_none (lookup_mode name) then () |
6320 | 208 |
else warning ("Redeclaration of symbol print mode " ^ quote name); |
10953 | 209 |
modes := Symtab.update ((name, m), ! modes)); |
210 |
||
211 |
fun get_mode () = |
|
212 |
if_none (get_first lookup_mode (! print_mode)) (default_output, default_indent); |
|
6272 | 213 |
|
214 |
||
215 |
(* mode output *) |
|
216 |
||
10953 | 217 |
fun output_width x = #1 (get_mode ()) x; |
6272 | 218 |
val output = #1 o output_width; |
10923 | 219 |
val plain_output = #1 o default_output; |
6272 | 220 |
|
10953 | 221 |
fun indent x = #2 (get_mode ()) x; |
222 |
||
6272 | 223 |
|
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
224 |
(*final declarations of this structure!*) |
6272 | 225 |
val length = sym_length; |
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
226 |
val explode = sym_explode; |
6272 | 227 |
|
6116
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
228 |
|
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff
changeset
|
229 |
end; |