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