]> git.saurik.com Git - bison.git/blame - src/conflicts.c
* src/LR0.c, src/derives.c, src/gram.c, src/gram.h, src/lalr.c,
[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;
08089d5d 38
b86796bf
AD
39static bitset shiftset;
40static bitset lookaheadset;
c29240e7 41\f
08089d5d 42
c29240e7 43static inline void
e53c6322 44log_resolution (state_t *state, int LAno, int token, const char *resolution)
08089d5d 45{
ec3bc396 46 if (report_flag & report_states)
64d15509
AD
47 obstack_fgrow4 (&output_obstack,
48 _("\
c29240e7 49Conflict in state %d between rule %d and token %s resolved as %s.\n"),
b0299a2e
AD
50 state->number,
51 LArule[LAno]->number,
52 symbols[token]->tag,
ad949da9 53 resolution);
08089d5d
DM
54}
55
56
c29240e7
AD
57/*------------------------------------------------------------------.
58| Turn off the shift recorded for the specified token in the |
59| specified state. Used when we resolve a shift-reduce conflict in |
60| favor of the reduction. |
61`------------------------------------------------------------------*/
62
4a120d45 63static void
065fbd27 64flush_shift (state_t *state, int token)
08089d5d 65{
065fbd27 66 shifts *shiftp = state->shifts;
9f136c07 67 int i;
c29240e7 68
b86796bf 69 bitset_reset (lookaheadset, token);
d954473d
AD
70 for (i = 0; i < shiftp->nshifts; i++)
71 if (!SHIFT_IS_DISABLED (shiftp, i) && SHIFT_SYMBOL (shiftp, i) == token)
72 SHIFT_DISABLE (shiftp, i);
08089d5d
DM
73}
74
75
709ae8c6
AD
76/*-------------------------------------------------------------------.
77| Turn off the reduce recorded for the specified token for the |
78| specified lookahead. Used when we resolve a shift-reduce conflict |
79| in favor of the shift. |
80`-------------------------------------------------------------------*/
81
82static void
83flush_reduce (int lookahead, int token)
84{
602bbf31 85 bitset_reset (LA[lookahead], token);
709ae8c6
AD
86}
87
88
c29240e7
AD
89/*------------------------------------------------------------------.
90| Attempt to resolve shift-reduce conflict for one rule by means of |
91| precedence declarations. It has already been checked that the |
92| rule has a precedence. A conflict is resolved by modifying the |
93| shift or reduce tables so that there is no longer a conflict. |
94`------------------------------------------------------------------*/
08089d5d 95
4a120d45 96static void
065fbd27 97resolve_sr_conflict (state_t *state, int lookahead)
08089d5d 98{
c29240e7 99 int i;
9f136c07 100 /* find the rule to reduce by to get precedence of reduction */
03b31c0c 101 int redprec = LArule[lookahead]->prec->prec;
2cec70b9
AD
102 errs *errp = errs_new (ntokens + 1);
103 errp->nerrs = 0;
08089d5d 104
08089d5d 105 for (i = 0; i < ntokens; i++)
602bbf31 106 if (bitset_test (LA[lookahead], i)
b86796bf 107 && bitset_test (lookaheadset, i)
0e78e603 108 && symbols[i]->prec)
92b16366 109 {
709ae8c6
AD
110 /* Shift-reduce conflict occurs for token number i
111 and it has a precedence.
112 The precedence of shifting is that of token i. */
0e78e603 113 if (symbols[i]->prec < redprec)
92b16366 114 {
709ae8c6 115 log_resolution (state, lookahead, i, _("reduce"));
92b16366
AD
116 flush_shift (state, i);
117 }
0e78e603 118 else if (symbols[i]->prec > redprec)
92b16366 119 {
709ae8c6
AD
120 log_resolution (state, lookahead, i, _("shift"));
121 flush_reduce (lookahead, i);
92b16366
AD
122 }
123 else
709ae8c6
AD
124 /* Matching precedence levels.
125 For left association, keep only the reduction.
126 For right association, keep only the shift.
127 For nonassociation, keep neither. */
128
5a670b1e 129 switch (symbols[i]->assoc)
709ae8c6
AD
130 {
131 case right_assoc:
132 log_resolution (state, lookahead, i, _("shift"));
133 flush_reduce (lookahead, i);
134 break;
135
136 case left_assoc:
137 log_resolution (state, lookahead, i, _("reduce"));
138 flush_shift (state, i);
139 break;
140
141 case non_assoc:
142 log_resolution (state, lookahead, i, _("an error"));
143 flush_shift (state, i);
144 flush_reduce (lookahead, i);
145 /* Record an explicit error for this token. */
2cec70b9 146 errp->errs[errp->nerrs++] = i;
709ae8c6
AD
147 break;
148 }
92b16366
AD
149 }
150
92b16366
AD
151 /* Some tokens have been explicitly made errors. Allocate a
152 permanent errs structure for this state, to record them. */
2cec70b9 153 state->errs = errs_dup (errp);
c29240e7 154 free (errp);
08089d5d
DM
155}
156
157
4a120d45 158static void
065fbd27 159set_conflicts (state_t *state)
08089d5d 160{
914feea9 161 int i;
c29240e7 162 shifts *shiftp;
c29240e7 163
065fbd27 164 if (state->consistent)
c29240e7 165 return;
08089d5d 166
b86796bf 167 bitset_zero (lookaheadset);
08089d5d 168
065fbd27 169 shiftp = state->shifts;
d954473d
AD
170 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
171 if (!SHIFT_IS_DISABLED (shiftp, i))
b86796bf 172 bitset_set (lookaheadset, SHIFT_SYMBOL (shiftp, i));
08089d5d 173
c29240e7
AD
174 /* Loop over all rules which require lookahead in this state. First
175 check for shift-reduce conflict, and try to resolve using
176 precedence */
065fbd27 177 for (i = 0; i < state->nlookaheads; ++i)
b0299a2e 178 if (LArule[state->lookaheadsp + i]->prec
03b31c0c 179 && LArule[state->lookaheadsp + i]->prec->prec
914feea9
AD
180 && !bitset_disjoint_p (LA[state->lookaheadsp + i], lookaheadset))
181 {
182 resolve_sr_conflict (state, state->lookaheadsp + i);
183 break;
184 }
08089d5d 185
c29240e7
AD
186 /* Loop over all rules which require lookahead in this state. Check
187 for conflicts not resolved above. */
065fbd27 188 for (i = 0; i < state->nlookaheads; ++i)
08089d5d 189 {
914feea9
AD
190 if (!bitset_disjoint_p (LA[state->lookaheadsp + i], lookaheadset))
191 conflicts[state->number] = 1;
08089d5d 192
f9abaa2c 193 bitset_or (lookaheadset, lookaheadset, LA[state->lookaheadsp + i]);
c29240e7
AD
194 }
195}
08089d5d
DM
196
197void
342b8b6e 198solve_conflicts (void)
08089d5d 199{
602bbf31 200 size_t i;
08089d5d 201
d7913476 202 conflicts = XCALLOC (char, nstates);
b86796bf 203 shiftset = bitset_create (ntokens, BITSET_FIXED);
b86796bf 204 lookaheadset = bitset_create (ntokens, BITSET_FIXED);
08089d5d 205
c29240e7 206 for (i = 0; i < nstates; i++)
29e88316 207 set_conflicts (states[i]);
08089d5d
DM
208}
209
210
c29240e7
AD
211/*---------------------------------------------.
212| Count the number of shift/reduce conflicts. |
213`---------------------------------------------*/
214
0df87bb6 215static int
065fbd27 216count_sr_conflicts (state_t *state)
08089d5d 217{
f9abaa2c 218 int i;
0df87bb6 219 int src_count = 0;
065fbd27 220 shifts *shiftp = state->shifts;
08089d5d 221
c29240e7 222 if (!shiftp)
0df87bb6 223 return 0;
08089d5d 224
b86796bf
AD
225 bitset_zero (lookaheadset);
226 bitset_zero (shiftset);
08089d5d 227
52afa962 228 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
9839bbe5 229 if (!SHIFT_IS_DISABLED (shiftp, i))
b86796bf 230 bitset_set (shiftset, SHIFT_SYMBOL (shiftp, i));
08089d5d 231
065fbd27 232 for (i = 0; i < state->nlookaheads; ++i)
f9abaa2c 233 bitset_or (lookaheadset, lookaheadset, LA[state->lookaheadsp + i]);
08089d5d 234
b86796bf 235 bitset_and (lookaheadset, lookaheadset, shiftset);
08089d5d 236
914feea9 237 src_count = bitset_count (lookaheadset);
0df87bb6
AD
238
239 return src_count;
08089d5d
DM
240}
241
242
c29240e7
AD
243/*----------------------------------------------.
244| Count the number of reduce/reduce conflicts. |
245`----------------------------------------------*/
246
0df87bb6 247static int
065fbd27 248count_rr_conflicts (state_t *state)
08089d5d 249{
c29240e7 250 int i;
0df87bb6 251 int rrc_count = 0;
08089d5d 252
065fbd27 253 if (state->nlookaheads < 2)
0df87bb6 254 return 0;
08089d5d 255
08089d5d
DM
256 for (i = 0; i < ntokens; i++)
257 {
0df87bb6
AD
258 int count = 0;
259 int j;
065fbd27 260 for (j = 0; j < state->nlookaheads; ++j)
602bbf31 261 if (bitset_test (LA[state->lookaheadsp + j], i))
52afa962 262 count++;
08089d5d 263
c29240e7
AD
264 if (count >= 2)
265 rrc_count++;
08089d5d 266 }
0df87bb6
AD
267
268 return rrc_count;
08089d5d
DM
269}
270
ff4423cc
AD
271/*--------------------------------------------------------------.
272| Return a human readable string which reports shift/reduce and |
273| reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
274`--------------------------------------------------------------*/
c29240e7 275
ff4423cc
AD
276static const char *
277conflict_report (int src_num, int rrc_num)
c29240e7 278{
ff4423cc
AD
279 static char res[4096];
280 char *cp = res;
281
7da99ede 282 if (src_num >= 1)
22c821f3 283 {
7da99ede
AD
284 sprintf (cp, ngettext ("%d shift/reduce conflict",
285 "%d shift/reduce conflicts", src_num), src_num);
22c821f3
AD
286 cp += strlen (cp);
287 }
c29240e7 288
0619caf0 289 if (src_num > 0 && rrc_num > 0)
22c821f3 290 {
7da99ede 291 sprintf (cp, " %s ", _("and"));
22c821f3
AD
292 cp += strlen (cp);
293 }
c29240e7 294
7da99ede 295 if (rrc_num >= 1)
22c821f3 296 {
7da99ede
AD
297 sprintf (cp, ngettext ("%d reduce/reduce conflict",
298 "%d reduce/reduce conflicts", rrc_num), rrc_num);
22c821f3
AD
299 cp += strlen (cp);
300 }
ff4423cc
AD
301
302 *cp++ = '.';
303 *cp++ = '\n';
304 *cp++ = '\0';
c29240e7 305
ff4423cc 306 return res;
c29240e7
AD
307}
308
309
0df87bb6
AD
310/*-----------------------------------------------------------.
311| Output the detailed description of states with conflicts. |
312`-----------------------------------------------------------*/
c29240e7
AD
313
314void
0df87bb6 315conflicts_output (FILE *out)
c29240e7 316{
d2d1b42b 317 bool printed_sth = FALSE;
602bbf31 318 size_t i;
0df87bb6
AD
319 for (i = 0; i < nstates; i++)
320 if (conflicts[i])
321 {
7da99ede 322 fprintf (out, _("State %d contains "), i);
29e88316
AD
323 fputs (conflict_report (count_sr_conflicts (states[i]),
324 count_rr_conflicts (states[i])), out);
d2d1b42b 325 printed_sth = TRUE;
0df87bb6 326 }
d2d1b42b
AD
327 if (printed_sth)
328 fputs ("\n\n", out);
0df87bb6 329}
c29240e7 330
c29240e7 331
0df87bb6
AD
332/*------------------------------------------.
333| Reporting the total number of conflicts. |
334`------------------------------------------*/
0619caf0 335
0df87bb6
AD
336void
337conflicts_print (void)
338{
602bbf31 339 size_t i;
0df87bb6 340
a034c8b8
AD
341 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
342 not set, and then we want 0 SR, or else it is specified, in which
343 case we want equality. */
344 int src_ok = 0;
345
0df87bb6
AD
346 int src_total = 0;
347 int rrc_total = 0;
348
349 /* Conflicts by state. */
350 for (i = 0; i < nstates; i++)
351 if (conflicts[i])
352 {
29e88316
AD
353 src_total += count_sr_conflicts (states[i]);
354 rrc_total += count_rr_conflicts (states[i]);
0df87bb6 355 }
c29240e7 356
a034c8b8
AD
357 src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
358
359 /* If there are no RR conflicts, and as many SR conflicts as
360 expected, then there is nothing to report. */
361 if (!rrc_total && src_ok)
362 return;
363
0619caf0 364 /* Report the total number of conflicts on STDERR. */
a034c8b8 365 if (yacc_flag)
09b503c8 366 {
a034c8b8
AD
367 /* If invoked with `--yacc', use the output format specified by
368 POSIX. */
369 fprintf (stderr, _("conflicts: "));
370 if (src_total > 0)
371 fprintf (stderr, _(" %d shift/reduce"), src_total);
372 if (src_total > 0 && rrc_total > 0)
373 fprintf (stderr, ",");
374 if (rrc_total > 0)
375 fprintf (stderr, _(" %d reduce/reduce"), rrc_total);
376 putc ('\n', stderr);
377 }
378 else
379 {
380 fprintf (stderr, _("%s contains "), infile);
381 fputs (conflict_report (src_total, rrc_total), stderr);
09b503c8 382 }
7da99ede 383
a034c8b8 384 if (expected_conflicts != -1 && !src_ok)
7da99ede
AD
385 {
386 complain_message_count++;
81e895c0
AD
387 fprintf (stderr, ngettext ("expected %d shift/reduce conflict\n",
388 "expected %d shift/reduce conflicts\n",
7da99ede
AD
389 expected_conflicts),
390 expected_conflicts);
391 }
c29240e7
AD
392}
393
394
08089d5d 395void
342b8b6e 396free_conflicts (void)
08089d5d 397{
d7913476 398 XFREE (conflicts);
b86796bf
AD
399 bitset_free (shiftset);
400 bitset_free (lookaheadset);
08089d5d 401}