]> git.saurik.com Git - bison.git/blame - src/conflicts.c
* src/state.h, src/state.c (transitions_t): Holds state_t*'s, not
[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
8b752b00 178resolve_sr_conflict (state_t *state, int lookahead,
640748ee 179 symbol_t **errs)
08089d5d 180{
d2576365 181 symbol_number_t i;
9801d40c
AD
182 /* Find the rule to reduce by to get precedence of reduction. */
183 rule_t *redrule = state->lookaheads_rule[lookahead];
184 int redprec = redrule->prec->prec;
185 bitset lookaheads = state->lookaheads[lookahead];
8b752b00 186 int nerrs = 0;
08089d5d 187
08089d5d 188 for (i = 0; i < ntokens; i++)
9801d40c 189 if (bitset_test (lookaheads, i)
b86796bf 190 && bitset_test (lookaheadset, i)
0e78e603 191 && symbols[i]->prec)
92b16366 192 {
709ae8c6
AD
193 /* Shift-reduce conflict occurs for token number i
194 and it has a precedence.
195 The precedence of shifting is that of token i. */
0e78e603 196 if (symbols[i]->prec < redprec)
92b16366 197 {
9801d40c 198 log_resolution (redrule, i, reduce_resolution);
92b16366
AD
199 flush_shift (state, i);
200 }
0e78e603 201 else if (symbols[i]->prec > redprec)
92b16366 202 {
9801d40c
AD
203 log_resolution (redrule, i, shift_resolution);
204 flush_reduce (lookaheads, i);
92b16366
AD
205 }
206 else
709ae8c6
AD
207 /* Matching precedence levels.
208 For left association, keep only the reduction.
209 For right association, keep only the shift.
210 For nonassociation, keep neither. */
211
5a670b1e 212 switch (symbols[i]->assoc)
709ae8c6
AD
213 {
214 case right_assoc:
9801d40c
AD
215 log_resolution (redrule, i, right_resolution);
216 flush_reduce (lookaheads, i);
709ae8c6
AD
217 break;
218
219 case left_assoc:
9801d40c 220 log_resolution (redrule, i, left_resolution);
709ae8c6
AD
221 flush_shift (state, i);
222 break;
223
224 case non_assoc:
9801d40c 225 log_resolution (redrule, i, nonassoc_resolution);
709ae8c6 226 flush_shift (state, i);
9801d40c 227 flush_reduce (lookaheads, i);
709ae8c6 228 /* Record an explicit error for this token. */
640748ee 229 errs[nerrs++] = symbols[i];
709ae8c6 230 break;
e9955c83
AD
231
232 case undef_assoc:
233 assert (symbols[i]->assoc != undef_assoc);
234 break;
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 |
254| lookaheads on which this STATE raises a parse error (%nonassoc). |
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;
c29240e7 262
065fbd27 263 if (state->consistent)
c29240e7 264 return;
08089d5d 265
b86796bf 266 bitset_zero (lookaheadset);
08089d5d 267
640748ee
AD
268 FOR_EACH_SHIFT (transitions, i)
269 bitset_set (lookaheadset, TRANSITION_SYMBOL (transitions, i));
08089d5d 270
c29240e7
AD
271 /* Loop over all rules which require lookahead in this state. First
272 check for shift-reduce conflict, and try to resolve using
9801d40c 273 precedence. */
065fbd27 274 for (i = 0; i < state->nlookaheads; ++i)
c0263492
AD
275 if (state->lookaheads_rule[i]->prec
276 && state->lookaheads_rule[i]->prec->prec
277 && !bitset_disjoint_p (state->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. */
065fbd27 285 for (i = 0; i < state->nlookaheads; ++i)
08089d5d 286 {
c0263492 287 if (!bitset_disjoint_p (state->lookaheads[i], lookaheadset))
914feea9 288 conflicts[state->number] = 1;
08089d5d 289
c0263492 290 bitset_or (lookaheadset, lookaheadset, state->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;
8b752b00 304 /* List of lookaheads on which we explicitly raise a parse 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;
08089d5d 336
ccaf65bc 337 if (!transitions)
0df87bb6 338 return 0;
08089d5d 339
b86796bf
AD
340 bitset_zero (lookaheadset);
341 bitset_zero (shiftset);
08089d5d 342
640748ee
AD
343 FOR_EACH_SHIFT (transitions, i)
344 bitset_set (shiftset, TRANSITION_SYMBOL (transitions, i));
08089d5d 345
065fbd27 346 for (i = 0; i < state->nlookaheads; ++i)
c0263492 347 bitset_or (lookaheadset, lookaheadset, state->lookaheads[i]);
08089d5d 348
b86796bf 349 bitset_and (lookaheadset, lookaheadset, shiftset);
08089d5d 350
914feea9 351 src_count = bitset_count (lookaheadset);
0df87bb6
AD
352
353 return src_count;
08089d5d
DM
354}
355
356
676385e2
PH
357/*----------------------------------------------------------------.
358| Count the number of reduce/reduce conflicts. If ONE_PER_TOKEN, |
359| count one conflict for each token that has any reduce/reduce |
360| conflicts. Otherwise, count one conflict for each pair of |
361| conflicting reductions. |
362+`----------------------------------------------------------------*/
c29240e7 363
0df87bb6 364static int
676385e2 365count_rr_conflicts (state_t *state, int one_per_token)
08089d5d 366{
c29240e7 367 int i;
0df87bb6 368 int rrc_count = 0;
08089d5d 369
065fbd27 370 if (state->nlookaheads < 2)
0df87bb6 371 return 0;
08089d5d 372
08089d5d
DM
373 for (i = 0; i < ntokens; i++)
374 {
0df87bb6
AD
375 int count = 0;
376 int j;
065fbd27 377 for (j = 0; j < state->nlookaheads; ++j)
c0263492 378 if (bitset_test (state->lookaheads[j], i))
52afa962 379 count++;
08089d5d 380
c29240e7 381 if (count >= 2)
676385e2 382 rrc_count += one_per_token ? 1 : count-1;
08089d5d 383 }
0df87bb6
AD
384
385 return rrc_count;
08089d5d
DM
386}
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
AD
418
419 *cp++ = '.';
420 *cp++ = '\n';
421 *cp++ = '\0';
c29240e7 422
ff4423cc 423 return res;
c29240e7
AD
424}
425
426
0df87bb6
AD
427/*-----------------------------------------------------------.
428| Output the detailed description of states with conflicts. |
429`-----------------------------------------------------------*/
c29240e7
AD
430
431void
0df87bb6 432conflicts_output (FILE *out)
c29240e7 433{
d2d1b42b 434 bool printed_sth = FALSE;
640748ee 435 bool *used_rules = XCALLOC (bool, nrules);
d57650a5 436 state_number_t i;
0df87bb6 437 for (i = 0; i < nstates; i++)
640748ee
AD
438 {
439 state_t *s = states[i];
440 int j;
441 for (j = 0; j < s->reductions->num; ++j)
442 used_rules[s->reductions->rules[j]->number] = TRUE;
443 if (conflicts[i])
444 {
445 fprintf (out, _("State %d contains "), i);
446 fputs (conflict_report (count_sr_conflicts (s),
447 count_rr_conflicts (s, TRUE)), out);
448 printed_sth = TRUE;
449 }
450 }
d2d1b42b
AD
451 if (printed_sth)
452 fputs ("\n\n", out);
640748ee
AD
453
454 for (i = 0; i < nstates; i++)
455 {
456 state_t *s = states[i];
457 reductions_t *r = s->reductions;
458 int j;
459 for (j = 0; j < r->num; ++j)
460 if (!used_rules[r->rules[j]->number])
461 {
462 LOCATION_PRINT (stderr, r->rules[j]->location);
463 fprintf (stderr, ": %s: %s: ",
464 _("warning"),
465 _("rule never reduced because of conflicts"));
466 rule_print (r->rules[j], stderr);
467 }
468 }
469 free (used_rules);
0df87bb6 470}
c29240e7 471
676385e2
PH
472/*--------------------------------------------------------.
473| Total the number of S/R and R/R conflicts. Unlike the |
474| code in conflicts_output, however, count EACH pair of |
475| reductions for the same state and lookahead as one |
476| conflict. |
477`--------------------------------------------------------*/
478
479int
480conflicts_total_count (void)
481{
d57650a5 482 state_number_t i;
676385e2
PH
483 int count;
484
485 /* Conflicts by state. */
486 count = 0;
487 for (i = 0; i < nstates; i++)
488 if (conflicts[i])
489 {
490 count += count_sr_conflicts (states[i]);
491 count += count_rr_conflicts (states[i], FALSE);
492 }
493 return count;
494}
e0e5bf84 495
c29240e7 496
0df87bb6
AD
497/*------------------------------------------.
498| Reporting the total number of conflicts. |
499`------------------------------------------*/
0619caf0 500
0df87bb6
AD
501void
502conflicts_print (void)
503{
a034c8b8
AD
504 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
505 not set, and then we want 0 SR, or else it is specified, in which
506 case we want equality. */
507 int src_ok = 0;
508
0df87bb6
AD
509 int src_total = 0;
510 int rrc_total = 0;
511
512 /* Conflicts by state. */
d57650a5
AD
513 {
514 state_number_t i;
515
516 for (i = 0; i < nstates; i++)
517 if (conflicts[i])
518 {
519 src_total += count_sr_conflicts (states[i]);
520 rrc_total += count_rr_conflicts (states[i], TRUE);
521 }
522 }
c29240e7 523
a034c8b8
AD
524 src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
525
526 /* If there are no RR conflicts, and as many SR conflicts as
527 expected, then there is nothing to report. */
528 if (!rrc_total && src_ok)
529 return;
530
0619caf0 531 /* Report the total number of conflicts on STDERR. */
a034c8b8 532 if (yacc_flag)
09b503c8 533 {
a034c8b8
AD
534 /* If invoked with `--yacc', use the output format specified by
535 POSIX. */
536 fprintf (stderr, _("conflicts: "));
537 if (src_total > 0)
538 fprintf (stderr, _(" %d shift/reduce"), src_total);
539 if (src_total > 0 && rrc_total > 0)
540 fprintf (stderr, ",");
541 if (rrc_total > 0)
542 fprintf (stderr, _(" %d reduce/reduce"), rrc_total);
543 putc ('\n', stderr);
544 }
545 else
546 {
547 fprintf (stderr, _("%s contains "), infile);
548 fputs (conflict_report (src_total, rrc_total), stderr);
09b503c8 549 }
7da99ede 550
a034c8b8 551 if (expected_conflicts != -1 && !src_ok)
7da99ede
AD
552 {
553 complain_message_count++;
81e895c0
AD
554 fprintf (stderr, ngettext ("expected %d shift/reduce conflict\n",
555 "expected %d shift/reduce conflicts\n",
7da99ede
AD
556 expected_conflicts),
557 expected_conflicts);
558 }
c29240e7
AD
559}
560
561
08089d5d 562void
b408954b 563conflicts_free (void)
08089d5d 564{
d7913476 565 XFREE (conflicts);
b86796bf
AD
566 bitset_free (shiftset);
567 bitset_free (lookaheadset);
b408954b 568 obstack_free (&solved_conflicts_obstack, NULL);
08089d5d 569}