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