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