]> git.saurik.com Git - bison.git/blame - src/conflicts.c
* src/conflicts.c (log_resolution): Accept the rule involved in
[bison.git] / src / conflicts.c
CommitLineData
08089d5d 1/* Find and resolve or report look-ahead conflicts for bison,
03b31c0c
AD
2 Copyright (C) 1984, 1989, 1992, 2000, 2001, 2002
3 Free Software Foundation, Inc.
08089d5d 4
ceed8467 5 This file is part of Bison, the GNU Compiler Compiler.
08089d5d 6
ceed8467
AD
7 Bison is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
08089d5d 11
ceed8467
AD
12 Bison is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
08089d5d 16
ceed8467
AD
17 You should have received a copy of the GNU General Public License
18 along with Bison; see the file COPYING. If not, write to the Free
19 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
08089d5d 21
08089d5d 22#include "system.h"
602bbf31 23#include "bitset.h"
7da99ede 24#include "complain.h"
ceed8467 25#include "getargs.h"
0e78e603 26#include "symtab.h"
08089d5d
DM
27#include "files.h"
28#include "gram.h"
29#include "state.h"
720d742f 30#include "lalr.h"
0619caf0 31#include "conflicts.h"
b2ca4022
AD
32#include "reader.h"
33#include "LR0.h"
d2729d44 34
7da99ede
AD
35/* -1 stands for not specified. */
36int expected_conflicts = -1;
342b8b6e 37static char *conflicts = NULL;
b408954b 38struct obstack solved_conflicts_obstack;
08089d5d 39
b86796bf
AD
40static bitset shiftset;
41static bitset lookaheadset;
b408954b 42
c29240e7 43\f
08089d5d 44
b408954b
AD
45enum conflict_resolution_e
46 {
47 shift_resolution,
48 reduce_resolution,
49 left_resolution,
50 right_resolution,
86eff183 51 nonassoc_resolution
b408954b
AD
52 };
53
54
9801d40c
AD
55/*----------------------------------------------------------------.
56| Explain how an SR conflict between TOKEN and RULE was resolved: |
57| RESOLUTION. |
58`----------------------------------------------------------------*/
59
c29240e7 60static inline void
9801d40c 61log_resolution (rule_t *rule, int token,
b408954b 62 enum conflict_resolution_e resolution)
08089d5d 63{
b408954b
AD
64 if (report_flag & report_solved_conflicts)
65 {
66 /* The description of the resolution. */
67 switch (resolution)
68 {
69 case shift_resolution:
70 case left_resolution:
71 obstack_fgrow2 (&solved_conflicts_obstack,
72 _("\
73 Conflict between rule %d and token %s resolved as shift"),
9801d40c 74 rule->number,
b408954b
AD
75 symbols[token]->tag);
76 break;
77 case reduce_resolution:
78 case right_resolution:
79 obstack_fgrow2 (&solved_conflicts_obstack,
80 _("\
81 Conflict between rule %d and token %s resolved as reduce"),
9801d40c 82 rule->number,
b408954b
AD
83 symbols[token]->tag);
84 break;
85 case nonassoc_resolution:
86 obstack_fgrow2 (&solved_conflicts_obstack,
87 _("\
88 Conflict between rule %d and token %s resolved as an error"),
9801d40c 89 rule->number,
b408954b
AD
90 symbols[token]->tag);
91 break;
92 }
93
94 /* The reason. */
95 switch (resolution)
96 {
97 case shift_resolution:
98 obstack_fgrow2 (&solved_conflicts_obstack,
99 " (%s < %s)",
9801d40c 100 rule->prec->tag,
b408954b
AD
101 symbols[token]->tag);
102 break;
103
104 case reduce_resolution:
105 obstack_fgrow2 (&solved_conflicts_obstack,
106 " (%s < %s)",
107 symbols[token]->tag,
9801d40c 108 rule->prec->tag);
b408954b
AD
109 break;
110
111 case left_resolution:
4a713ec2 112 obstack_fgrow1 (&solved_conflicts_obstack,
b408954b
AD
113 " (%%left %s)",
114 symbols[token]->tag);
115 break;
116
117 case right_resolution:
118 obstack_fgrow1 (&solved_conflicts_obstack,
119 " (%%right %s)",
120 symbols[token]->tag);
121 break;
122 case nonassoc_resolution:
123 obstack_fgrow1 (&solved_conflicts_obstack,
124 " (%%nonassoc %s)",
125 symbols[token]->tag);
126 break;
127 }
128 obstack_sgrow (&solved_conflicts_obstack, ".\n");
129 }
08089d5d
DM
130}
131
132
c29240e7
AD
133/*------------------------------------------------------------------.
134| Turn off the shift recorded for the specified token in the |
135| specified state. Used when we resolve a shift-reduce conflict in |
136| favor of the reduction. |
137`------------------------------------------------------------------*/
138
4a120d45 139static void
065fbd27 140flush_shift (state_t *state, int token)
08089d5d 141{
065fbd27 142 shifts *shiftp = state->shifts;
9f136c07 143 int i;
c29240e7 144
b86796bf 145 bitset_reset (lookaheadset, token);
d954473d
AD
146 for (i = 0; i < shiftp->nshifts; i++)
147 if (!SHIFT_IS_DISABLED (shiftp, i) && SHIFT_SYMBOL (shiftp, i) == token)
148 SHIFT_DISABLE (shiftp, i);
08089d5d
DM
149}
150
151
709ae8c6
AD
152/*-------------------------------------------------------------------.
153| Turn off the reduce recorded for the specified token for the |
154| specified lookahead. Used when we resolve a shift-reduce conflict |
155| in favor of the shift. |
156`-------------------------------------------------------------------*/
157
158static void
9801d40c 159flush_reduce (bitset lookaheads, int token)
709ae8c6 160{
9801d40c 161 bitset_reset (lookaheads, token);
709ae8c6
AD
162}
163
164
c29240e7
AD
165/*------------------------------------------------------------------.
166| Attempt to resolve shift-reduce conflict for one rule by means of |
167| precedence declarations. It has already been checked that the |
168| rule has a precedence. A conflict is resolved by modifying the |
169| shift or reduce tables so that there is no longer a conflict. |
9801d40c
AD
170| |
171| LOOKAHEAD is the number of the lookahead bitset to consider. |
c29240e7 172`------------------------------------------------------------------*/
08089d5d 173
4a120d45 174static void
065fbd27 175resolve_sr_conflict (state_t *state, int lookahead)
08089d5d 176{
c29240e7 177 int i;
9801d40c
AD
178 /* Find the rule to reduce by to get precedence of reduction. */
179 rule_t *redrule = state->lookaheads_rule[lookahead];
180 int redprec = redrule->prec->prec;
181 bitset lookaheads = state->lookaheads[lookahead];
2cec70b9
AD
182 errs *errp = errs_new (ntokens + 1);
183 errp->nerrs = 0;
08089d5d 184
08089d5d 185 for (i = 0; i < ntokens; i++)
9801d40c 186 if (bitset_test (lookaheads, i)
b86796bf 187 && bitset_test (lookaheadset, i)
0e78e603 188 && symbols[i]->prec)
92b16366 189 {
709ae8c6
AD
190 /* Shift-reduce conflict occurs for token number i
191 and it has a precedence.
192 The precedence of shifting is that of token i. */
0e78e603 193 if (symbols[i]->prec < redprec)
92b16366 194 {
9801d40c 195 log_resolution (redrule, i, reduce_resolution);
92b16366
AD
196 flush_shift (state, i);
197 }
0e78e603 198 else if (symbols[i]->prec > redprec)
92b16366 199 {
9801d40c
AD
200 log_resolution (redrule, i, shift_resolution);
201 flush_reduce (lookaheads, i);
92b16366
AD
202 }
203 else
709ae8c6
AD
204 /* Matching precedence levels.
205 For left association, keep only the reduction.
206 For right association, keep only the shift.
207 For nonassociation, keep neither. */
208
5a670b1e 209 switch (symbols[i]->assoc)
709ae8c6
AD
210 {
211 case right_assoc:
9801d40c
AD
212 log_resolution (redrule, i, right_resolution);
213 flush_reduce (lookaheads, i);
709ae8c6
AD
214 break;
215
216 case left_assoc:
9801d40c 217 log_resolution (redrule, i, left_resolution);
709ae8c6
AD
218 flush_shift (state, i);
219 break;
220
221 case non_assoc:
9801d40c 222 log_resolution (redrule, i, nonassoc_resolution);
709ae8c6 223 flush_shift (state, i);
9801d40c 224 flush_reduce (lookaheads, i);
709ae8c6 225 /* Record an explicit error for this token. */
2cec70b9 226 errp->errs[errp->nerrs++] = i;
709ae8c6 227 break;
e9955c83
AD
228
229 case undef_assoc:
230 assert (symbols[i]->assoc != undef_assoc);
231 break;
709ae8c6 232 }
92b16366
AD
233 }
234
92b16366
AD
235 /* Some tokens have been explicitly made errors. Allocate a
236 permanent errs structure for this state, to record them. */
2cec70b9 237 state->errs = errs_dup (errp);
c29240e7 238 free (errp);
b408954b
AD
239
240 if (obstack_object_size (&solved_conflicts_obstack))
241 {
242 obstack_1grow (&solved_conflicts_obstack, '\0');
243 state->solved_conflicts = obstack_finish (&solved_conflicts_obstack);
244 }
08089d5d
DM
245}
246
247
4a120d45 248static void
065fbd27 249set_conflicts (state_t *state)
08089d5d 250{
914feea9 251 int i;
c29240e7 252 shifts *shiftp;
c29240e7 253
065fbd27 254 if (state->consistent)
c29240e7 255 return;
08089d5d 256
b86796bf 257 bitset_zero (lookaheadset);
08089d5d 258
065fbd27 259 shiftp = state->shifts;
d954473d
AD
260 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
261 if (!SHIFT_IS_DISABLED (shiftp, i))
b86796bf 262 bitset_set (lookaheadset, SHIFT_SYMBOL (shiftp, i));
08089d5d 263
c29240e7
AD
264 /* Loop over all rules which require lookahead in this state. First
265 check for shift-reduce conflict, and try to resolve using
9801d40c 266 precedence. */
065fbd27 267 for (i = 0; i < state->nlookaheads; ++i)
c0263492
AD
268 if (state->lookaheads_rule[i]->prec
269 && state->lookaheads_rule[i]->prec->prec
270 && !bitset_disjoint_p (state->lookaheads[i], lookaheadset))
914feea9 271 {
9801d40c 272 resolve_sr_conflict (state, i);
914feea9
AD
273 break;
274 }
08089d5d 275
c29240e7
AD
276 /* Loop over all rules which require lookahead in this state. Check
277 for conflicts not resolved above. */
065fbd27 278 for (i = 0; i < state->nlookaheads; ++i)
08089d5d 279 {
c0263492 280 if (!bitset_disjoint_p (state->lookaheads[i], lookaheadset))
914feea9 281 conflicts[state->number] = 1;
08089d5d 282
c0263492 283 bitset_or (lookaheadset, lookaheadset, state->lookaheads[i]);
c29240e7
AD
284 }
285}
08089d5d
DM
286
287void
b408954b 288conflicts_solve (void)
08089d5d 289{
602bbf31 290 size_t i;
08089d5d 291
d7913476 292 conflicts = XCALLOC (char, nstates);
b86796bf 293 shiftset = bitset_create (ntokens, BITSET_FIXED);
b86796bf 294 lookaheadset = bitset_create (ntokens, BITSET_FIXED);
b408954b 295 obstack_init (&solved_conflicts_obstack);
08089d5d 296
c29240e7 297 for (i = 0; i < nstates; i++)
29e88316 298 set_conflicts (states[i]);
08089d5d
DM
299}
300
301
c29240e7
AD
302/*---------------------------------------------.
303| Count the number of shift/reduce conflicts. |
304`---------------------------------------------*/
305
0df87bb6 306static int
065fbd27 307count_sr_conflicts (state_t *state)
08089d5d 308{
f9abaa2c 309 int i;
0df87bb6 310 int src_count = 0;
065fbd27 311 shifts *shiftp = state->shifts;
08089d5d 312
c29240e7 313 if (!shiftp)
0df87bb6 314 return 0;
08089d5d 315
b86796bf
AD
316 bitset_zero (lookaheadset);
317 bitset_zero (shiftset);
08089d5d 318
52afa962 319 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
9839bbe5 320 if (!SHIFT_IS_DISABLED (shiftp, i))
b86796bf 321 bitset_set (shiftset, SHIFT_SYMBOL (shiftp, i));
08089d5d 322
065fbd27 323 for (i = 0; i < state->nlookaheads; ++i)
c0263492 324 bitset_or (lookaheadset, lookaheadset, state->lookaheads[i]);
08089d5d 325
b86796bf 326 bitset_and (lookaheadset, lookaheadset, shiftset);
08089d5d 327
914feea9 328 src_count = bitset_count (lookaheadset);
0df87bb6
AD
329
330 return src_count;
08089d5d
DM
331}
332
333
c29240e7
AD
334/*----------------------------------------------.
335| Count the number of reduce/reduce conflicts. |
336`----------------------------------------------*/
337
0df87bb6 338static int
065fbd27 339count_rr_conflicts (state_t *state)
08089d5d 340{
c29240e7 341 int i;
0df87bb6 342 int rrc_count = 0;
08089d5d 343
065fbd27 344 if (state->nlookaheads < 2)
0df87bb6 345 return 0;
08089d5d 346
08089d5d
DM
347 for (i = 0; i < ntokens; i++)
348 {
0df87bb6
AD
349 int count = 0;
350 int j;
065fbd27 351 for (j = 0; j < state->nlookaheads; ++j)
c0263492 352 if (bitset_test (state->lookaheads[j], i))
52afa962 353 count++;
08089d5d 354
c29240e7
AD
355 if (count >= 2)
356 rrc_count++;
08089d5d 357 }
0df87bb6
AD
358
359 return rrc_count;
08089d5d
DM
360}
361
ff4423cc
AD
362/*--------------------------------------------------------------.
363| Return a human readable string which reports shift/reduce and |
364| reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
365`--------------------------------------------------------------*/
c29240e7 366
ff4423cc
AD
367static const char *
368conflict_report (int src_num, int rrc_num)
c29240e7 369{
ff4423cc
AD
370 static char res[4096];
371 char *cp = res;
372
7da99ede 373 if (src_num >= 1)
22c821f3 374 {
7da99ede
AD
375 sprintf (cp, ngettext ("%d shift/reduce conflict",
376 "%d shift/reduce conflicts", src_num), src_num);
22c821f3
AD
377 cp += strlen (cp);
378 }
c29240e7 379
0619caf0 380 if (src_num > 0 && rrc_num > 0)
22c821f3 381 {
7da99ede 382 sprintf (cp, " %s ", _("and"));
22c821f3
AD
383 cp += strlen (cp);
384 }
c29240e7 385
7da99ede 386 if (rrc_num >= 1)
22c821f3 387 {
7da99ede
AD
388 sprintf (cp, ngettext ("%d reduce/reduce conflict",
389 "%d reduce/reduce conflicts", rrc_num), rrc_num);
22c821f3
AD
390 cp += strlen (cp);
391 }
ff4423cc
AD
392
393 *cp++ = '.';
394 *cp++ = '\n';
395 *cp++ = '\0';
c29240e7 396
ff4423cc 397 return res;
c29240e7
AD
398}
399
400
0df87bb6
AD
401/*-----------------------------------------------------------.
402| Output the detailed description of states with conflicts. |
403`-----------------------------------------------------------*/
c29240e7
AD
404
405void
0df87bb6 406conflicts_output (FILE *out)
c29240e7 407{
d2d1b42b 408 bool printed_sth = FALSE;
602bbf31 409 size_t i;
0df87bb6
AD
410 for (i = 0; i < nstates; i++)
411 if (conflicts[i])
412 {
7da99ede 413 fprintf (out, _("State %d contains "), i);
29e88316
AD
414 fputs (conflict_report (count_sr_conflicts (states[i]),
415 count_rr_conflicts (states[i])), out);
d2d1b42b 416 printed_sth = TRUE;
0df87bb6 417 }
d2d1b42b
AD
418 if (printed_sth)
419 fputs ("\n\n", out);
0df87bb6 420}
c29240e7 421
c29240e7 422
0df87bb6
AD
423/*------------------------------------------.
424| Reporting the total number of conflicts. |
425`------------------------------------------*/
0619caf0 426
0df87bb6
AD
427void
428conflicts_print (void)
429{
602bbf31 430 size_t i;
0df87bb6 431
a034c8b8
AD
432 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
433 not set, and then we want 0 SR, or else it is specified, in which
434 case we want equality. */
435 int src_ok = 0;
436
0df87bb6
AD
437 int src_total = 0;
438 int rrc_total = 0;
439
440 /* Conflicts by state. */
441 for (i = 0; i < nstates; i++)
442 if (conflicts[i])
443 {
29e88316
AD
444 src_total += count_sr_conflicts (states[i]);
445 rrc_total += count_rr_conflicts (states[i]);
0df87bb6 446 }
c29240e7 447
a034c8b8
AD
448 src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
449
450 /* If there are no RR conflicts, and as many SR conflicts as
451 expected, then there is nothing to report. */
452 if (!rrc_total && src_ok)
453 return;
454
0619caf0 455 /* Report the total number of conflicts on STDERR. */
a034c8b8 456 if (yacc_flag)
09b503c8 457 {
a034c8b8
AD
458 /* If invoked with `--yacc', use the output format specified by
459 POSIX. */
460 fprintf (stderr, _("conflicts: "));
461 if (src_total > 0)
462 fprintf (stderr, _(" %d shift/reduce"), src_total);
463 if (src_total > 0 && rrc_total > 0)
464 fprintf (stderr, ",");
465 if (rrc_total > 0)
466 fprintf (stderr, _(" %d reduce/reduce"), rrc_total);
467 putc ('\n', stderr);
468 }
469 else
470 {
471 fprintf (stderr, _("%s contains "), infile);
472 fputs (conflict_report (src_total, rrc_total), stderr);
09b503c8 473 }
7da99ede 474
a034c8b8 475 if (expected_conflicts != -1 && !src_ok)
7da99ede
AD
476 {
477 complain_message_count++;
81e895c0
AD
478 fprintf (stderr, ngettext ("expected %d shift/reduce conflict\n",
479 "expected %d shift/reduce conflicts\n",
7da99ede
AD
480 expected_conflicts),
481 expected_conflicts);
482 }
c29240e7
AD
483}
484
485
08089d5d 486void
b408954b 487conflicts_free (void)
08089d5d 488{
d7913476 489 XFREE (conflicts);
b86796bf
AD
490 bitset_free (shiftset);
491 bitset_free (lookaheadset);
b408954b 492 obstack_free (&solved_conflicts_obstack, NULL);
08089d5d 493}