]> git.saurik.com Git - bison.git/blob - src/LR0.c
15b29f3010d851ddf2228de254c23bccbefd621e
[bison.git] / src / LR0.c
1 /* Generate the nondeterministic finite state machine for bison,
2 Copyright 1984, 1986, 1989, 2000, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of Bison, the GNU Compiler Compiler.
5
6 Bison is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 Bison is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Bison; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 /* See comments in state.h for the data structures that represent it.
23 The entry point is generate_states. */
24
25 #include "system.h"
26 #include "bitset.h"
27 #include "symtab.h"
28 #include "getargs.h"
29 #include "reader.h"
30 #include "gram.h"
31 #include "state.h"
32 #include "complain.h"
33 #include "closure.h"
34 #include "LR0.h"
35 #include "lalr.h"
36 #include "reduce.h"
37
38 unsigned int nstates;
39 /* Initialize the final state to -1, otherwise, it might be set to 0
40 by default, and since we don't compute the reductions of the final
41 state, we end up not computing the reductions of the initial state,
42 which is of course needed.
43
44 FINAL_STATE is properly set by new_state when it recognizes the
45 accessing symbol: EOF. */
46 int final_state = -1;
47 static state_t *first_state = NULL;
48
49 static state_t *this_state = NULL;
50 static state_t *last_state = NULL;
51
52 static int nshifts;
53 static short *shift_symbol = NULL;
54
55 static short *redset = NULL;
56 static short *shiftset = NULL;
57
58 static short **kernel_base = NULL;
59 static int *kernel_size = NULL;
60 static short *kernel_items = NULL;
61
62 /* hash table for states, to recognize equivalent ones. */
63
64 #define STATE_HASH_SIZE 1009
65 static state_t **state_hash = NULL;
66
67 \f
68 static void
69 allocate_itemsets (void)
70 {
71 int i, r;
72 short *rhsp;
73
74 /* Count the number of occurrences of all the symbols in RITEMS.
75 Note that useless productions (hence useless nonterminals) are
76 browsed too, hence we need to allocate room for _all_ the
77 symbols. */
78 int count = 0;
79 short *symbol_count = XCALLOC (short, nsyms + nuseless_nonterminals);
80
81 for (r = 1; r < nrules + 1; ++r)
82 for (rhsp = rules[r].rhs; *rhsp >= 0; ++rhsp)
83 {
84 count++;
85 symbol_count[*rhsp]++;
86 }
87
88 /* See comments before new_itemsets. All the vectors of items
89 live inside KERNEL_ITEMS. The number of active items after
90 some symbol cannot be more than the number of times that symbol
91 appears as an item, which is symbol_count[symbol].
92 We allocate that much space for each symbol. */
93
94 kernel_base = XCALLOC (short *, nsyms);
95 if (count)
96 kernel_items = XCALLOC (short, count);
97
98 count = 0;
99 for (i = 0; i < nsyms; i++)
100 {
101 kernel_base[i] = kernel_items + count;
102 count += symbol_count[i];
103 }
104
105 free (symbol_count);
106 kernel_size = XCALLOC (int, nsyms);
107 }
108
109
110 static void
111 allocate_storage (void)
112 {
113 allocate_itemsets ();
114
115 shiftset = XCALLOC (short, nsyms);
116 redset = XCALLOC (short, nrules + 1);
117 state_hash = XCALLOC (state_t *, STATE_HASH_SIZE);
118 shift_symbol = XCALLOC (short, nsyms);
119 }
120
121
122 static void
123 free_storage (void)
124 {
125 free (shift_symbol);
126 free (redset);
127 free (shiftset);
128 free (kernel_base);
129 free (kernel_size);
130 XFREE (kernel_items);
131 free (state_hash);
132 }
133
134
135
136
137 /*----------------------------------------------------------------.
138 | Find which symbols can be shifted in the current state, and for |
139 | each one record which items would be active after that shift. |
140 | Uses the contents of itemset. |
141 | |
142 | shift_symbol is set to a vector of the symbols that can be |
143 | shifted. For each symbol in the grammar, kernel_base[symbol] |
144 | points to a vector of item numbers activated if that symbol is |
145 | shifted, and kernel_size[symbol] is their numbers. |
146 `----------------------------------------------------------------*/
147
148 static void
149 new_itemsets (void)
150 {
151 int i;
152
153 if (trace_flag)
154 fprintf (stderr, "Entering new_itemsets, state = %d\n",
155 this_state->number);
156
157 for (i = 0; i < nsyms; i++)
158 kernel_size[i] = 0;
159
160 nshifts = 0;
161
162 for (i = 0; i < nitemset; ++i)
163 {
164 int symbol = ritem[itemset[i]];
165 if (symbol >= 0)
166 {
167 if (!kernel_size[symbol])
168 {
169 shift_symbol[nshifts] = symbol;
170 nshifts++;
171 }
172
173 kernel_base[symbol][kernel_size[symbol]] = itemset[i] + 1;
174 kernel_size[symbol]++;
175 }
176 }
177 }
178
179
180
181 /*-----------------------------------------------------------------.
182 | Subroutine of get_state. Create a new state for those items, if |
183 | necessary. |
184 `-----------------------------------------------------------------*/
185
186 static state_t *
187 new_state (int symbol)
188 {
189 state_t *p;
190
191 if (trace_flag)
192 fprintf (stderr, "Entering new_state, state = %d, symbol = %d (%s)\n",
193 this_state->number, symbol, symbols[symbol]->tag);
194
195 if (nstates >= MAXSHORT)
196 fatal (_("too many states (max %d)"), MAXSHORT);
197
198 p = STATE_ALLOC (kernel_size[symbol]);
199 p->accessing_symbol = symbol;
200 p->number = nstates;
201 p->nitems = kernel_size[symbol];
202
203 shortcpy (p->items, kernel_base[symbol], kernel_size[symbol]);
204
205 last_state->next = p;
206 last_state = p;
207 nstates++;
208
209 /* If this is the eoftoken, then this is the final state. */
210 if (symbol == 0)
211 final_state = p->number;
212
213 return p;
214 }
215
216
217 /*--------------------------------------------------------------.
218 | Find the state number for the state we would get to (from the |
219 | current state) by shifting symbol. Create a new state if no |
220 | equivalent one exists already. Used by append_states. |
221 `--------------------------------------------------------------*/
222
223 static int
224 get_state (int symbol)
225 {
226 int key;
227 int i;
228 state_t *sp;
229
230 if (trace_flag)
231 fprintf (stderr, "Entering get_state, state = %d, symbol = %d (%s)\n",
232 this_state->number, symbol, symbols[symbol]->tag);
233
234 /* Add up the target state's active item numbers to get a hash key.
235 */
236 key = 0;
237 for (i = 0; i < kernel_size[symbol]; ++i)
238 key += kernel_base[symbol][i];
239 key = key % STATE_HASH_SIZE;
240 sp = state_hash[key];
241
242 if (sp)
243 {
244 int found = 0;
245 while (!found)
246 {
247 if (sp->nitems == kernel_size[symbol])
248 {
249 found = 1;
250 for (i = 0; i < kernel_size[symbol]; ++i)
251 if (kernel_base[symbol][i] != sp->items[i])
252 found = 0;
253 }
254
255 if (!found)
256 {
257 if (sp->link)
258 {
259 sp = sp->link;
260 }
261 else /* bucket exhausted and no match */
262 {
263 sp = sp->link = new_state (symbol);
264 found = 1;
265 }
266 }
267 }
268 }
269 else /* bucket is empty */
270 {
271 state_hash[key] = sp = new_state (symbol);
272 }
273
274 if (trace_flag)
275 fprintf (stderr, "Exiting get_state => %d\n", sp->number);
276
277 return sp->number;
278 }
279
280 /*------------------------------------------------------------------.
281 | Use the information computed by new_itemsets to find the state |
282 | numbers reached by each shift transition from the current state. |
283 | |
284 | shiftset is set up as a vector of state numbers of those states. |
285 `------------------------------------------------------------------*/
286
287 static void
288 append_states (void)
289 {
290 int i;
291 int j;
292 int symbol;
293
294 if (trace_flag)
295 fprintf (stderr, "Entering append_states, state = %d\n",
296 this_state->number);
297
298 /* first sort shift_symbol into increasing order */
299
300 for (i = 1; i < nshifts; i++)
301 {
302 symbol = shift_symbol[i];
303 j = i;
304 while (j > 0 && shift_symbol[j - 1] > symbol)
305 {
306 shift_symbol[j] = shift_symbol[j - 1];
307 j--;
308 }
309 shift_symbol[j] = symbol;
310 }
311
312 for (i = 0; i < nshifts; i++)
313 shiftset[i] = get_state (shift_symbol[i]);
314 }
315
316
317 static void
318 new_states (void)
319 {
320 first_state = last_state = this_state = STATE_ALLOC (0);
321 nstates = 1;
322 }
323
324
325 /*------------------------------------------------------------.
326 | Save the NSHIFTS of SHIFTSET into the current linked list. |
327 `------------------------------------------------------------*/
328
329 static void
330 save_shifts (void)
331 {
332 shifts *p = shifts_new (nshifts);
333 shortcpy (p->shifts, shiftset, nshifts);
334 this_state->shifts = p;
335 }
336
337
338 /*----------------------------------------------------------------.
339 | Find which rules can be used for reduction transitions from the |
340 | current state and make a reductions structure for the state to |
341 | record their rule numbers. |
342 `----------------------------------------------------------------*/
343
344 static void
345 save_reductions (void)
346 {
347 int count = 0;
348 int i;
349
350 /* If this is the final state, we want it to have no reductions at
351 all, although it has one for `START_SYMBOL EOF .'. */
352 if (this_state->number == final_state)
353 return;
354
355 /* Find and count the active items that represent ends of rules. */
356 for (i = 0; i < nitemset; ++i)
357 {
358 int item = ritem[itemset[i]];
359 if (item < 0)
360 redset[count++] = -item;
361 }
362
363 /* Make a reductions structure and copy the data into it. */
364 this_state->reductions = reductions_new (count);
365 shortcpy (this_state->reductions->rules, redset, count);
366 }
367
368 \f
369 /*---------------.
370 | Build STATES. |
371 `---------------*/
372
373 static void
374 set_states (void)
375 {
376 state_t *sp;
377 states = XCALLOC (state_t *, nstates);
378
379 for (sp = first_state; sp; sp = sp->next)
380 {
381 /* Pessimization, but simplification of the code: make sure all
382 the states have a shifts, errs, and reductions, even if
383 reduced to 0. */
384 if (!sp->shifts)
385 sp->shifts = shifts_new (0);
386 if (!sp->errs)
387 sp->errs = errs_new (0);
388 if (!sp->reductions)
389 sp->reductions = reductions_new (0);
390
391 states[sp->number] = sp;
392 }
393 }
394
395 /*-------------------------------------------------------------------.
396 | Compute the nondeterministic finite state machine (see state.h for |
397 | details) from the grammar. |
398 `-------------------------------------------------------------------*/
399
400 void
401 generate_states (void)
402 {
403 allocate_storage ();
404 new_closure (nritems);
405 new_states ();
406
407 while (this_state)
408 {
409 if (trace_flag)
410 fprintf (stderr, "Processing state %d (reached by %s)\n",
411 this_state->number,
412 symbols[this_state->accessing_symbol]->tag);
413 /* Set up ruleset and itemset for the transitions out of this
414 state. ruleset gets a 1 bit for each rule that could reduce
415 now. itemset gets a vector of all the items that could be
416 accepted next. */
417 closure (this_state->items, this_state->nitems);
418 /* record the reductions allowed out of this state */
419 save_reductions ();
420 /* find the itemsets of the states that shifts can reach */
421 new_itemsets ();
422 /* find or create the core structures for those states */
423 append_states ();
424
425 /* create the shifts structures for the shifts to those states,
426 now that the state numbers transitioning to are known */
427 save_shifts ();
428
429 /* states are queued when they are created; process them all */
430 this_state = this_state->next;
431 }
432
433 /* discard various storage */
434 free_closure ();
435 free_storage ();
436
437 /* Set up STATES. */
438 set_states ();
439 }