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