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