]> git.saurik.com Git - bison.git/blame - src/conflicts.c
* src/state.h (reductions_t): Rename member `nreds' as num.
[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
d2576365 61log_resolution (rule_t *rule, symbol_number_t 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{
ccaf65bc 142 transitions_t *transitions = state->shifts;
9f136c07 143 int i;
c29240e7 144
b86796bf 145 bitset_reset (lookaheadset, token);
ccaf65bc 146 for (i = 0; i < transitions->num; i++)
d2576365
AD
147 if (!TRANSITION_IS_DISABLED (transitions, i)
148 && TRANSITION_SYMBOL (transitions, i) == token)
ccaf65bc 149 TRANSITION_DISABLE (transitions, i);
08089d5d
DM
150}
151
152
709ae8c6
AD
153/*-------------------------------------------------------------------.
154| Turn off the reduce recorded for the specified token for the |
155| specified lookahead. Used when we resolve a shift-reduce conflict |
156| in favor of the shift. |
157`-------------------------------------------------------------------*/
158
159static void
9801d40c 160flush_reduce (bitset lookaheads, int token)
709ae8c6 161{
9801d40c 162 bitset_reset (lookaheads, token);
709ae8c6
AD
163}
164
165
c29240e7
AD
166/*------------------------------------------------------------------.
167| Attempt to resolve shift-reduce conflict for one rule by means of |
168| precedence declarations. It has already been checked that the |
169| rule has a precedence. A conflict is resolved by modifying the |
170| shift or reduce tables so that there is no longer a conflict. |
9801d40c
AD
171| |
172| LOOKAHEAD is the number of the lookahead bitset to consider. |
c29240e7 173`------------------------------------------------------------------*/
08089d5d 174
4a120d45 175static void
065fbd27 176resolve_sr_conflict (state_t *state, int lookahead)
08089d5d 177{
d2576365 178 symbol_number_t i;
9801d40c
AD
179 /* Find the rule to reduce by to get precedence of reduction. */
180 rule_t *redrule = state->lookaheads_rule[lookahead];
181 int redprec = redrule->prec->prec;
182 bitset lookaheads = state->lookaheads[lookahead];
8a731ca8 183 errs_t *errp = errs_new (ntokens + 1);
d2576365 184 errp->num = 0;
08089d5d 185
08089d5d 186 for (i = 0; i < ntokens; i++)
9801d40c 187 if (bitset_test (lookaheads, i)
b86796bf 188 && bitset_test (lookaheadset, i)
0e78e603 189 && symbols[i]->prec)
92b16366 190 {
709ae8c6
AD
191 /* Shift-reduce conflict occurs for token number i
192 and it has a precedence.
193 The precedence of shifting is that of token i. */
0e78e603 194 if (symbols[i]->prec < redprec)
92b16366 195 {
9801d40c 196 log_resolution (redrule, i, reduce_resolution);
92b16366
AD
197 flush_shift (state, i);
198 }
0e78e603 199 else if (symbols[i]->prec > redprec)
92b16366 200 {
9801d40c
AD
201 log_resolution (redrule, i, shift_resolution);
202 flush_reduce (lookaheads, i);
92b16366
AD
203 }
204 else
709ae8c6
AD
205 /* Matching precedence levels.
206 For left association, keep only the reduction.
207 For right association, keep only the shift.
208 For nonassociation, keep neither. */
209
5a670b1e 210 switch (symbols[i]->assoc)
709ae8c6
AD
211 {
212 case right_assoc:
9801d40c
AD
213 log_resolution (redrule, i, right_resolution);
214 flush_reduce (lookaheads, i);
709ae8c6
AD
215 break;
216
217 case left_assoc:
9801d40c 218 log_resolution (redrule, i, left_resolution);
709ae8c6
AD
219 flush_shift (state, i);
220 break;
221
222 case non_assoc:
9801d40c 223 log_resolution (redrule, i, nonassoc_resolution);
709ae8c6 224 flush_shift (state, i);
9801d40c 225 flush_reduce (lookaheads, i);
709ae8c6 226 /* Record an explicit error for this token. */
d2576365 227 errp->symbols[errp->num++] = i;
709ae8c6 228 break;
e9955c83
AD
229
230 case undef_assoc:
231 assert (symbols[i]->assoc != undef_assoc);
232 break;
709ae8c6 233 }
92b16366
AD
234 }
235
92b16366
AD
236 /* Some tokens have been explicitly made errors. Allocate a
237 permanent errs structure for this state, to record them. */
2cec70b9 238 state->errs = errs_dup (errp);
c29240e7 239 free (errp);
b408954b
AD
240
241 if (obstack_object_size (&solved_conflicts_obstack))
242 {
243 obstack_1grow (&solved_conflicts_obstack, '\0');
244 state->solved_conflicts = obstack_finish (&solved_conflicts_obstack);
245 }
08089d5d
DM
246}
247
248
4a120d45 249static void
065fbd27 250set_conflicts (state_t *state)
08089d5d 251{
914feea9 252 int i;
ccaf65bc 253 transitions_t *transitions;
c29240e7 254
065fbd27 255 if (state->consistent)
c29240e7 256 return;
08089d5d 257
b86796bf 258 bitset_zero (lookaheadset);
08089d5d 259
ccaf65bc
AD
260 transitions = state->shifts;
261 for (i = 0; i < transitions->num && TRANSITION_IS_SHIFT (transitions, i); i++)
262 if (!TRANSITION_IS_DISABLED (transitions, i))
263 bitset_set (lookaheadset, TRANSITION_SYMBOL (transitions, i));
08089d5d 264
c29240e7
AD
265 /* Loop over all rules which require lookahead in this state. First
266 check for shift-reduce conflict, and try to resolve using
9801d40c 267 precedence. */
065fbd27 268 for (i = 0; i < state->nlookaheads; ++i)
c0263492
AD
269 if (state->lookaheads_rule[i]->prec
270 && state->lookaheads_rule[i]->prec->prec
271 && !bitset_disjoint_p (state->lookaheads[i], lookaheadset))
914feea9 272 {
9801d40c 273 resolve_sr_conflict (state, i);
914feea9
AD
274 break;
275 }
08089d5d 276
c29240e7
AD
277 /* Loop over all rules which require lookahead in this state. Check
278 for conflicts not resolved above. */
065fbd27 279 for (i = 0; i < state->nlookaheads; ++i)
08089d5d 280 {
c0263492 281 if (!bitset_disjoint_p (state->lookaheads[i], lookaheadset))
914feea9 282 conflicts[state->number] = 1;
08089d5d 283
c0263492 284 bitset_or (lookaheadset, lookaheadset, state->lookaheads[i]);
c29240e7
AD
285 }
286}
08089d5d
DM
287
288void
b408954b 289conflicts_solve (void)
08089d5d 290{
d57650a5 291 state_number_t i;
08089d5d 292
d7913476 293 conflicts = XCALLOC (char, nstates);
b86796bf 294 shiftset = bitset_create (ntokens, BITSET_FIXED);
b86796bf 295 lookaheadset = bitset_create (ntokens, BITSET_FIXED);
b408954b 296 obstack_init (&solved_conflicts_obstack);
08089d5d 297
c29240e7 298 for (i = 0; i < nstates; i++)
29e88316 299 set_conflicts (states[i]);
08089d5d
DM
300}
301
302
c29240e7
AD
303/*---------------------------------------------.
304| Count the number of shift/reduce conflicts. |
305`---------------------------------------------*/
306
0df87bb6 307static int
065fbd27 308count_sr_conflicts (state_t *state)
08089d5d 309{
f9abaa2c 310 int i;
0df87bb6 311 int src_count = 0;
ccaf65bc 312 transitions_t *transitions = state->shifts;
08089d5d 313
ccaf65bc 314 if (!transitions)
0df87bb6 315 return 0;
08089d5d 316
b86796bf
AD
317 bitset_zero (lookaheadset);
318 bitset_zero (shiftset);
08089d5d 319
ccaf65bc
AD
320 for (i = 0; i < transitions->num && TRANSITION_IS_SHIFT (transitions, i); i++)
321 if (!TRANSITION_IS_DISABLED (transitions, i))
322 bitset_set (shiftset, TRANSITION_SYMBOL (transitions, i));
08089d5d 323
065fbd27 324 for (i = 0; i < state->nlookaheads; ++i)
c0263492 325 bitset_or (lookaheadset, lookaheadset, state->lookaheads[i]);
08089d5d 326
b86796bf 327 bitset_and (lookaheadset, lookaheadset, shiftset);
08089d5d 328
914feea9 329 src_count = bitset_count (lookaheadset);
0df87bb6
AD
330
331 return src_count;
08089d5d
DM
332}
333
334
676385e2
PH
335/*----------------------------------------------------------------.
336| Count the number of reduce/reduce conflicts. If ONE_PER_TOKEN, |
337| count one conflict for each token that has any reduce/reduce |
338| conflicts. Otherwise, count one conflict for each pair of |
339| conflicting reductions. |
340+`----------------------------------------------------------------*/
c29240e7 341
0df87bb6 342static int
676385e2 343count_rr_conflicts (state_t *state, int one_per_token)
08089d5d 344{
c29240e7 345 int i;
0df87bb6 346 int rrc_count = 0;
08089d5d 347
065fbd27 348 if (state->nlookaheads < 2)
0df87bb6 349 return 0;
08089d5d 350
08089d5d
DM
351 for (i = 0; i < ntokens; i++)
352 {
0df87bb6
AD
353 int count = 0;
354 int j;
065fbd27 355 for (j = 0; j < state->nlookaheads; ++j)
c0263492 356 if (bitset_test (state->lookaheads[j], i))
52afa962 357 count++;
08089d5d 358
c29240e7 359 if (count >= 2)
676385e2 360 rrc_count += one_per_token ? 1 : count-1;
08089d5d 361 }
0df87bb6
AD
362
363 return rrc_count;
08089d5d
DM
364}
365
ff4423cc
AD
366/*--------------------------------------------------------------.
367| Return a human readable string which reports shift/reduce and |
368| reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
369`--------------------------------------------------------------*/
c29240e7 370
ff4423cc
AD
371static const char *
372conflict_report (int src_num, int rrc_num)
c29240e7 373{
ff4423cc
AD
374 static char res[4096];
375 char *cp = res;
376
7da99ede 377 if (src_num >= 1)
22c821f3 378 {
7da99ede
AD
379 sprintf (cp, ngettext ("%d shift/reduce conflict",
380 "%d shift/reduce conflicts", src_num), src_num);
22c821f3
AD
381 cp += strlen (cp);
382 }
c29240e7 383
0619caf0 384 if (src_num > 0 && rrc_num > 0)
22c821f3 385 {
7da99ede 386 sprintf (cp, " %s ", _("and"));
22c821f3
AD
387 cp += strlen (cp);
388 }
c29240e7 389
7da99ede 390 if (rrc_num >= 1)
22c821f3 391 {
7da99ede
AD
392 sprintf (cp, ngettext ("%d reduce/reduce conflict",
393 "%d reduce/reduce conflicts", rrc_num), rrc_num);
22c821f3
AD
394 cp += strlen (cp);
395 }
ff4423cc
AD
396
397 *cp++ = '.';
398 *cp++ = '\n';
399 *cp++ = '\0';
c29240e7 400
ff4423cc 401 return res;
c29240e7
AD
402}
403
404
0df87bb6
AD
405/*-----------------------------------------------------------.
406| Output the detailed description of states with conflicts. |
407`-----------------------------------------------------------*/
c29240e7
AD
408
409void
0df87bb6 410conflicts_output (FILE *out)
c29240e7 411{
d2d1b42b 412 bool printed_sth = FALSE;
d57650a5 413 state_number_t i;
0df87bb6
AD
414 for (i = 0; i < nstates; i++)
415 if (conflicts[i])
416 {
7da99ede 417 fprintf (out, _("State %d contains "), i);
29e88316 418 fputs (conflict_report (count_sr_conflicts (states[i]),
676385e2 419 count_rr_conflicts (states[i], TRUE)), out);
d2d1b42b 420 printed_sth = TRUE;
0df87bb6 421 }
d2d1b42b
AD
422 if (printed_sth)
423 fputs ("\n\n", out);
0df87bb6 424}
c29240e7 425
676385e2
PH
426/*--------------------------------------------------------.
427| Total the number of S/R and R/R conflicts. Unlike the |
428| code in conflicts_output, however, count EACH pair of |
429| reductions for the same state and lookahead as one |
430| conflict. |
431`--------------------------------------------------------*/
432
433int
434conflicts_total_count (void)
435{
d57650a5 436 state_number_t i;
676385e2
PH
437 int count;
438
439 /* Conflicts by state. */
440 count = 0;
441 for (i = 0; i < nstates; i++)
442 if (conflicts[i])
443 {
444 count += count_sr_conflicts (states[i]);
445 count += count_rr_conflicts (states[i], FALSE);
446 }
447 return count;
448}
e0e5bf84 449
c29240e7 450
0df87bb6
AD
451/*------------------------------------------.
452| Reporting the total number of conflicts. |
453`------------------------------------------*/
0619caf0 454
0df87bb6
AD
455void
456conflicts_print (void)
457{
a034c8b8
AD
458 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
459 not set, and then we want 0 SR, or else it is specified, in which
460 case we want equality. */
461 int src_ok = 0;
462
0df87bb6
AD
463 int src_total = 0;
464 int rrc_total = 0;
465
466 /* Conflicts by state. */
d57650a5
AD
467 {
468 state_number_t i;
469
470 for (i = 0; i < nstates; i++)
471 if (conflicts[i])
472 {
473 src_total += count_sr_conflicts (states[i]);
474 rrc_total += count_rr_conflicts (states[i], TRUE);
475 }
476 }
c29240e7 477
a034c8b8
AD
478 src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
479
480 /* If there are no RR conflicts, and as many SR conflicts as
481 expected, then there is nothing to report. */
482 if (!rrc_total && src_ok)
483 return;
484
0619caf0 485 /* Report the total number of conflicts on STDERR. */
a034c8b8 486 if (yacc_flag)
09b503c8 487 {
a034c8b8
AD
488 /* If invoked with `--yacc', use the output format specified by
489 POSIX. */
490 fprintf (stderr, _("conflicts: "));
491 if (src_total > 0)
492 fprintf (stderr, _(" %d shift/reduce"), src_total);
493 if (src_total > 0 && rrc_total > 0)
494 fprintf (stderr, ",");
495 if (rrc_total > 0)
496 fprintf (stderr, _(" %d reduce/reduce"), rrc_total);
497 putc ('\n', stderr);
498 }
499 else
500 {
501 fprintf (stderr, _("%s contains "), infile);
502 fputs (conflict_report (src_total, rrc_total), stderr);
09b503c8 503 }
7da99ede 504
a034c8b8 505 if (expected_conflicts != -1 && !src_ok)
7da99ede
AD
506 {
507 complain_message_count++;
81e895c0
AD
508 fprintf (stderr, ngettext ("expected %d shift/reduce conflict\n",
509 "expected %d shift/reduce conflicts\n",
7da99ede
AD
510 expected_conflicts),
511 expected_conflicts);
512 }
c29240e7
AD
513}
514
515
08089d5d 516void
b408954b 517conflicts_free (void)
08089d5d 518{
d7913476 519 XFREE (conflicts);
b86796bf
AD
520 bitset_free (shiftset);
521 bitset_free (lookaheadset);
b408954b 522 obstack_free (&solved_conflicts_obstack, NULL);
08089d5d 523}