Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* ML-Yacc Parser Generator (c) 1991 Andrew W. Appel, David R. Tarditi *) |
2 | ||
3 | signature SORT_ARG = | |
4 | sig | |
5 | type entry | |
6 | val gt : entry * entry -> bool | |
7 | end | |
8 | signature SORT = | |
9 | sig | |
10 | type entry | |
11 | val sort : entry list -> entry list | |
12 | end | |
13 | signature EQUIV_ARG = | |
14 | sig | |
15 | type entry | |
16 | val gt : entry * entry -> bool | |
17 | val eq : entry * entry -> bool | |
18 | end | |
19 | signature EQUIV = | |
20 | sig | |
21 | type entry | |
22 | ||
23 | (* equivalences: take a list of entries and divides them into | |
24 | equivalence classes numbered 0 to n-1. | |
25 | ||
26 | It returns a triple consisting of: | |
27 | ||
28 | * the number of equivalence classes | |
29 | * a list which maps each original entry to an equivalence | |
30 | class. The nth entry in this list gives the equivalence | |
31 | class for the nth entry in the original entry list. | |
32 | * a list which maps equivalence classes to some representative | |
33 | element. The nth entry in this list is an element from the | |
34 | nth equivalence class | |
35 | *) | |
36 | ||
37 | val equivalences : entry list -> (int * int list * entry list) | |
38 | end | |
39 | ||
40 | (* An O(n lg n) merge sort routine *) | |
41 | ||
42 | functor MergeSortFun(A : SORT_ARG) : SORT = | |
43 | struct | |
44 | type entry = A.entry | |
45 | ||
46 | (* sort: an O(n lg n) merge sort routine. We create a list of lists | |
47 | and then merge these lists in passes until only one list is left.*) | |
48 | ||
49 | fun sort nil = nil | |
50 | | sort l = | |
51 | let (* merge: merge two lists *) | |
52 | ||
53 | fun merge (l as a::at,r as b::bt) = | |
54 | if A.gt(a,b) | |
55 | then b :: merge(l,bt) | |
56 | else a :: merge(at,r) | |
57 | | merge (l,nil) = l | |
58 | | merge (nil,r) = r | |
59 | ||
60 | (* scan: merge pairs of lists on a list of lists. | |
61 | Reduces the number of lists by about 1/2 *) | |
62 | ||
63 | fun scan (a :: b :: rest) = merge(a,b) :: scan rest | |
64 | | scan l = l | |
65 | ||
66 | (* loop: calls scan on a list of lists until only | |
67 | one list is left. It terminates only if the list of | |
68 | lists is nonempty. (The pattern match for sort | |
69 | ensures this.) *) | |
70 | ||
71 | fun loop (a :: nil) = a | |
72 | | loop l = loop (scan l) | |
73 | ||
74 | in loop (map (fn a => [a]) l) | |
75 | end | |
76 | end | |
77 | ||
78 | (* an O(n lg n) routine for placing items in equivalence classes *) | |
79 | ||
80 | functor EquivFun(A : EQUIV_ARG) : EQUIV = | |
81 | struct | |
82 | val sub = Array.sub | |
83 | infix 9 sub | |
84 | ||
85 | (* Our algorithm for finding equivalence class is simple. The basic | |
86 | idea is to sort the entries and place duplicates entries in the same | |
87 | equivalence class. | |
88 | ||
89 | Let the original entry list be E. We map E to a list of a pairs | |
90 | consisting of the entry and its position in E, where the positions | |
91 | are numbered 0 to n-1. Call this list of pairs EP. | |
92 | ||
93 | We then sort EP on the original entries. The second elements in the | |
94 | pairs now specify a permutation that will return us to EP. | |
95 | ||
96 | We then scan the sorted list to create a list R of representative | |
97 | entries, a list P of integers which permutes the sorted list back to | |
98 | the original list and a list SE of integers which gives the | |
99 | equivalence class for the nth entry in the sorted list . | |
100 | ||
101 | We then return the length of R, R, and the list that results from | |
102 | permuting SE by P. | |
103 | *) | |
104 | ||
105 | type entry = A.entry | |
106 | ||
107 | val gt = fn ((a,_),(b,_)) => A.gt(a,b) | |
108 | ||
109 | structure Sort = MergeSortFun(type entry = A.entry * int | |
110 | val gt = gt) | |
111 | val assignIndex = | |
112 | fn l => | |
113 | let fun loop (index,nil) = nil | |
114 | | loop (index,h :: t) = (h,index) :: loop(index+1,t) | |
115 | in loop (0,l) | |
116 | end | |
117 | ||
118 | local fun loop ((e,_) :: t, prev, class, R , SE) = | |
119 | if A.eq(e,prev) | |
120 | then loop(t,e,class,R, class :: SE) | |
121 | else loop(t,e,class+1,e :: R, (class + 1) :: SE) | |
122 | | loop (nil,_,_,R,SE) = (rev R, rev SE) | |
123 | in val createEquivalences = | |
124 | fn nil => (nil,nil) | |
125 | | (e,_) :: t => loop(t, e, 0, [e],[0]) | |
126 | end | |
127 | ||
128 | val inversePermute = fn permutation => | |
129 | fn nil => nil | |
130 | | l as h :: _ => | |
131 | let val result = Array.array(length l,h) | |
132 | fun loop (elem :: r, dest :: s) = | |
133 | (Array.update(result,dest,elem); loop(r,s)) | |
134 | | loop _ = () | |
135 | fun listofarray i = | |
136 | if i < Array.length result then | |
137 | (result sub i) :: listofarray (i+1) | |
138 | else nil | |
139 | in loop (l,permutation); listofarray 0 | |
140 | end | |
141 | ||
142 | fun makePermutation x = map (fn (_,b) => b) x | |
143 | ||
144 | val equivalences = fn l => | |
145 | let val EP = assignIndex l | |
146 | val sorted = Sort.sort EP | |
147 | val P = makePermutation sorted | |
148 | val (R, SE) = createEquivalences sorted | |
149 | in (length R, inversePermute P SE, R) | |
150 | end | |
151 | end | |
152 | ||
153 | functor ShrinkLrTableFun(structure LrTable : LR_TABLE) : SHRINK_LR_TABLE = | |
154 | struct | |
155 | structure LrTable = LrTable | |
156 | open LrTable | |
157 | val gtAction = fn (a,b) => | |
158 | case a | |
159 | of SHIFT (STATE s) => | |
160 | (case b of SHIFT (STATE s') => s>s' | _ => true) | |
161 | | REDUCE i => (case b of SHIFT _ => false | REDUCE i' => i>i' | |
162 | | _ => true) | |
163 | | ACCEPT => (case b of ERROR => true | _ => false) | |
164 | | ERROR => false | |
165 | structure ActionEntryList = | |
166 | struct | |
167 | type entry = (term, action) pairlist * action | |
168 | local | |
169 | fun eqlist (EMPTY, EMPTY) = true | |
170 | | eqlist (PAIR (T t,d,r),PAIR(T t',d',r')) = | |
171 | t=t' andalso d=d' andalso eqlist(r,r') | |
172 | | eqlist _ = false | |
173 | fun gtlist (PAIR _,EMPTY) = true | |
174 | | gtlist (PAIR(T t,d,r),PAIR(T t',d',r')) = | |
175 | t>t' orelse (t=t' andalso | |
176 | (gtAction(d,d') orelse | |
177 | (d=d' andalso gtlist(r,r')))) | |
178 | | gtlist _ = false | |
179 | in | |
180 | fun eq ((l,a): entry, (l',a'): entry) = | |
181 | a = a' andalso eqlist (l,l') | |
182 | fun gt ((l,a): entry, (l',a'): entry) = | |
183 | gtAction(a,a') orelse (a=a' andalso gtlist(l,l')) | |
184 | end | |
185 | end | |
186 | (* structure GotoEntryList = | |
187 | struct | |
188 | type entry = (nonterm,state) pairlist | |
189 | val rec eq = | |
190 | fn (EMPTY,EMPTY) => true | |
191 | | (PAIR (t,d,r),PAIR(t',d',r')) => | |
192 | t=t' andalso d=d' andalso eq(r,r') | |
193 | | _ => false | |
194 | val rec gt = | |
195 | fn (PAIR _,EMPTY) => true | |
196 | | (PAIR(NT t,STATE d,r),PAIR(NT t',STATE d',r')) => | |
197 | t>t' orelse (t=t' andalso | |
198 | (d>d' orelse (d=d' andalso gt(r,r')))) | |
199 | | _ => false | |
200 | end *) | |
201 | structure EquivActionList = EquivFun(ActionEntryList) | |
202 | val states = fn max => | |
203 | let fun f i=if i<max then STATE i :: f(i+1) else nil | |
204 | in f 0 | |
205 | end | |
206 | val length : ('a,'b) pairlist -> int = | |
207 | fn l => | |
208 | let fun g(EMPTY,len) = len | |
209 | | g(PAIR(_,_,r),len) = g(r,len+1) | |
210 | in g(l,0) | |
211 | end | |
212 | val size : (('a,'b) pairlist * 'c) list -> int = | |
213 | fn l => | |
214 | let val c = ref 0 | |
215 | in (app (fn (row,_) => c := !c + length row) l; !c) | |
216 | end | |
217 | val shrinkActionList = | |
218 | fn (table,verbose) => | |
219 | case EquivActionList.equivalences | |
220 | (map (describeActions table) (states (numStates table))) | |
221 | of result as (_,_,l) => (result,if verbose then size l else 0) | |
222 | end; |