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