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