]> git.saurik.com Git - bison.git/blame - src/conflicts.c
* tests/regression.at (AT_TEST_CPP_GUARD_H): Adjust the clean up
[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_count;
39static int rrc_count;
c29240e7 40\f
08089d5d 41
c29240e7
AD
42static inline void
43log_resolution (int state, int LAno, int token, char *resolution)
08089d5d 44{
ff4423cc
AD
45 obstack_fgrow4 (&output_obstack,
46 _("\
c29240e7 47Conflict in state %d between rule %d and token %s resolved as %s.\n"),
ff4423cc 48 state, LAruleno[LAno], tags[token], resolution);
08089d5d
DM
49}
50
51
c29240e7
AD
52/*------------------------------------------------------------------.
53| Turn off the shift recorded for the specified token in the |
54| specified state. Used when we resolve a shift-reduce conflict in |
55| favor of the reduction. |
56`------------------------------------------------------------------*/
57
4a120d45 58static void
c29240e7 59flush_shift (int state, int token)
08089d5d 60{
c29240e7
AD
61 shifts *shiftp;
62 int k, i;
08089d5d
DM
63
64 shiftp = shift_table[state];
c29240e7 65
08089d5d
DM
66 if (shiftp)
67 {
68 k = shiftp->nshifts;
69 for (i = 0; i < k; i++)
70 {
c29240e7
AD
71 if (shiftp->shifts[i]
72 && token == accessing_symbol[shiftp->shifts[i]])
73 (shiftp->shifts[i]) = 0;
08089d5d 74 }
08089d5d
DM
75 }
76}
77
78
c29240e7
AD
79/*------------------------------------------------------------------.
80| Attempt to resolve shift-reduce conflict for one rule by means of |
81| precedence declarations. It has already been checked that the |
82| rule has a precedence. A conflict is resolved by modifying the |
83| shift or reduce tables so that there is no longer a conflict. |
84`------------------------------------------------------------------*/
08089d5d 85
4a120d45 86static void
d2729d44 87resolve_sr_conflict (int state, int lookaheadnum)
08089d5d 88{
c29240e7
AD
89 int i;
90 int mask;
91 unsigned *fp1;
92 unsigned *fp2;
93 int redprec;
d7913476 94 errs *errp = (errs *) xcalloc (sizeof (errs) + ntokens * sizeof (short), 1);
08089d5d
DM
95 short *errtokens = errp->errs;
96
97 /* find the rule to reduce by to get precedence of reduction */
98 redprec = rprec[LAruleno[lookaheadnum]];
99
100 mask = 1;
101 fp1 = LA + lookaheadnum * tokensetsize;
102 fp2 = lookaheadset;
103 for (i = 0; i < ntokens; i++)
104 {
105 if ((mask & *fp2 & *fp1) && sprec[i])
106 /* Shift-reduce conflict occurs for token number i
107 and it has a precedence.
108 The precedence of shifting is that of token i. */
109 {
110 if (sprec[i] < redprec)
111 {
c29240e7
AD
112 log_resolution (state, lookaheadnum, i, _("reduce"));
113 *fp2 &= ~mask; /* flush the shift for this token */
114 flush_shift (state, i);
08089d5d
DM
115 }
116 else if (sprec[i] > redprec)
117 {
c29240e7
AD
118 log_resolution (state, lookaheadnum, i, _("shift"));
119 *fp1 &= ~mask; /* flush the reduce for this token */
08089d5d
DM
120 }
121 else
122 {
123 /* Matching precedence levels.
c29240e7
AD
124 For left association, keep only the reduction.
125 For right association, keep only the shift.
126 For nonassociation, keep neither. */
08089d5d
DM
127
128 switch (sassoc[i])
129 {
d7020c20 130 case right_assoc:
c29240e7 131 log_resolution (state, lookaheadnum, i, _("shift"));
08089d5d
DM
132 break;
133
d7020c20 134 case left_assoc:
c29240e7 135 log_resolution (state, lookaheadnum, i, _("reduce"));
08089d5d
DM
136 break;
137
d7020c20 138 case non_assoc:
c29240e7 139 log_resolution (state, lookaheadnum, i, _("an error"));
08089d5d
DM
140 break;
141 }
142
d7020c20 143 if (sassoc[i] != right_assoc)
08089d5d 144 {
c29240e7
AD
145 *fp2 &= ~mask; /* flush the shift for this token */
146 flush_shift (state, i);
08089d5d 147 }
d7020c20 148 if (sassoc[i] != left_assoc)
c29240e7
AD
149 {
150 *fp1 &= ~mask; /* flush the reduce for this token */
08089d5d 151 }
d7020c20 152 if (sassoc[i] == non_assoc)
08089d5d
DM
153 {
154 /* Record an explicit error for this token. */
155 *errtokens++ = i;
156 }
157 }
158 }
159
160 mask <<= 1;
161 if (mask == 0)
162 {
163 mask = 1;
c29240e7
AD
164 fp2++;
165 fp1++;
08089d5d
DM
166 }
167 }
168 errp->nerrs = errtokens - errp->errs;
169 if (errp->nerrs)
170 {
171 /* Some tokens have been explicitly made errors. Allocate
c29240e7 172 a permanent errs structure for this state, to record them. */
08089d5d 173 i = (char *) errtokens - (char *) errp;
d7913476 174 err_table[state] = (errs *) xcalloc ((unsigned int) i, 1);
08089d5d
DM
175 bcopy (errp, err_table[state], i);
176 }
177 else
178 err_table[state] = 0;
c29240e7 179 free (errp);
08089d5d
DM
180}
181
182
4a120d45 183static void
c29240e7 184set_conflicts (int state)
08089d5d 185{
c29240e7
AD
186 int i;
187 int k;
188 shifts *shiftp;
189 unsigned *fp2;
190 unsigned *fp3;
191 unsigned *fp4;
192 unsigned *fp1;
193 int symbol;
194
195 if (consistent[state])
196 return;
08089d5d 197
c29240e7
AD
198 for (i = 0; i < tokensetsize; i++)
199 lookaheadset[i] = 0;
08089d5d 200
c29240e7 201 shiftp = shift_table[state];
08089d5d
DM
202 if (shiftp)
203 {
204 k = shiftp->nshifts;
205 for (i = 0; i < k; i++)
206 {
c29240e7
AD
207 symbol = accessing_symbol[shiftp->shifts[i]];
208 if (ISVAR (symbol))
209 break;
210 SETBIT (lookaheadset, symbol);
08089d5d
DM
211 }
212 }
08089d5d 213
c29240e7
AD
214 k = lookaheads[state + 1];
215 fp4 = lookaheadset + tokensetsize;
08089d5d 216
c29240e7
AD
217 /* Loop over all rules which require lookahead in this state. First
218 check for shift-reduce conflict, and try to resolve using
219 precedence */
220 for (i = lookaheads[state]; i < k; i++)
221 if (rprec[LAruleno[i]])
222 {
223 fp1 = LA + i * tokensetsize;
224 fp2 = fp1;
225 fp3 = lookaheadset;
08089d5d 226
c29240e7
AD
227 while (fp3 < fp4)
228 {
229 if (*fp2++ & *fp3++)
230 {
231 resolve_sr_conflict (state, i);
232 break;
233 }
234 }
235 }
08089d5d 236
08089d5d 237
c29240e7
AD
238 /* Loop over all rules which require lookahead in this state. Check
239 for conflicts not resolved above. */
240 for (i = lookaheads[state]; i < k; i++)
08089d5d 241 {
c29240e7
AD
242 fp1 = LA + i * tokensetsize;
243 fp2 = fp1;
244 fp3 = lookaheadset;
245
246 while (fp3 < fp4)
08089d5d 247 {
c29240e7
AD
248 if (*fp2++ & *fp3++)
249 {
250 conflicts[state] = 1;
251 any_conflicts = 1;
252 }
08089d5d 253 }
08089d5d 254
c29240e7
AD
255 fp2 = fp1;
256 fp3 = lookaheadset;
ceed8467 257
c29240e7
AD
258 while (fp3 < fp4)
259 *fp3++ |= *fp2++;
260 }
261}
08089d5d
DM
262
263void
342b8b6e 264solve_conflicts (void)
08089d5d 265{
c29240e7 266 int i;
08089d5d 267
d7913476
AD
268 conflicts = XCALLOC (char, nstates);
269 shiftset = XCALLOC (unsigned, tokensetsize);
270 lookaheadset = XCALLOC (unsigned, tokensetsize);
08089d5d 271
d7913476 272 err_table = XCALLOC (errs *, nstates);
08089d5d 273
c29240e7 274 any_conflicts = 0;
08089d5d 275
c29240e7
AD
276 for (i = 0; i < nstates; i++)
277 set_conflicts (i);
08089d5d
DM
278}
279
280
c29240e7
AD
281/*---------------------------------------------.
282| Count the number of shift/reduce conflicts. |
283`---------------------------------------------*/
284
4a120d45 285static void
d2729d44 286count_sr_conflicts (int state)
08089d5d 287{
c29240e7
AD
288 int i;
289 int k;
290 int mask;
291 shifts *shiftp;
292 unsigned *fp1;
293 unsigned *fp2;
294 unsigned *fp3;
295 int symbol;
08089d5d
DM
296
297 src_count = 0;
298
299 shiftp = shift_table[state];
c29240e7
AD
300 if (!shiftp)
301 return;
08089d5d
DM
302
303 for (i = 0; i < tokensetsize; i++)
304 {
305 shiftset[i] = 0;
306 lookaheadset[i] = 0;
307 }
308
309 k = shiftp->nshifts;
310 for (i = 0; i < k; i++)
311 {
c29240e7
AD
312 if (!shiftp->shifts[i])
313 continue;
08089d5d 314 symbol = accessing_symbol[shiftp->shifts[i]];
c29240e7
AD
315 if (ISVAR (symbol))
316 break;
317 SETBIT (shiftset, symbol);
08089d5d
DM
318 }
319
320 k = lookaheads[state + 1];
321 fp3 = lookaheadset + tokensetsize;
322
323 for (i = lookaheads[state]; i < k; i++)
324 {
325 fp1 = LA + i * tokensetsize;
326 fp2 = lookaheadset;
327
328 while (fp2 < fp3)
329 *fp2++ |= *fp1++;
330 }
331
332 fp1 = shiftset;
333 fp2 = lookaheadset;
334
335 while (fp2 < fp3)
336 *fp2++ &= *fp1++;
337
338 mask = 1;
339 fp2 = lookaheadset;
340 for (i = 0; i < ntokens; i++)
341 {
342 if (mask & *fp2)
343 src_count++;
344
345 mask <<= 1;
346 if (mask == 0)
347 {
348 mask = 1;
349 fp2++;
350 }
351 }
352}
353
354
c29240e7
AD
355/*----------------------------------------------.
356| Count the number of reduce/reduce conflicts. |
357`----------------------------------------------*/
358
4a120d45 359static void
d2729d44 360count_rr_conflicts (int state)
08089d5d 361{
c29240e7
AD
362 int i;
363 int j;
364 int count;
365 unsigned mask;
366 unsigned *baseword;
367 unsigned *wordp;
368 int m;
369 int n;
08089d5d
DM
370
371 rrc_count = 0;
372
373 m = lookaheads[state];
374 n = lookaheads[state + 1];
375
c29240e7
AD
376 if (n - m < 2)
377 return;
08089d5d
DM
378
379 mask = 1;
380 baseword = LA + m * tokensetsize;
381 for (i = 0; i < ntokens; i++)
382 {
383 wordp = baseword;
384
385 count = 0;
386 for (j = m; j < n; j++)
387 {
388 if (mask & *wordp)
389 count++;
390
391 wordp += tokensetsize;
392 }
393
c29240e7
AD
394 if (count >= 2)
395 rrc_count++;
08089d5d
DM
396
397 mask <<= 1;
398 if (mask == 0)
399 {
400 mask = 1;
401 baseword++;
402 }
403 }
404}
405
ff4423cc
AD
406/*--------------------------------------------------------------.
407| Return a human readable string which reports shift/reduce and |
408| reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
409`--------------------------------------------------------------*/
c29240e7 410
ff4423cc
AD
411static const char *
412conflict_report (int src_num, int rrc_num)
c29240e7 413{
ff4423cc
AD
414 static char res[4096];
415 char *cp = res;
416
0619caf0 417 if (src_num == 1)
22c821f3
AD
418 {
419 sprintf (cp, _(" 1 shift/reduce conflict"));
420 cp += strlen (cp);
421 }
0619caf0 422 else if (src_num > 1)
22c821f3
AD
423 {
424 sprintf (cp, _(" %d shift/reduce conflicts"), src_num);
425 cp += strlen (cp);
426 }
c29240e7 427
0619caf0 428 if (src_num > 0 && rrc_num > 0)
22c821f3
AD
429 {
430 sprintf (cp, _(" and"));
431 cp += strlen (cp);
432 }
c29240e7 433
0619caf0 434 if (rrc_num == 1)
22c821f3
AD
435 {
436 sprintf (cp, _(" 1 reduce/reduce conflict"));
437 cp += strlen (cp);
438 }
0619caf0 439 else if (rrc_num > 1)
22c821f3
AD
440 {
441 sprintf (cp, _(" %d reduce/reduce conflicts"), rrc_num);
442 cp += strlen (cp);
443 }
ff4423cc
AD
444
445 *cp++ = '.';
446 *cp++ = '\n';
447 *cp++ = '\0';
c29240e7 448
ff4423cc 449 return res;
c29240e7
AD
450}
451
452
453/*---------------------------------------------.
454| Compute and give a report on the conflicts. |
455`---------------------------------------------*/
456
457void
342b8b6e 458print_conflicts (FILE *out)
c29240e7
AD
459{
460 int i;
0846f581
PB
461 int src_total;
462 int rrc_total;
c29240e7
AD
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}