]> git.saurik.com Git - bison.git/blame - src/conflicts.c
* src/state.h (state_number_t, STATE_NUMBER_MAX): New.
[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{
d57650a5 290 state_number_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
676385e2
PH
334/*----------------------------------------------------------------.
335| Count the number of reduce/reduce conflicts. If ONE_PER_TOKEN, |
336| count one conflict for each token that has any reduce/reduce |
337| conflicts. Otherwise, count one conflict for each pair of |
338| conflicting reductions. |
339+`----------------------------------------------------------------*/
c29240e7 340
0df87bb6 341static int
676385e2 342count_rr_conflicts (state_t *state, int one_per_token)
08089d5d 343{
c29240e7 344 int i;
0df87bb6 345 int rrc_count = 0;
08089d5d 346
065fbd27 347 if (state->nlookaheads < 2)
0df87bb6 348 return 0;
08089d5d 349
08089d5d
DM
350 for (i = 0; i < ntokens; i++)
351 {
0df87bb6
AD
352 int count = 0;
353 int j;
065fbd27 354 for (j = 0; j < state->nlookaheads; ++j)
c0263492 355 if (bitset_test (state->lookaheads[j], i))
52afa962 356 count++;
08089d5d 357
c29240e7 358 if (count >= 2)
676385e2 359 rrc_count += one_per_token ? 1 : count-1;
08089d5d 360 }
0df87bb6
AD
361
362 return rrc_count;
08089d5d
DM
363}
364
ff4423cc
AD
365/*--------------------------------------------------------------.
366| Return a human readable string which reports shift/reduce and |
367| reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
368`--------------------------------------------------------------*/
c29240e7 369
ff4423cc
AD
370static const char *
371conflict_report (int src_num, int rrc_num)
c29240e7 372{
ff4423cc
AD
373 static char res[4096];
374 char *cp = res;
375
7da99ede 376 if (src_num >= 1)
22c821f3 377 {
7da99ede
AD
378 sprintf (cp, ngettext ("%d shift/reduce conflict",
379 "%d shift/reduce conflicts", src_num), src_num);
22c821f3
AD
380 cp += strlen (cp);
381 }
c29240e7 382
0619caf0 383 if (src_num > 0 && rrc_num > 0)
22c821f3 384 {
7da99ede 385 sprintf (cp, " %s ", _("and"));
22c821f3
AD
386 cp += strlen (cp);
387 }
c29240e7 388
7da99ede 389 if (rrc_num >= 1)
22c821f3 390 {
7da99ede
AD
391 sprintf (cp, ngettext ("%d reduce/reduce conflict",
392 "%d reduce/reduce conflicts", rrc_num), rrc_num);
22c821f3
AD
393 cp += strlen (cp);
394 }
ff4423cc
AD
395
396 *cp++ = '.';
397 *cp++ = '\n';
398 *cp++ = '\0';
c29240e7 399
ff4423cc 400 return res;
c29240e7
AD
401}
402
403
0df87bb6
AD
404/*-----------------------------------------------------------.
405| Output the detailed description of states with conflicts. |
406`-----------------------------------------------------------*/
c29240e7
AD
407
408void
0df87bb6 409conflicts_output (FILE *out)
c29240e7 410{
d2d1b42b 411 bool printed_sth = FALSE;
d57650a5 412 state_number_t i;
0df87bb6
AD
413 for (i = 0; i < nstates; i++)
414 if (conflicts[i])
415 {
7da99ede 416 fprintf (out, _("State %d contains "), i);
29e88316 417 fputs (conflict_report (count_sr_conflicts (states[i]),
676385e2 418 count_rr_conflicts (states[i], TRUE)), out);
d2d1b42b 419 printed_sth = TRUE;
0df87bb6 420 }
d2d1b42b
AD
421 if (printed_sth)
422 fputs ("\n\n", out);
0df87bb6 423}
c29240e7 424
676385e2
PH
425/*--------------------------------------------------------.
426| Total the number of S/R and R/R conflicts. Unlike the |
427| code in conflicts_output, however, count EACH pair of |
428| reductions for the same state and lookahead as one |
429| conflict. |
430`--------------------------------------------------------*/
431
432int
433conflicts_total_count (void)
434{
d57650a5 435 state_number_t i;
676385e2
PH
436 int count;
437
438 /* Conflicts by state. */
439 count = 0;
440 for (i = 0; i < nstates; i++)
441 if (conflicts[i])
442 {
443 count += count_sr_conflicts (states[i]);
444 count += count_rr_conflicts (states[i], FALSE);
445 }
446 return count;
447}
e0e5bf84 448
c29240e7 449
0df87bb6
AD
450/*------------------------------------------.
451| Reporting the total number of conflicts. |
452`------------------------------------------*/
0619caf0 453
0df87bb6
AD
454void
455conflicts_print (void)
456{
a034c8b8
AD
457 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
458 not set, and then we want 0 SR, or else it is specified, in which
459 case we want equality. */
460 int src_ok = 0;
461
0df87bb6
AD
462 int src_total = 0;
463 int rrc_total = 0;
464
465 /* Conflicts by state. */
d57650a5
AD
466 {
467 state_number_t i;
468
469 for (i = 0; i < nstates; i++)
470 if (conflicts[i])
471 {
472 src_total += count_sr_conflicts (states[i]);
473 rrc_total += count_rr_conflicts (states[i], TRUE);
474 }
475 }
c29240e7 476
a034c8b8
AD
477 src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
478
479 /* If there are no RR conflicts, and as many SR conflicts as
480 expected, then there is nothing to report. */
481 if (!rrc_total && src_ok)
482 return;
483
0619caf0 484 /* Report the total number of conflicts on STDERR. */
a034c8b8 485 if (yacc_flag)
09b503c8 486 {
a034c8b8
AD
487 /* If invoked with `--yacc', use the output format specified by
488 POSIX. */
489 fprintf (stderr, _("conflicts: "));
490 if (src_total > 0)
491 fprintf (stderr, _(" %d shift/reduce"), src_total);
492 if (src_total > 0 && rrc_total > 0)
493 fprintf (stderr, ",");
494 if (rrc_total > 0)
495 fprintf (stderr, _(" %d reduce/reduce"), rrc_total);
496 putc ('\n', stderr);
497 }
498 else
499 {
500 fprintf (stderr, _("%s contains "), infile);
501 fputs (conflict_report (src_total, rrc_total), stderr);
09b503c8 502 }
7da99ede 503
a034c8b8 504 if (expected_conflicts != -1 && !src_ok)
7da99ede
AD
505 {
506 complain_message_count++;
81e895c0
AD
507 fprintf (stderr, ngettext ("expected %d shift/reduce conflict\n",
508 "expected %d shift/reduce conflicts\n",
7da99ede
AD
509 expected_conflicts),
510 expected_conflicts);
511 }
c29240e7
AD
512}
513
514
08089d5d 515void
b408954b 516conflicts_free (void)
08089d5d 517{
d7913476 518 XFREE (conflicts);
b86796bf
AD
519 bitset_free (shiftset);
520 bitset_free (lookaheadset);
b408954b 521 obstack_free (&solved_conflicts_obstack, NULL);
08089d5d 522}