]> git.saurik.com Git - bison.git/blob - src/conflicts.c
Initial revision
[bison.git] / src / conflicts.c
1 /* Find and resolve or report look-ahead conflicts for bison,
2 Copyright (C) 1984, 1989 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #ifdef _AIX
21 #pragma alloca
22 #endif
23 #include <stdio.h>
24 #include "system.h"
25 #include "machine.h"
26 #include "new.h"
27 #include "files.h"
28 #include "gram.h"
29 #include "state.h"
30
31
32 #ifdef __GNUC__
33 #define alloca __builtin_alloca
34 #else
35 #ifdef HAVE_ALLOCA_H
36 #include <alloca.h>
37 #else
38 #ifndef _AIX
39 extern char *alloca ();
40 #endif
41 #endif
42 #endif
43
44 extern char **tags;
45 extern int tokensetsize;
46 extern char *consistent;
47 extern short *accessing_symbol;
48 extern shifts **shift_table;
49 extern unsigned *LA;
50 extern short *LAruleno;
51 extern short *lookaheads;
52 extern int verboseflag;
53
54 void set_conflicts();
55 void resolve_sr_conflict();
56 void flush_shift();
57 void log_resolution();
58 void total_conflicts();
59 void count_sr_conflicts();
60 void count_rr_conflicts();
61
62 char any_conflicts;
63 char *conflicts;
64 errs **err_table;
65 int expected_conflicts;
66
67
68 static unsigned *shiftset;
69 static unsigned *lookaheadset;
70 static int src_total;
71 static int rrc_total;
72 static int src_count;
73 static int rrc_count;
74
75
76 void
77 initialize_conflicts()
78 {
79 register int i;
80 /* register errs *sp; JF unused */
81
82 conflicts = NEW2(nstates, char);
83 shiftset = NEW2(tokensetsize, unsigned);
84 lookaheadset = NEW2(tokensetsize, unsigned);
85
86 err_table = NEW2(nstates, errs *);
87
88 any_conflicts = 0;
89
90 for (i = 0; i < nstates; i++)
91 set_conflicts(i);
92 }
93
94
95 void
96 set_conflicts(state)
97 int state;
98 {
99 register int i;
100 register int k;
101 register shifts *shiftp;
102 register unsigned *fp2;
103 register unsigned *fp3;
104 register unsigned *fp4;
105 register unsigned *fp1;
106 register int symbol;
107
108 if (consistent[state]) return;
109
110 for (i = 0; i < tokensetsize; i++)
111 lookaheadset[i] = 0;
112
113 shiftp = shift_table[state];
114 if (shiftp)
115 {
116 k = shiftp->nshifts;
117 for (i = 0; i < k; i++)
118 {
119 symbol = accessing_symbol[shiftp->shifts[i]];
120 if (ISVAR(symbol)) break;
121 SETBIT(lookaheadset, symbol);
122 }
123 }
124
125 k = lookaheads[state + 1];
126 fp4 = lookaheadset + tokensetsize;
127
128 /* loop over all rules which require lookahead in this state */
129 /* first check for shift-reduce conflict, and try to resolve using precedence */
130
131 for (i = lookaheads[state]; i < k; i++)
132 if (rprec[LAruleno[i]])
133 {
134 fp1 = LA + i * tokensetsize;
135 fp2 = fp1;
136 fp3 = lookaheadset;
137
138 while (fp3 < fp4)
139 {
140 if (*fp2++ & *fp3++)
141 {
142 resolve_sr_conflict(state, i);
143 break;
144 }
145 }
146 }
147
148 /* loop over all rules which require lookahead in this state */
149 /* Check for conflicts not resolved above. */
150
151 for (i = lookaheads[state]; i < k; i++)
152 {
153 fp1 = LA + i * tokensetsize;
154 fp2 = fp1;
155 fp3 = lookaheadset;
156
157 while (fp3 < fp4)
158 {
159 if (*fp2++ & *fp3++)
160 {
161 conflicts[state] = 1;
162 any_conflicts = 1;
163 }
164 }
165
166 fp2 = fp1;
167 fp3 = lookaheadset;
168
169 while (fp3 < fp4)
170 *fp3++ |= *fp2++;
171 }
172 }
173
174
175
176 /* Attempt to resolve shift-reduce conflict for one rule
177 by means of precedence declarations.
178 It has already been checked that the rule has a precedence.
179 A conflict is resolved by modifying the shift or reduce tables
180 so that there is no longer a conflict. */
181
182 void
183 resolve_sr_conflict(state, lookaheadnum)
184 int state;
185 int lookaheadnum;
186 {
187 register int i;
188 register int mask;
189 register unsigned *fp1;
190 register unsigned *fp2;
191 register int redprec;
192 /* Extra parens avoid errors on Ultrix 4.3. */
193 errs *errp = (errs *) alloca ((sizeof(errs) + ntokens * sizeof(short)));
194 short *errtokens = errp->errs;
195
196 /* find the rule to reduce by to get precedence of reduction */
197 redprec = rprec[LAruleno[lookaheadnum]];
198
199 mask = 1;
200 fp1 = LA + lookaheadnum * tokensetsize;
201 fp2 = lookaheadset;
202 for (i = 0; i < ntokens; i++)
203 {
204 if ((mask & *fp2 & *fp1) && sprec[i])
205 /* Shift-reduce conflict occurs for token number i
206 and it has a precedence.
207 The precedence of shifting is that of token i. */
208 {
209 if (sprec[i] < redprec)
210 {
211 if (verboseflag) log_resolution(state, lookaheadnum, i, "reduce");
212 *fp2 &= ~mask; /* flush the shift for this token */
213 flush_shift(state, i);
214 }
215 else if (sprec[i] > redprec)
216 {
217 if (verboseflag) log_resolution(state, lookaheadnum, i, "shift");
218 *fp1 &= ~mask; /* flush the reduce for this token */
219 }
220 else
221 {
222 /* Matching precedence levels.
223 For left association, keep only the reduction.
224 For right association, keep only the shift.
225 For nonassociation, keep neither. */
226
227 switch (sassoc[i])
228 {
229
230 case RIGHT_ASSOC:
231 if (verboseflag) log_resolution(state, lookaheadnum, i, "shift");
232 break;
233
234 case LEFT_ASSOC:
235 if (verboseflag) log_resolution(state, lookaheadnum, i, "reduce");
236 break;
237
238 case NON_ASSOC:
239 if (verboseflag) log_resolution(state, lookaheadnum, i, "an error");
240 break;
241 }
242
243 if (sassoc[i] != RIGHT_ASSOC)
244 {
245 *fp2 &= ~mask; /* flush the shift for this token */
246 flush_shift(state, i);
247 }
248 if (sassoc[i] != LEFT_ASSOC)
249 {
250 *fp1 &= ~mask; /* flush the reduce for this token */
251 }
252 if (sassoc[i] == NON_ASSOC)
253 {
254 /* Record an explicit error for this token. */
255 *errtokens++ = i;
256 }
257 }
258 }
259
260 mask <<= 1;
261 if (mask == 0)
262 {
263 mask = 1;
264 fp2++; fp1++;
265 }
266 }
267 errp->nerrs = errtokens - errp->errs;
268 if (errp->nerrs)
269 {
270 /* Some tokens have been explicitly made errors. Allocate
271 a permanent errs structure for this state, to record them. */
272 i = (char *) errtokens - (char *) errp;
273 err_table[state] = (errs *) xmalloc ((unsigned int)i);
274 bcopy (errp, err_table[state], i);
275 }
276 else
277 err_table[state] = 0;
278 }
279
280
281
282 /* turn off the shift recorded for the specified token in the specified state.
283 Used when we resolve a shift-reduce conflict in favor of the reduction. */
284
285 void
286 flush_shift(state, token)
287 int state;
288 int token;
289 {
290 register shifts *shiftp;
291 register int k, i;
292 /* register unsigned symbol; JF unused */
293
294 shiftp = shift_table[state];
295
296 if (shiftp)
297 {
298 k = shiftp->nshifts;
299 for (i = 0; i < k; i++)
300 {
301 if (shiftp->shifts[i] && token == accessing_symbol[shiftp->shifts[i]])
302 (shiftp->shifts[i]) = 0;
303 }
304 }
305 }
306
307
308 void
309 log_resolution(state, LAno, token, resolution)
310 int state, LAno, token;
311 char *resolution;
312 {
313 fprintf(foutput,
314 "Conflict in state %d between rule %d and token %s resolved as %s.\n",
315 state, LAruleno[LAno], tags[token], resolution);
316 }
317
318
319 void
320 conflict_log()
321 {
322 register int i;
323
324 src_total = 0;
325 rrc_total = 0;
326
327 for (i = 0; i < nstates; i++)
328 {
329 if (conflicts[i])
330 {
331 count_sr_conflicts(i);
332 count_rr_conflicts(i);
333 src_total += src_count;
334 rrc_total += rrc_count;
335 }
336 }
337
338 total_conflicts();
339 }
340
341
342 void
343 verbose_conflict_log()
344 {
345 register int i;
346
347 src_total = 0;
348 rrc_total = 0;
349
350 for (i = 0; i < nstates; i++)
351 {
352 if (conflicts[i])
353 {
354 count_sr_conflicts(i);
355 count_rr_conflicts(i);
356 src_total += src_count;
357 rrc_total += rrc_count;
358
359 fprintf(foutput, "State %d contains", i);
360
361 if (src_count == 1)
362 fprintf(foutput, " 1 shift/reduce conflict");
363 else if (src_count > 1)
364 fprintf(foutput, " %d shift/reduce conflicts", src_count);
365
366 if (src_count > 0 && rrc_count > 0)
367 fprintf(foutput, " and");
368
369 if (rrc_count == 1)
370 fprintf(foutput, " 1 reduce/reduce conflict");
371 else if (rrc_count > 1)
372 fprintf(foutput, " %d reduce/reduce conflicts", rrc_count);
373
374 putc('.', foutput);
375 putc('\n', foutput);
376 }
377 }
378
379 total_conflicts();
380 }
381
382
383 void
384 total_conflicts()
385 {
386 extern int fixed_outfiles;
387
388 if (src_total == expected_conflicts && rrc_total == 0)
389 return;
390
391 if (fixed_outfiles)
392 {
393 /* If invoked under the name `yacc', use the output format
394 specified by POSIX. */
395 fprintf(stderr, "conflicts: ");
396 if (src_total > 0)
397 fprintf(stderr, " %d shift/reduce", src_total);
398 if (src_total > 0 && rrc_total > 0)
399 fprintf(stderr, ",");
400 if (rrc_total > 0)
401 fprintf(stderr, " %d reduce/reduce", rrc_total);
402 putc('\n', stderr);
403 }
404 else
405 {
406 fprintf(stderr, "%s contains", infile);
407
408 if (src_total == 1)
409 fprintf(stderr, " 1 shift/reduce conflict");
410 else if (src_total > 1)
411 fprintf(stderr, " %d shift/reduce conflicts", src_total);
412
413 if (src_total > 0 && rrc_total > 0)
414 fprintf(stderr, " and");
415
416 if (rrc_total == 1)
417 fprintf(stderr, " 1 reduce/reduce conflict");
418 else if (rrc_total > 1)
419 fprintf(stderr, " %d reduce/reduce conflicts", rrc_total);
420
421 putc('.', stderr);
422 putc('\n', stderr);
423 }
424 }
425
426
427 void
428 count_sr_conflicts(state)
429 int state;
430 {
431 register int i;
432 register int k;
433 register int mask;
434 register shifts *shiftp;
435 register unsigned *fp1;
436 register unsigned *fp2;
437 register unsigned *fp3;
438 register int symbol;
439
440 src_count = 0;
441
442 shiftp = shift_table[state];
443 if (!shiftp) return;
444
445 for (i = 0; i < tokensetsize; i++)
446 {
447 shiftset[i] = 0;
448 lookaheadset[i] = 0;
449 }
450
451 k = shiftp->nshifts;
452 for (i = 0; i < k; i++)
453 {
454 if (! shiftp->shifts[i]) continue;
455 symbol = accessing_symbol[shiftp->shifts[i]];
456 if (ISVAR(symbol)) break;
457 SETBIT(shiftset, symbol);
458 }
459
460 k = lookaheads[state + 1];
461 fp3 = lookaheadset + tokensetsize;
462
463 for (i = lookaheads[state]; i < k; i++)
464 {
465 fp1 = LA + i * tokensetsize;
466 fp2 = lookaheadset;
467
468 while (fp2 < fp3)
469 *fp2++ |= *fp1++;
470 }
471
472 fp1 = shiftset;
473 fp2 = lookaheadset;
474
475 while (fp2 < fp3)
476 *fp2++ &= *fp1++;
477
478 mask = 1;
479 fp2 = lookaheadset;
480 for (i = 0; i < ntokens; i++)
481 {
482 if (mask & *fp2)
483 src_count++;
484
485 mask <<= 1;
486 if (mask == 0)
487 {
488 mask = 1;
489 fp2++;
490 }
491 }
492 }
493
494
495 void
496 count_rr_conflicts(state)
497 int state;
498 {
499 register int i;
500 register int j;
501 register int count;
502 register unsigned mask;
503 register unsigned *baseword;
504 register unsigned *wordp;
505 register int m;
506 register int n;
507
508 rrc_count = 0;
509
510 m = lookaheads[state];
511 n = lookaheads[state + 1];
512
513 if (n - m < 2) return;
514
515 mask = 1;
516 baseword = LA + m * tokensetsize;
517 for (i = 0; i < ntokens; i++)
518 {
519 wordp = baseword;
520
521 count = 0;
522 for (j = m; j < n; j++)
523 {
524 if (mask & *wordp)
525 count++;
526
527 wordp += tokensetsize;
528 }
529
530 if (count >= 2) rrc_count++;
531
532 mask <<= 1;
533 if (mask == 0)
534 {
535 mask = 1;
536 baseword++;
537 }
538 }
539 }
540
541
542 void
543 print_reductions(state)
544 int state;
545 {
546 register int i;
547 register int j;
548 register int k;
549 register unsigned *fp1;
550 register unsigned *fp2;
551 register unsigned *fp3;
552 register unsigned *fp4;
553 register int rule;
554 register int symbol;
555 register unsigned mask;
556 register int m;
557 register int n;
558 register int default_LA;
559 register int default_rule;
560 register int cmax;
561 register int count;
562 register shifts *shiftp;
563 register errs *errp;
564 int nodefault = 0;
565
566 for (i = 0; i < tokensetsize; i++)
567 shiftset[i] = 0;
568
569 shiftp = shift_table[state];
570 if (shiftp)
571 {
572 k = shiftp->nshifts;
573 for (i = 0; i < k; i++)
574 {
575 if (! shiftp->shifts[i]) continue;
576 symbol = accessing_symbol[shiftp->shifts[i]];
577 if (ISVAR(symbol)) break;
578 /* if this state has a shift for the error token,
579 don't use a default rule. */
580 if (symbol == error_token_number) nodefault = 1;
581 SETBIT(shiftset, symbol);
582 }
583 }
584
585 errp = err_table[state];
586 if (errp)
587 {
588 k = errp->nerrs;
589 for (i = 0; i < k; i++)
590 {
591 if (! errp->errs[i]) continue;
592 symbol = errp->errs[i];
593 SETBIT(shiftset, symbol);
594 }
595 }
596
597 m = lookaheads[state];
598 n = lookaheads[state + 1];
599
600 if (n - m == 1 && ! nodefault)
601 {
602 default_rule = LAruleno[m];
603
604 fp1 = LA + m * tokensetsize;
605 fp2 = shiftset;
606 fp3 = lookaheadset;
607 fp4 = lookaheadset + tokensetsize;
608
609 while (fp3 < fp4)
610 *fp3++ = *fp1++ & *fp2++;
611
612 mask = 1;
613 fp3 = lookaheadset;
614
615 for (i = 0; i < ntokens; i++)
616 {
617 if (mask & *fp3)
618 fprintf(foutput, " %-4s\t[reduce using rule %d (%s)]\n",
619 tags[i], default_rule, tags[rlhs[default_rule]]);
620
621 mask <<= 1;
622 if (mask == 0)
623 {
624 mask = 1;
625 fp3++;
626 }
627 }
628
629 fprintf(foutput, " $default\treduce using rule %d (%s)\n\n",
630 default_rule, tags[rlhs[default_rule]]);
631 }
632 else if (n - m >= 1)
633 {
634 cmax = 0;
635 default_LA = -1;
636 fp4 = lookaheadset + tokensetsize;
637
638 if (! nodefault)
639 for (i = m; i < n; i++)
640 {
641 fp1 = LA + i * tokensetsize;
642 fp2 = shiftset;
643 fp3 = lookaheadset;
644
645 while (fp3 < fp4)
646 *fp3++ = *fp1++ & ( ~ (*fp2++));
647
648 count = 0;
649 mask = 1;
650 fp3 = lookaheadset;
651 for (j = 0; j < ntokens; j++)
652 {
653 if (mask & *fp3)
654 count++;
655
656 mask <<= 1;
657 if (mask == 0)
658 {
659 mask = 1;
660 fp3++;
661 }
662 }
663
664 if (count > cmax)
665 {
666 cmax = count;
667 default_LA = i;
668 default_rule = LAruleno[i];
669 }
670
671 fp2 = shiftset;
672 fp3 = lookaheadset;
673
674 while (fp3 < fp4)
675 *fp2++ |= *fp3++;
676 }
677
678 for (i = 0; i < tokensetsize; i++)
679 shiftset[i] = 0;
680
681 if (shiftp)
682 {
683 k = shiftp->nshifts;
684 for (i = 0; i < k; i++)
685 {
686 if (! shiftp->shifts[i]) continue;
687 symbol = accessing_symbol[shiftp->shifts[i]];
688 if (ISVAR(symbol)) break;
689 SETBIT(shiftset, symbol);
690 }
691 }
692
693 mask = 1;
694 fp1 = LA + m * tokensetsize;
695 fp2 = shiftset;
696 for (i = 0; i < ntokens; i++)
697 {
698 int defaulted = 0;
699
700 if (mask & *fp2)
701 count = 1;
702 else
703 count = 0;
704
705 fp3 = fp1;
706 for (j = m; j < n; j++)
707 {
708 if (mask & *fp3)
709 {
710 if (count == 0)
711 {
712 if (j != default_LA)
713 {
714 rule = LAruleno[j];
715 fprintf(foutput, " %-4s\treduce using rule %d (%s)\n",
716 tags[i], rule, tags[rlhs[rule]]);
717 }
718 else defaulted = 1;
719
720 count++;
721 }
722 else
723 {
724 if (defaulted)
725 {
726 rule = LAruleno[default_LA];
727 fprintf(foutput, " %-4s\treduce using rule %d (%s)\n",
728 tags[i], rule, tags[rlhs[rule]]);
729 defaulted = 0;
730 }
731 rule = LAruleno[j];
732 fprintf(foutput, " %-4s\t[reduce using rule %d (%s)]\n",
733 tags[i], rule, tags[rlhs[rule]]);
734 }
735 }
736
737 fp3 += tokensetsize;
738 }
739
740 mask <<= 1;
741 if (mask == 0)
742 {
743 mask = 1;
744 /* This used to be fp1, but I think fp2 is right
745 because fp2 is where the words are fetched to test with mask
746 in this loop. */
747 fp2++;
748 }
749 }
750
751 if (default_LA >= 0)
752 {
753 fprintf(foutput, " $default\treduce using rule %d (%s)\n",
754 default_rule, tags[rlhs[default_rule]]);
755 }
756
757 putc('\n', foutput);
758 }
759 }
760
761
762 void
763 finalize_conflicts()
764 {
765 FREE(conflicts);
766 FREE(shiftset);
767 FREE(lookaheadset);
768 }