source: vendor/FreeBSD-yacc/current/lalr.c@ 3365

Last change on this file since 3365 was 2464, checked in by bird, 20 years ago

FreeBSD CVS 2005-07-07

File size: 12.9 KB
Line 
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Robert Paul Corbett.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if 0
38#ifndef lint
39static char sccsid[] = "@(#)lalr.c 5.3 (Berkeley) 6/1/90";
40#endif
41#endif
42
43#include <sys/cdefs.h>
44__FBSDID("$FreeBSD: src/usr.bin/yacc/lalr.c,v 1.15 2002/06/11 11:27:20 robert Exp $");
45
46#include <limits.h>
47#include <stdlib.h>
48#include "defs.h"
49
50typedef
51 struct shorts
52 {
53 struct shorts *next;
54 short value;
55 }
56 shorts;
57
58int tokensetsize;
59short *lookaheads;
60short *LAruleno;
61unsigned *LA;
62short *accessing_symbol;
63core **state_table;
64shifts **shift_table;
65reductions **reduction_table;
66short *goto_map;
67short *from_state;
68short *to_state;
69
70static void add_lookback_edge(int, int, int);
71static void build_relations(void);
72static void compute_FOLLOWS(void);
73static void compute_lookaheads(void);
74static void digraph(short **);
75static void initialize_F(void);
76static void initialize_LA(void);
77static int map_goto(int, int);
78static void set_accessing_symbol(void);
79static void set_goto_map(void);
80static void set_maxrhs(void);
81static void set_reduction_table(void);
82static void set_shift_table(void);
83static void set_state_table(void);
84static short **transpose(short **, int);
85static void traverse(int, short **);
86
87static int infinity;
88static int maxrhs;
89static int ngotos;
90static unsigned *F;
91static short **includes;
92static shorts **lookback;
93static short *INDEX;
94static short *VERTICES;
95static int top;
96
97
98void
99lalr()
100{
101 tokensetsize = WORDSIZE(ntokens);
102
103 set_state_table();
104 set_accessing_symbol();
105 set_shift_table();
106 set_reduction_table();
107 set_maxrhs();
108 initialize_LA();
109 set_goto_map();
110 initialize_F();
111 build_relations();
112 compute_FOLLOWS();
113 compute_lookaheads();
114}
115
116
117
118static void
119set_state_table()
120{
121 core *sp;
122
123 state_table = NEW2(nstates, core *);
124 for (sp = first_state; sp; sp = sp->next)
125 state_table[sp->number] = sp;
126}
127
128
129
130static void
131set_accessing_symbol()
132{
133 core *sp;
134
135 accessing_symbol = NEW2(nstates, short);
136 for (sp = first_state; sp; sp = sp->next)
137 accessing_symbol[sp->number] = sp->accessing_symbol;
138}
139
140
141
142static void
143set_shift_table()
144{
145 shifts *sp;
146
147 shift_table = NEW2(nstates, shifts *);
148 for (sp = first_shift; sp; sp = sp->next)
149 shift_table[sp->number] = sp;
150}
151
152
153
154static void
155set_reduction_table()
156{
157 reductions *rp;
158
159 reduction_table = NEW2(nstates, reductions *);
160 for (rp = first_reduction; rp; rp = rp->next)
161 reduction_table[rp->number] = rp;
162}
163
164
165
166static void
167set_maxrhs()
168{
169 short *itemp;
170 short *item_end;
171 int length;
172 int max;
173
174 length = 0;
175 max = 0;
176 item_end = ritem + nitems;
177 for (itemp = ritem; itemp < item_end; itemp++)
178 {
179 if (*itemp >= 0)
180 {
181 length++;
182 }
183 else
184 {
185 if (length > max) max = length;
186 length = 0;
187 }
188 }
189
190 maxrhs = max;
191}
192
193
194
195static void
196initialize_LA()
197{
198 int i, j, k;
199 reductions *rp;
200
201 lookaheads = NEW2(nstates + 1, short);
202
203 k = 0;
204 for (i = 0; i < nstates; i++)
205 {
206 lookaheads[i] = k;
207 rp = reduction_table[i];
208 if (rp)
209 k += rp->nreds;
210 }
211 lookaheads[nstates] = k;
212
213 LA = NEW2(k * tokensetsize, unsigned);
214 LAruleno = NEW2(k, short);
215 lookback = NEW2(k, shorts *);
216
217 k = 0;
218 for (i = 0; i < nstates; i++)
219 {
220 rp = reduction_table[i];
221 if (rp)
222 {
223 for (j = 0; j < rp->nreds; j++)
224 {
225 LAruleno[k] = rp->rules[j];
226 k++;
227 }
228 }
229 }
230}
231
232
233static void
234set_goto_map()
235{
236 shifts *sp;
237 int i;
238 int symbol;
239 int k;
240 short *temp_map;
241 int state2;
242 int state1;
243
244 goto_map = NEW2(nvars + 1, short) - ntokens;
245 temp_map = NEW2(nvars + 1, short) - ntokens;
246
247 ngotos = 0;
248 for (sp = first_shift; sp; sp = sp->next)
249 {
250 for (i = sp->nshifts - 1; i >= 0; i--)
251 {
252 symbol = accessing_symbol[sp->shift[i]];
253
254 if (ISTOKEN(symbol)) break;
255
256 if (ngotos == SHRT_MAX)
257 fatal("too many gotos");
258
259 ngotos++;
260 goto_map[symbol]++;
261 }
262 }
263
264 k = 0;
265 for (i = ntokens; i < nsyms; i++)
266 {
267 temp_map[i] = k;
268 k += goto_map[i];
269 }
270
271 for (i = ntokens; i < nsyms; i++)
272 goto_map[i] = temp_map[i];
273
274 goto_map[nsyms] = ngotos;
275 temp_map[nsyms] = ngotos;
276
277 from_state = NEW2(ngotos, short);
278 to_state = NEW2(ngotos, short);
279
280 for (sp = first_shift; sp; sp = sp->next)
281 {
282 state1 = sp->number;
283 for (i = sp->nshifts - 1; i >= 0; i--)
284 {
285 state2 = sp->shift[i];
286 symbol = accessing_symbol[state2];
287
288 if (ISTOKEN(symbol)) break;
289
290 k = temp_map[symbol]++;
291 from_state[k] = state1;
292 to_state[k] = state2;
293 }
294 }
295
296 FREE(temp_map + ntokens);
297}
298
299
300
301/* Map_goto maps a state/symbol pair into its numeric representation. */
302
303static int
304map_goto(state, symbol)
305int state;
306int symbol;
307{
308 int high;
309 int low;
310 int middle;
311 int s;
312
313 low = goto_map[symbol];
314 high = goto_map[symbol + 1];
315
316 for (;;)
317 {
318 assert(low <= high);
319 middle = (low + high) >> 1;
320 s = from_state[middle];
321 if (s == state)
322 return (middle);
323 else if (s < state)
324 low = middle + 1;
325 else
326 high = middle - 1;
327 }
328}
329
330
331
332static void
333initialize_F()
334{
335 int i;
336 int j;
337 int k;
338 shifts *sp;
339 short *edge;
340 unsigned *rowp;
341 short *rp;
342 short **reads;
343 int nedges;
344 int stateno;
345 int symbol;
346 int nwords;
347
348 nwords = ngotos * tokensetsize;
349 F = NEW2(nwords, unsigned);
350
351 reads = NEW2(ngotos, short *);
352 edge = NEW2(ngotos + 1, short);
353 nedges = 0;
354
355 rowp = F;
356 for (i = 0; i < ngotos; i++)
357 {
358 stateno = to_state[i];
359 sp = shift_table[stateno];
360
361 if (sp)
362 {
363 k = sp->nshifts;
364
365 for (j = 0; j < k; j++)
366 {
367 symbol = accessing_symbol[sp->shift[j]];
368 if (ISVAR(symbol))
369 break;
370 SETBIT(rowp, symbol);
371 }
372
373 for (; j < k; j++)
374 {
375 symbol = accessing_symbol[sp->shift[j]];
376 if (nullable[symbol])
377 edge[nedges++] = map_goto(stateno, symbol);
378 }
379
380 if (nedges)
381 {
382 reads[i] = rp = NEW2(nedges + 1, short);
383
384 for (j = 0; j < nedges; j++)
385 rp[j] = edge[j];
386
387 rp[nedges] = -1;
388 nedges = 0;
389 }
390 }
391
392 rowp += tokensetsize;
393 }
394
395 SETBIT(F, 0);
396 digraph(reads);
397
398 for (i = 0; i < ngotos; i++)
399 {
400 if (reads[i])
401 FREE(reads[i]);
402 }
403
404 FREE(reads);
405 FREE(edge);
406}
407
408
409
410static void
411build_relations()
412{
413 int i;
414 int j;
415 int k;
416 short *rulep;
417 short *rp;
418 shifts *sp;
419 int length;
420 int nedges;
421 int done1;
422 int state1;
423 int stateno;
424 int symbol1;
425 int symbol2;
426 short *shortp;
427 short *edge;
428 short *states;
429 short **new_includes;
430
431 includes = NEW2(ngotos, short *);
432 edge = NEW2(ngotos + 1, short);
433 states = NEW2(maxrhs + 1, short);
434
435 for (i = 0; i < ngotos; i++)
436 {
437 nedges = 0;
438 state1 = from_state[i];
439 symbol1 = accessing_symbol[to_state[i]];
440
441 for (rulep = derives[symbol1]; *rulep >= 0; rulep++)
442 {
443 length = 1;
444 states[0] = state1;
445 stateno = state1;
446
447 for (rp = ritem + rrhs[*rulep]; *rp >= 0; rp++)
448 {
449 symbol2 = *rp;
450 sp = shift_table[stateno];
451 k = sp->nshifts;
452
453 for (j = 0; j < k; j++)
454 {
455 stateno = sp->shift[j];
456 if (accessing_symbol[stateno] == symbol2) break;
457 }
458
459 states[length++] = stateno;
460 }
461
462 add_lookback_edge(stateno, *rulep, i);
463
464 length--;
465 done1 = 0;
466 while (!done1)
467 {
468 done1 = 1;
469 rp--;
470 if (ISVAR(*rp))
471 {
472 stateno = states[--length];
473 edge[nedges++] = map_goto(stateno, *rp);
474 if (nullable[*rp] && length > 0) done1 = 0;
475 }
476 }
477 }
478
479 if (nedges)
480 {
481 includes[i] = shortp = NEW2(nedges + 1, short);
482 for (j = 0; j < nedges; j++)
483 shortp[j] = edge[j];
484 shortp[nedges] = -1;
485 }
486 }
487
488 new_includes = transpose(includes, ngotos);
489
490 for (i = 0; i < ngotos; i++)
491 if (includes[i])
492 FREE(includes[i]);
493
494 FREE(includes);
495
496 includes = new_includes;
497
498 FREE(edge);
499 FREE(states);
500}
501
502
503static void
504add_lookback_edge(stateno, ruleno, gotono)
505int stateno, ruleno, gotono;
506{
507 int i, k;
508 int found;
509 shorts *sp;
510
511 i = lookaheads[stateno];
512 k = lookaheads[stateno + 1];
513 found = 0;
514 while (!found && i < k)
515 {
516 if (LAruleno[i] == ruleno)
517 found = 1;
518 else
519 ++i;
520 }
521 assert(found);
522
523 sp = NEW(shorts);
524 sp->next = lookback[i];
525 sp->value = gotono;
526 lookback[i] = sp;
527}
528
529
530
531static short **
532transpose(R, n)
533short **R;
534int n;
535{
536 short **new_R;
537 short **temp_R;
538 short *nedges;
539 short *sp;
540 int i;
541 int k;
542
543 nedges = NEW2(n, short);
544
545 for (i = 0; i < n; i++)
546 {
547 sp = R[i];
548 if (sp)
549 {
550 while (*sp >= 0)
551 nedges[*sp++]++;
552 }
553 }
554
555 new_R = NEW2(n, short *);
556 temp_R = NEW2(n, short *);
557
558 for (i = 0; i < n; i++)
559 {
560 k = nedges[i];
561 if (k > 0)
562 {
563 sp = NEW2(k + 1, short);
564 new_R[i] = sp;
565 temp_R[i] = sp;
566 sp[k] = -1;
567 }
568 }
569
570 FREE(nedges);
571
572 for (i = 0; i < n; i++)
573 {
574 sp = R[i];
575 if (sp)
576 {
577 while (*sp >= 0)
578 *temp_R[*sp++]++ = i;
579 }
580 }
581
582 FREE(temp_R);
583
584 return (new_R);
585}
586
587
588
589static void
590compute_FOLLOWS()
591{
592 digraph(includes);
593}
594
595
596static void
597compute_lookaheads()
598{
599 int i, n;
600 unsigned *fp1, *fp2, *fp3;
601 shorts *sp, *next;
602 unsigned *rowp;
603
604 rowp = LA;
605 n = lookaheads[nstates];
606 for (i = 0; i < n; i++)
607 {
608 fp3 = rowp + tokensetsize;
609 for (sp = lookback[i]; sp; sp = sp->next)
610 {
611 fp1 = rowp;
612 fp2 = F + tokensetsize * sp->value;
613 while (fp1 < fp3)
614 *fp1++ |= *fp2++;
615 }
616 rowp = fp3;
617 }
618
619 for (i = 0; i < n; i++)
620 for (sp = lookback[i]; sp; sp = next)
621 {
622 next = sp->next;
623 FREE(sp);
624 }
625
626 FREE(lookback);
627 FREE(F);
628}
629
630
631static void
632digraph(relation)
633short **relation;
634{
635 int i;
636
637 infinity = ngotos + 2;
638 INDEX = NEW2(ngotos + 1, short);
639 VERTICES = NEW2(ngotos + 1, short);
640 top = 0;
641
642 for (i = 0; i < ngotos; i++)
643 INDEX[i] = 0;
644
645 for (i = 0; i < ngotos; i++)
646 {
647 if (INDEX[i] == 0 && relation[i])
648 traverse(i, relation);
649 }
650
651 FREE(INDEX);
652 FREE(VERTICES);
653}
654
655
656
657static void
658traverse(i, R)
659int i;
660short **R;
661{
662 unsigned *fp1;
663 unsigned *fp2;
664 unsigned *fp3;
665 int j;
666 short *rp;
667
668 int height;
669 unsigned *base;
670
671 VERTICES[++top] = i;
672 INDEX[i] = height = top;
673
674 base = F + i * tokensetsize;
675 fp3 = base + tokensetsize;
676
677 rp = R[i];
678 if (rp)
679 {
680 while ((j = *rp++) >= 0)
681 {
682 if (INDEX[j] == 0)
683 traverse(j, R);
684
685 if (INDEX[i] > INDEX[j])
686 INDEX[i] = INDEX[j];
687
688 fp1 = base;
689 fp2 = F + j * tokensetsize;
690
691 while (fp1 < fp3)
692 *fp1++ |= *fp2++;
693 }
694 }
695
696 if (INDEX[i] == height)
697 {
698 for (;;)
699 {
700 j = VERTICES[top--];
701 INDEX[j] = infinity;
702
703 if (i == j)
704 break;
705
706 fp1 = base;
707 fp2 = F + j * tokensetsize;
708
709 while (fp1 < fp3)
710 *fp2++ = *fp1++;
711 }
712 }
713}
Note: See TracBrowser for help on using the repository browser.