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