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