author | nipkow |
Sun, 30 Mar 1997 13:40:38 +0200 | |
changeset 2847 | 6226b83ce2d8 |
parent 2672 | 85d7e800d754 |
child 4483 | caf8ae95c61f |
permissions | -rw-r--r-- |
234 | 1 |
(* Title: Pure/symtab.ML |
0 | 2 |
ID: $Id$ |
234 | 3 |
Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
0 | 4 |
Copyright 1989 University of Cambridge |
5 |
||
234 | 6 |
Unbalanced binary trees indexed by strings; no way to delete an entry. |
0 | 7 |
*) |
8 |
||
234 | 9 |
signature SYMTAB = |
0 | 10 |
sig |
234 | 11 |
exception DUPLICATE of string |
374 | 12 |
exception DUPS of string list |
234 | 13 |
type 'a table |
14 |
val null: 'a table |
|
15 |
val is_null: 'a table -> bool |
|
16 |
val lookup: 'a table * string -> 'a option |
|
563 | 17 |
val find_first: (string * 'a -> bool) -> 'a table -> (string * 'a) option |
234 | 18 |
val update: (string * 'a) * 'a table -> 'a table |
19 |
val update_new: (string * 'a) * 'a table -> 'a table |
|
563 | 20 |
val map: ('a -> 'b) -> 'a table -> 'b table |
234 | 21 |
val balance: 'a table -> 'a table |
22 |
val st_of_declist: (string list * 'a) list * 'a table -> 'a table |
|
374 | 23 |
val make: (string * 'a) list -> 'a table |
24 |
val dest: 'a table -> (string * 'a) list |
|
234 | 25 |
val extend: ('a * 'a -> bool) -> 'a table * (string * 'a) list -> 'a table |
374 | 26 |
val extend_new: 'a table * (string * 'a) list -> 'a table |
234 | 27 |
val merge: ('a * 'a -> bool) -> 'a table * 'a table -> 'a table |
28 |
val lookup_multi: 'a list table * string -> 'a list |
|
29 |
val make_multi: (string * 'a) list -> 'a list table |
|
30 |
val dest_multi: 'a list table -> (string * 'a) list |
|
0 | 31 |
end; |
32 |
||
1415 | 33 |
structure Symtab: SYMTAB = |
0 | 34 |
struct |
35 |
||
36 |
(*symbol table errors, such as from update_new*) |
|
37 |
exception DUPLICATE of string; |
|
374 | 38 |
exception DUPS of string list; |
0 | 39 |
|
234 | 40 |
datatype 'a table = Tip | Branch of (string * 'a * 'a table * 'a table); |
0 | 41 |
|
42 |
||
43 |
val null = Tip; |
|
44 |
||
45 |
fun is_null Tip = true |
|
46 |
| is_null _ = false; |
|
47 |
||
48 |
||
234 | 49 |
fun lookup (symtab: 'a table, key: string) : 'a option = |
0 | 50 |
let fun look Tip = None |
234 | 51 |
| look (Branch (key', entry, left, right)) = |
52 |
if key < key' then look left |
|
53 |
else if key' < key then look right |
|
54 |
else Some entry |
|
0 | 55 |
in look symtab end; |
56 |
||
475 | 57 |
|
563 | 58 |
fun find_first _ Tip = None |
59 |
| find_first pred (Branch (key, entry, left, right)) = |
|
60 |
(case find_first pred left of |
|
61 |
None => |
|
62 |
if pred (key, entry) then Some (key, entry) |
|
63 |
else find_first pred right |
|
64 |
| some => some); |
|
65 |
||
66 |
||
0 | 67 |
(*update, allows overwriting of an entry*) |
68 |
fun update ((key: string, entry: 'a), symtab : 'a table) |
|
69 |
: 'a table = |
|
234 | 70 |
let fun upd Tip = Branch (key, entry, Tip, Tip) |
71 |
| upd (Branch(key', entry', left, right)) = |
|
72 |
if key < key' then Branch (key', entry', upd left, right) |
|
73 |
else if key' < key then Branch (key', entry', left, upd right) |
|
74 |
else Branch (key, entry, left, right) |
|
0 | 75 |
in upd symtab end; |
76 |
||
1415 | 77 |
(*Like update but fails if key is already defined in table.*) |
0 | 78 |
fun update_new ((key: string, entry: 'a), symtab : 'a table) |
79 |
: 'a table = |
|
234 | 80 |
let fun upd Tip = Branch (key, entry, Tip, Tip) |
81 |
| upd (Branch(key', entry', left, right)) = |
|
82 |
if key < key' then Branch (key', entry', upd left, right) |
|
83 |
else if key' < key then Branch (key', entry', left, upd right) |
|
84 |
else raise DUPLICATE(key) |
|
0 | 85 |
in upd symtab end; |
86 |
||
475 | 87 |
|
0 | 88 |
(*conversion of symbol table to sorted association list*) |
1415 | 89 |
fun dest (symtab : 'a table) : (string * 'a) list = |
234 | 90 |
let fun ali (symtab, cont) = case symtab of |
91 |
Tip => cont |
|
92 |
| Branch (key, entry, left, right) => |
|
93 |
ali(left, (key, entry) :: ali(right, cont)) |
|
94 |
in ali (symtab, []) end; |
|
0 | 95 |
|
96 |
||
97 |
(*Make a balanced tree of the first n members of the sorted alist (sal). |
|
98 |
Utility for the function balance.*) |
|
99 |
fun bal_of (sal, 0) = Tip |
|
100 |
| bal_of (sal, n) = |
|
101 |
let val mid = n div 2 |
|
234 | 102 |
in case drop (mid, sal) of |
103 |
[] => bal_of (sal, mid) (*should not occur*) |
|
104 |
| ((key, entry):: pairs) => |
|
105 |
Branch(key, entry, bal_of(sal, mid), bal_of(pairs, n-mid-1)) |
|
0 | 106 |
end; |
107 |
||
108 |
||
109 |
fun balance symtab = |
|
1415 | 110 |
let val sal = dest symtab |
0 | 111 |
in bal_of (sal, length sal) end; |
112 |
||
113 |
||
114 |
(*A "declaration" associates the same entry with a list of keys; |
|
115 |
does not allow overwriting of an entry*) |
|
116 |
fun decl_update_new ((keys : string list, entry: 'a), symtab) |
|
117 |
: 'a table = |
|
234 | 118 |
let fun decl (key, symtab) = update_new ((key, entry), symtab) |
119 |
in foldr decl (keys, symtab) end; |
|
0 | 120 |
|
121 |
(*Addition of a list of declarations to a symbol table*) |
|
122 |
fun st_of_declist (dl, symtab) = |
|
234 | 123 |
balance (foldr decl_update_new (dl, symtab)); |
124 |
||
125 |
||
374 | 126 |
(* make, extend, merge tables *) |
234 | 127 |
|
128 |
fun eq_pair eq ((key1, entry1), (key2, entry2)) = |
|
129 |
key1 = key2 andalso eq (entry1, entry2); |
|
130 |
||
374 | 131 |
fun make alst = |
132 |
(case gen_duplicates eq_fst alst of |
|
1415 | 133 |
[] => balance (foldr update_new (alst, Tip)) |
374 | 134 |
| dups => raise DUPS (map fst dups)); |
234 | 135 |
|
136 |
fun extend eq (tab, alst) = |
|
374 | 137 |
generic_extend (eq_pair eq) dest make tab alst; |
138 |
||
2228
f381c1a98209
Eta-expansion of a function definition, for value polymorphism
paulson
parents:
1415
diff
changeset
|
139 |
fun extend_new (tab, alst) = extend (K false) (tab, alst); |
234 | 140 |
|
141 |
fun merge eq (tab1, tab2) = |
|
374 | 142 |
generic_merge (eq_pair eq) dest make tab1 tab2; |
234 | 143 |
|
144 |
||
145 |
(* tables with multiple entries per key *) |
|
146 |
(*order of entries with same key is preserved*) |
|
147 |
||
148 |
fun lookup_multi (tab, key) = |
|
149 |
(case lookup (tab, key) of |
|
150 |
Some entries => entries |
|
151 |
| None => []); |
|
152 |
||
153 |
fun cons_entry ((key, entry), tab) = |
|
154 |
update ((key, entry :: lookup_multi (tab, key)), tab); |
|
155 |
||
156 |
fun make_multi alst = |
|
157 |
balance (foldr cons_entry (alst, Tip)); |
|
158 |
||
159 |
fun dest_multi tab = |
|
2672
85d7e800d754
Replaced "flat" by the Basis Library function List.concat
paulson
parents:
2228
diff
changeset
|
160 |
List.concat (map (fn (key, entries) => map (pair key) entries) (dest tab)); |
234 | 161 |
|
0 | 162 |
|
563 | 163 |
(* map tables *) |
164 |
||
165 |
fun map _ Tip = Tip |
|
166 |
| map f (Branch (key, entry, left, right)) = |
|
167 |
Branch (key, f entry, map f left, map f right); |
|
168 |
||
0 | 169 |
end; |
170 |