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