source: trunk/yacc/lr0.c@ 2466

Last change on this file since 2466 was 2464, checked in by bird, 20 years ago

FreeBSD CVS 2005-07-07

File size: 12.3 KB
Line 
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Robert Paul Corbett.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if 0
38#ifndef lint
39static char sccsid[] = "@(#)lr0.c 5.3 (Berkeley) 1/20/91";
40#endif
41#endif
42
43#include <sys/cdefs.h>
44__FBSDID("$FreeBSD: src/usr.bin/yacc/lr0.c,v 1.13 2002/06/11 11:27:20 robert Exp $");
45
46#include <limits.h>
47#include <stdlib.h>
48#include "defs.h"
49
50extern short *itemset;
51extern short *itemsetend;
52extern unsigned *ruleset;
53
54int nstates;
55core *first_state;
56shifts *first_shift;
57reductions *first_reduction;
58
59static void allocate_itemsets(void);
60static void allocate_storage(void);
61static void append_states(void);
62static void free_storage(void);
63static void generate_states(void);
64static int get_state(int);
65static void initialize_states(void);
66static void new_itemsets(void);
67static core *new_state(int);
68#ifdef DEBUG
69static void print_derives(void);
70#endif
71static void save_reductions(void);
72static void save_shifts(void);
73static void set_derives(void);
74static void set_nullable(void);
75
76static core **state_set;
77static core *this_state;
78static core *last_state;
79static shifts *last_shift;
80static reductions *last_reduction;
81
82static int nshifts;
83static short *shift_symbol;
84
85static short *redset;
86static short *shiftset;
87
88static short **kernel_base;
89static short **kernel_end;
90static short *kernel_items;
91
92
93static void
94allocate_itemsets()
95{
96 short *itemp;
97 short *item_end;
98 int symbol;
99 int i;
100 int count;
101 int max;
102 short *symbol_count;
103
104 count = 0;
105 symbol_count = NEW2(nsyms, short);
106
107 item_end = ritem + nitems;
108 for (itemp = ritem; itemp < item_end; itemp++)
109 {
110 symbol = *itemp;
111 if (symbol >= 0)
112 {
113 count++;
114 symbol_count[symbol]++;
115 }
116 }
117
118 kernel_base = NEW2(nsyms, short *);
119 kernel_items = NEW2(count, short);
120
121 count = 0;
122 max = 0;
123 for (i = 0; i < nsyms; i++)
124 {
125 kernel_base[i] = kernel_items + count;
126 count += symbol_count[i];
127 if (max < symbol_count[i])
128 max = symbol_count[i];
129 }
130
131 shift_symbol = symbol_count;
132 kernel_end = NEW2(nsyms, short *);
133}
134
135
136static void
137allocate_storage()
138{
139 allocate_itemsets();
140 shiftset = NEW2(nsyms, short);
141 redset = NEW2(nrules + 1, short);
142 state_set = NEW2(nitems, core *);
143}
144
145
146static void
147append_states()
148{
149 int i;
150 int j;
151 int symbol;
152
153#ifdef TRACE
154 fprintf(stderr, "Entering append_states()\n");
155#endif
156 for (i = 1; i < nshifts; i++)
157 {
158 symbol = shift_symbol[i];
159 j = i;
160 while (j > 0 && shift_symbol[j - 1] > symbol)
161 {
162 shift_symbol[j] = shift_symbol[j - 1];
163 j--;
164 }
165 shift_symbol[j] = symbol;
166 }
167
168 for (i = 0; i < nshifts; i++)
169 {
170 symbol = shift_symbol[i];
171 shiftset[i] = get_state(symbol);
172 }
173}
174
175
176static void
177free_storage()
178{
179 FREE(shift_symbol);
180 FREE(redset);
181 FREE(shiftset);
182 FREE(kernel_base);
183 FREE(kernel_end);
184 FREE(kernel_items);
185 FREE(state_set);
186}
187
188
189
190static void
191generate_states()
192{
193 allocate_storage();
194 itemset = NEW2(nitems, short);
195 ruleset = NEW2(WORDSIZE(nrules), unsigned);
196 set_first_derives();
197 initialize_states();
198
199 while (this_state)
200 {
201 closure(this_state->items, this_state->nitems);
202 save_reductions();
203 new_itemsets();
204 append_states();
205
206 if (nshifts > 0)
207 save_shifts();
208
209 this_state = this_state->next;
210 }
211
212 finalize_closure();
213 free_storage();
214}
215
216
217
218static int
219get_state(symbol)
220int symbol;
221{
222 int key;
223 short *isp1;
224 short *isp2;
225 short *iend;
226 core *sp;
227 int found;
228 int n;
229
230#ifdef TRACE
231 fprintf(stderr, "Entering get_state(%d)\n", symbol);
232#endif
233
234 isp1 = kernel_base[symbol];
235 iend = kernel_end[symbol];
236 n = iend - isp1;
237
238 key = *isp1;
239 assert(0 <= key && key < nitems);
240 sp = state_set[key];
241 if (sp)
242 {
243 found = 0;
244 while (!found)
245 {
246 if (sp->nitems == n)
247 {
248 found = 1;
249 isp1 = kernel_base[symbol];
250 isp2 = sp->items;
251
252 while (found && isp1 < iend)
253 {
254 if (*isp1++ != *isp2++)
255 found = 0;
256 }
257 }
258
259 if (!found)
260 {
261 if (sp->link)
262 {
263 sp = sp->link;
264 }
265 else
266 {
267 sp = sp->link = new_state(symbol);
268 found = 1;
269 }
270 }
271 }
272 }
273 else
274 {
275 state_set[key] = sp = new_state(symbol);
276 }
277
278 return (sp->number);
279}
280
281
282
283static void
284initialize_states()
285{
286 int i;
287 short *start_derives;
288 core *p;
289
290 start_derives = derives[start_symbol];
291 for (i = 0; start_derives[i] >= 0; ++i)
292 continue;
293
294 p = (core *) MALLOC(sizeof(core) + i*sizeof(short));
295 if (p == 0) no_space();
296
297 p->next = 0;
298 p->link = 0;
299 p->number = 0;
300 p->accessing_symbol = 0;
301 p->nitems = i;
302
303 for (i = 0; start_derives[i] >= 0; ++i)
304 p->items[i] = rrhs[start_derives[i]];
305
306 first_state = last_state = this_state = p;
307 nstates = 1;
308}
309
310
311static void
312new_itemsets()
313{
314 int i;
315 int shiftcount;
316 short *isp;
317 short *ksp;
318 int symbol;
319
320 for (i = 0; i < nsyms; i++)
321 kernel_end[i] = 0;
322
323 shiftcount = 0;
324 isp = itemset;
325 while (isp < itemsetend)
326 {
327 i = *isp++;
328 symbol = ritem[i];
329 if (symbol > 0)
330 {
331 ksp = kernel_end[symbol];
332 if (!ksp)
333 {
334 shift_symbol[shiftcount++] = symbol;
335 ksp = kernel_base[symbol];