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