]> git.saurik.com Git - bison.git/blame - src/conflicts.c
* src/output.c (output_table_data): Change the prototype to use
[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"
7da99ede 22#include "complain.h"
ceed8467 23#include "getargs.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"
b2ca4022
AD
29#include "reader.h"
30#include "LR0.h"
d2729d44 31
7da99ede
AD
32/* -1 stands for not specified. */
33int expected_conflicts = -1;
342b8b6e 34static char *conflicts = NULL;
08089d5d 35
342b8b6e
AD
36static unsigned *shiftset = NULL;
37static unsigned *lookaheadset = NULL;
c29240e7 38\f
08089d5d 39
c29240e7
AD
40static inline void
41log_resolution (int state, int LAno, int token, char *resolution)
08089d5d 42{
64d15509
AD
43 if (verbose_flag)
44 obstack_fgrow4 (&output_obstack,
45 _("\
c29240e7 46Conflict in state %d between rule %d and token %s resolved as %s.\n"),
64d15509 47 state, LAruleno[LAno], tags[token], resolution);
08089d5d
DM
48}
49
50
c29240e7
AD
51/*------------------------------------------------------------------.
52| Turn off the shift recorded for the specified token in the |
53| specified state. Used when we resolve a shift-reduce conflict in |
54| favor of the reduction. |
55`------------------------------------------------------------------*/
56
4a120d45 57static void
c29240e7 58flush_shift (int state, int token)
08089d5d 59{
f693ad14 60 shifts *shiftp = state_table[state]->shifts;
9f136c07 61 int i;
c29240e7 62
709ae8c6 63 RESETBIT (lookaheadset, token);
d954473d
AD
64 for (i = 0; i < shiftp->nshifts; i++)
65 if (!SHIFT_IS_DISABLED (shiftp, i) && SHIFT_SYMBOL (shiftp, i) == token)
66 SHIFT_DISABLE (shiftp, i);
08089d5d
DM
67}
68
69
709ae8c6
AD
70/*-------------------------------------------------------------------.
71| Turn off the reduce recorded for the specified token for the |
72| specified lookahead. Used when we resolve a shift-reduce conflict |
73| in favor of the shift. |
74`-------------------------------------------------------------------*/
75
76static void
77flush_reduce (int lookahead, int token)
78{
79 RESETBIT (LA (lookahead), token);
80}
81
82
c29240e7
AD
83/*------------------------------------------------------------------.
84| Attempt to resolve shift-reduce conflict for one rule by means of |
85| precedence declarations. It has already been checked that the |
86| rule has a precedence. A conflict is resolved by modifying the |
87| shift or reduce tables so that there is no longer a conflict. |
88`------------------------------------------------------------------*/
08089d5d 89
4a120d45 90static void
709ae8c6 91resolve_sr_conflict (int state, int lookahead)
08089d5d 92{
c29240e7 93 int i;
9f136c07 94 /* find the rule to reduce by to get precedence of reduction */
709ae8c6 95 int redprec = rule_table[LAruleno[lookahead]].prec;
f59c437a 96 errs *errp = ERRS_ALLOC (ntokens + 1);
08089d5d
DM
97 short *errtokens = errp->errs;
98
08089d5d 99 for (i = 0; i < ntokens; i++)
709ae8c6 100 if (BITISSET (LA (lookahead), i)
92b16366
AD
101 && BITISSET (lookaheadset, i)
102 && sprec[i])
92b16366 103 {
709ae8c6
AD
104 /* Shift-reduce conflict occurs for token number i
105 and it has a precedence.
106 The precedence of shifting is that of token i. */
92b16366
AD
107 if (sprec[i] < redprec)
108 {
709ae8c6 109 log_resolution (state, lookahead, i, _("reduce"));
92b16366
AD
110 flush_shift (state, i);
111 }
112 else if (sprec[i] > redprec)
113 {
709ae8c6
AD
114 log_resolution (state, lookahead, i, _("shift"));
115 flush_reduce (lookahead, i);
92b16366
AD
116 }
117 else
709ae8c6
AD
118 /* Matching precedence levels.
119 For left association, keep only the reduction.
120 For right association, keep only the shift.
121 For nonassociation, keep neither. */
122
123 switch (sassoc[i])
124 {
125 case right_assoc:
126 log_resolution (state, lookahead, i, _("shift"));
127 flush_reduce (lookahead, i);
128 break;
129
130 case left_assoc:
131 log_resolution (state, lookahead, i, _("reduce"));
132 flush_shift (state, i);
133 break;
134
135 case non_assoc:
136 log_resolution (state, lookahead, i, _("an error"));
137 flush_shift (state, i);
138 flush_reduce (lookahead, i);
139 /* Record an explicit error for this token. */
140 *errtokens++ = i;
141 break;
142 }
92b16366
AD
143 }
144
08089d5d 145 errp->nerrs = errtokens - errp->errs;
92b16366
AD
146 /* Some tokens have been explicitly made errors. Allocate a
147 permanent errs structure for this state, to record them. */
148 i = (char *) errtokens - (char *) errp;
f693ad14
AD
149 state_table[state]->errs = ERRS_ALLOC (i + 1);
150 memcpy (state_table[state]->errs, errp, i);
c29240e7 151 free (errp);
08089d5d
DM
152}
153
154
4a120d45 155static void
c29240e7 156set_conflicts (int state)
08089d5d 157{
d8cf039f 158 int i, j;
c29240e7 159 shifts *shiftp;
c29240e7 160
f693ad14 161 if (state_table[state]->consistent)
c29240e7 162 return;
08089d5d 163
c29240e7
AD
164 for (i = 0; i < tokensetsize; i++)
165 lookaheadset[i] = 0;
08089d5d 166
f693ad14 167 shiftp = state_table[state]->shifts;
d954473d
AD
168 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
169 if (!SHIFT_IS_DISABLED (shiftp, i))
170 SETBIT (lookaheadset, SHIFT_SYMBOL (shiftp, i));
08089d5d 171
c29240e7
AD
172 /* Loop over all rules which require lookahead in this state. First
173 check for shift-reduce conflict, and try to resolve using
174 precedence */
3877f72b
AD
175 for (i = state_table[state]->lookaheadsp;
176 i < state_table[state + 1]->lookaheadsp;
d8cf039f 177 ++i)
652a871c 178 if (rule_table[LAruleno[i]].prec)
d8cf039f
AD
179 for (j = 0; j < tokensetsize; ++j)
180 if (LA (i)[j] & lookaheadset[j])
c29240e7 181 {
d8cf039f
AD
182 resolve_sr_conflict (state, i);
183 break;
c29240e7 184 }
08089d5d 185
08089d5d 186
c29240e7
AD
187 /* Loop over all rules which require lookahead in this state. Check
188 for conflicts not resolved above. */
3877f72b
AD
189 for (i = state_table[state]->lookaheadsp;
190 i < state_table[state + 1]->lookaheadsp;
d8cf039f 191 ++i)
08089d5d 192 {
d8cf039f
AD
193 for (j = 0; j < tokensetsize; ++j)
194 if (LA (i)[j] & lookaheadset[j])
0df87bb6 195 conflicts[state] = 1;
08089d5d 196
d8cf039f
AD
197 for (j = 0; j < tokensetsize; ++j)
198 lookaheadset[j] |= LA (i)[j];
c29240e7
AD
199 }
200}
08089d5d
DM
201
202void
342b8b6e 203solve_conflicts (void)
08089d5d 204{
c29240e7 205 int i;
08089d5d 206
d7913476
AD
207 conflicts = XCALLOC (char, nstates);
208 shiftset = XCALLOC (unsigned, tokensetsize);
209 lookaheadset = XCALLOC (unsigned, tokensetsize);
08089d5d 210
c29240e7
AD
211 for (i = 0; i < nstates; i++)
212 set_conflicts (i);
08089d5d
DM
213}
214
215
c29240e7
AD
216/*---------------------------------------------.
217| Count the number of shift/reduce conflicts. |
218`---------------------------------------------*/
219
0df87bb6 220static int
d2729d44 221count_sr_conflicts (int state)
08089d5d 222{
52afa962 223 int i, k;
0df87bb6 224 int src_count = 0;
f693ad14 225 shifts *shiftp = state_table[state]->shifts;
08089d5d 226
c29240e7 227 if (!shiftp)
0df87bb6 228 return 0;
08089d5d
DM
229
230 for (i = 0; i < tokensetsize; i++)
231 {
232 shiftset[i] = 0;
233 lookaheadset[i] = 0;
234 }
235
52afa962 236 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
9839bbe5
AD
237 if (!SHIFT_IS_DISABLED (shiftp, i))
238 SETBIT (shiftset, SHIFT_SYMBOL (shiftp, i));
08089d5d 239
3877f72b
AD
240 for (i = state_table[state]->lookaheadsp;
241 i < state_table[state + 1]->lookaheadsp;
52afa962
AD
242 ++i)
243 for (k = 0; k < tokensetsize; ++k)
244 lookaheadset[k] |= LA (i)[k];
08089d5d 245
52afa962
AD
246 for (k = 0; k < tokensetsize; ++k)
247 lookaheadset[k] &= shiftset[k];
08089d5d 248
08089d5d 249 for (i = 0; i < ntokens; i++)
52afa962
AD
250 if (BITISSET (lookaheadset, i))
251 src_count++;
0df87bb6
AD
252
253 return src_count;
08089d5d
DM
254}
255
256
c29240e7
AD
257/*----------------------------------------------.
258| Count the number of reduce/reduce conflicts. |
259`----------------------------------------------*/
260
0df87bb6 261static int
d2729d44 262count_rr_conflicts (int state)
08089d5d 263{
c29240e7 264 int i;
0df87bb6 265 int rrc_count = 0;
08089d5d 266
3877f72b
AD
267 int m = state_table[state]->lookaheadsp;
268 int n = state_table[state + 1]->lookaheadsp;
08089d5d 269
c29240e7 270 if (n - m < 2)
0df87bb6 271 return 0;
08089d5d 272
08089d5d
DM
273 for (i = 0; i < ntokens; i++)
274 {
0df87bb6
AD
275 int count = 0;
276 int j;
08089d5d 277 for (j = m; j < n; j++)
52afa962
AD
278 if (BITISSET (LA (m), j))
279 count++;
08089d5d 280
c29240e7
AD
281 if (count >= 2)
282 rrc_count++;
08089d5d 283 }
0df87bb6
AD
284
285 return rrc_count;
08089d5d
DM
286}
287
ff4423cc
AD
288/*--------------------------------------------------------------.
289| Return a human readable string which reports shift/reduce and |
290| reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
291`--------------------------------------------------------------*/
c29240e7 292
ff4423cc
AD
293static const char *
294conflict_report (int src_num, int rrc_num)
c29240e7 295{
ff4423cc
AD
296 static char res[4096];
297 char *cp = res;
298
7da99ede 299 if (src_num >= 1)
22c821f3 300 {
7da99ede
AD
301 sprintf (cp, ngettext ("%d shift/reduce conflict",
302 "%d shift/reduce conflicts", src_num), src_num);
22c821f3
AD
303 cp += strlen (cp);
304 }
c29240e7 305
0619caf0 306 if (src_num > 0 && rrc_num > 0)
22c821f3 307 {
7da99ede 308 sprintf (cp, " %s ", _("and"));
22c821f3
AD
309 cp += strlen (cp);
310 }
c29240e7 311
7da99ede 312 if (rrc_num >= 1)
22c821f3 313 {
7da99ede
AD
314 sprintf (cp, ngettext ("%d reduce/reduce conflict",
315 "%d reduce/reduce conflicts", rrc_num), rrc_num);
22c821f3
AD
316 cp += strlen (cp);
317 }
ff4423cc
AD
318
319 *cp++ = '.';
320 *cp++ = '\n';
321 *cp++ = '\0';
c29240e7 322
ff4423cc 323 return res;
c29240e7
AD
324}
325
326
0df87bb6
AD
327/*-----------------------------------------------------------.
328| Output the detailed description of states with conflicts. |
329`-----------------------------------------------------------*/
c29240e7
AD
330
331void
0df87bb6 332conflicts_output (FILE *out)
c29240e7 333{
d2d1b42b 334 bool printed_sth = FALSE;
c29240e7 335 int i;
0df87bb6
AD
336 for (i = 0; i < nstates; i++)
337 if (conflicts[i])
338 {
7da99ede 339 fprintf (out, _("State %d contains "), i);
0df87bb6
AD
340 fputs (conflict_report (count_sr_conflicts (i),
341 count_rr_conflicts (i)), out);
d2d1b42b 342 printed_sth = TRUE;
0df87bb6 343 }
d2d1b42b
AD
344 if (printed_sth)
345 fputs ("\n\n", out);
0df87bb6 346}
c29240e7 347
c29240e7 348
0df87bb6
AD
349/*------------------------------------------.
350| Reporting the total number of conflicts. |
351`------------------------------------------*/
0619caf0 352
0df87bb6
AD
353void
354conflicts_print (void)
355{
356 int i;
357
a034c8b8
AD
358 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
359 not set, and then we want 0 SR, or else it is specified, in which
360 case we want equality. */
361 int src_ok = 0;
362
0df87bb6
AD
363 int src_total = 0;
364 int rrc_total = 0;
365
366 /* Conflicts by state. */
367 for (i = 0; i < nstates; i++)
368 if (conflicts[i])
369 {
370 src_total += count_sr_conflicts (i);
371 rrc_total += count_rr_conflicts (i);
372 }
c29240e7 373
a034c8b8
AD
374 src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
375
376 /* If there are no RR conflicts, and as many SR conflicts as
377 expected, then there is nothing to report. */
378 if (!rrc_total && src_ok)
379 return;
380
0619caf0 381 /* Report the total number of conflicts on STDERR. */
a034c8b8 382 if (yacc_flag)
09b503c8 383 {
a034c8b8
AD
384 /* If invoked with `--yacc', use the output format specified by
385 POSIX. */
386 fprintf (stderr, _("conflicts: "));
387 if (src_total > 0)
388 fprintf (stderr, _(" %d shift/reduce"), src_total);
389 if (src_total > 0 && rrc_total > 0)
390 fprintf (stderr, ",");
391 if (rrc_total > 0)
392 fprintf (stderr, _(" %d reduce/reduce"), rrc_total);
393 putc ('\n', stderr);
394 }
395 else
396 {
397 fprintf (stderr, _("%s contains "), infile);
398 fputs (conflict_report (src_total, rrc_total), stderr);
09b503c8 399 }
7da99ede 400
a034c8b8 401 if (expected_conflicts != -1 && !src_ok)
7da99ede
AD
402 {
403 complain_message_count++;
81e895c0
AD
404 fprintf (stderr, ngettext ("expected %d shift/reduce conflict\n",
405 "expected %d shift/reduce conflicts\n",
7da99ede
AD
406 expected_conflicts),
407 expected_conflicts);
408 }
c29240e7
AD
409}
410
411
08089d5d 412void
c73a41af 413print_reductions (FILE *out, int state)
08089d5d 414{
c29240e7 415 int i;
3877f72b
AD
416 int m = state_table[state]->lookaheadsp;
417 int n = state_table[state + 1]->lookaheadsp;
be750e4c
AD
418 shifts *shiftp = state_table[state]->shifts;
419 errs *errp = state_table[state]->errs;
08089d5d
DM
420 int nodefault = 0;
421
422 for (i = 0; i < tokensetsize; i++)
423 shiftset[i] = 0;
424
d954473d
AD
425 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
426 if (!SHIFT_IS_DISABLED (shiftp, i))
427 {
428 /* if this state has a shift for the error token, don't use a
429 default rule. */
430 if (SHIFT_IS_ERROR (shiftp, i))
431 nodefault = 1;
432 SETBIT (shiftset, SHIFT_SYMBOL (shiftp, i));
433 }
08089d5d 434
08089d5d 435 if (errp)
e74dc321
AD
436 for (i = 0; i < errp->nerrs; i++)
437 if (errp->errs[i])
438 SETBIT (shiftset, errp->errs[i]);
08089d5d 439
c29240e7 440 if (n - m == 1 && !nodefault)
08089d5d 441 {
a04bc341 442 int k;
52afa962 443 int default_rule = LAruleno[m];
08089d5d 444
a04bc341
AD
445 for (k = 0; k < tokensetsize; ++k)
446 lookaheadset[k] = LA (m)[k] & shiftset[k];
08089d5d
DM
447
448 for (i = 0; i < ntokens; i++)
a04bc341
AD
449 if (BITISSET (lookaheadset, i))
450 fprintf (out, _(" %-4s\t[reduce using rule %d (%s)]\n"),
451 tags[i], default_rule,
452 tags[rule_table[default_rule].lhs]);
08089d5d 453
c73a41af 454 fprintf (out, _(" $default\treduce using rule %d (%s)\n\n"),
b2ed6e58 455 default_rule, tags[rule_table[default_rule].lhs]);
08089d5d
DM
456 }
457 else if (n - m >= 1)
458 {
52afa962
AD
459 int cmax = 0;
460 int default_LA = -1;
461 int default_rule = 0;
08089d5d 462
c29240e7 463 if (!nodefault)
08089d5d
DM
464 for (i = m; i < n; i++)
465 {
e74dc321 466 int count = 0;
776209d6 467 int j, k;
e74dc321 468
768fca83
AD
469 for (k = 0; k < tokensetsize; ++k)
470 lookaheadset[k] = LA (i)[k] & ~shiftset[k];
ceed8467 471
08089d5d 472 for (j = 0; j < ntokens; j++)
768fca83
AD
473 if (BITISSET (lookaheadset, j))
474 count++;
ceed8467 475
08089d5d
DM
476 if (count > cmax)
477 {
478 cmax = count;
479 default_LA = i;
480 default_rule = LAruleno[i];
481 }
ceed8467 482
e74dc321
AD
483 for (k = 0; k < tokensetsize; ++k)
484 shiftset[k] |= lookaheadset[k];
08089d5d
DM
485 }
486
487 for (i = 0; i < tokensetsize; i++)
c29240e7 488 shiftset[i] = 0;
08089d5d 489
d954473d
AD
490 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
491 if (!SHIFT_IS_DISABLED (shiftp, i))
492 SETBIT (shiftset, SHIFT_SYMBOL (shiftp, i));
08089d5d 493
08089d5d
DM
494 for (i = 0; i < ntokens; i++)
495 {
776209d6 496 int j;
08089d5d 497 int defaulted = 0;
e74dc321 498 int count = BITISSET (shiftset, i);
08089d5d 499
08089d5d
DM
500 for (j = m; j < n; j++)
501 {
776209d6 502 if (BITISSET (LA (j), i))
08089d5d
DM
503 {
504 if (count == 0)
505 {
506 if (j != default_LA)
a17e599f
AD
507 fprintf (out,
508 _(" %-4s\treduce using rule %d (%s)\n"),
509 tags[i],
510 LAruleno[j],
511 tags[rule_table[LAruleno[j]].lhs]);
c29240e7
AD
512 else
513 defaulted = 1;
08089d5d
DM
514
515 count++;
516 }
517 else
518 {
519 if (defaulted)
a17e599f
AD
520 fprintf (out,
521 _(" %-4s\treduce using rule %d (%s)\n"),
522 tags[i],
523 LAruleno[default_LA],
524 tags[rule_table[LAruleno[default_LA]].lhs]);
525 defaulted = 0;
c73a41af 526 fprintf (out,
c29240e7 527 _(" %-4s\t[reduce using rule %d (%s)]\n"),
a17e599f
AD
528 tags[i],
529 LAruleno[j],
530 tags[rule_table[LAruleno[j]].lhs]);
08089d5d
DM
531 }
532 }
08089d5d
DM
533 }
534 }
535
536 if (default_LA >= 0)
c73a41af 537 fprintf (out, _(" $default\treduce using rule %d (%s)\n"),
b2ed6e58 538 default_rule, tags[rule_table[default_rule].lhs]);
08089d5d
DM
539 }
540}
541
542
543void
342b8b6e 544free_conflicts (void)
08089d5d 545{
d7913476
AD
546 XFREE (conflicts);
547 XFREE (shiftset);
548 XFREE (lookaheadset);
08089d5d 549}