]> git.saurik.com Git - bison.git/blame - src/conflicts.c
Stop storing rules from 1 to nrules + 1.
[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
AD
178resolve_sr_conflict (state_t *state, int lookahead,
179 symbol_number_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. */
8b752b00 229 errs[nerrs++] = 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
8b752b00 258set_conflicts (state_t *state, symbol_number_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
ccaf65bc
AD
268 for (i = 0; i < transitions->num && TRANSITION_IS_SHIFT (transitions, i); i++)
269 if (!TRANSITION_IS_DISABLED (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. */
065fbd27 275 for (i = 0; i < state->nlookaheads; ++i)
c0263492
AD
276 if (state->lookaheads_rule[i]->prec
277 && state->lookaheads_rule[i]->prec->prec
278 && !bitset_disjoint_p (state->lookaheads[i], lookaheadset))
914feea9 279 {
8b752b00 280 resolve_sr_conflict (state, i, errs);
914feea9
AD
281 break;
282 }
08089d5d 283
c29240e7
AD
284 /* Loop over all rules which require lookahead in this state. Check
285 for conflicts not resolved above. */
065fbd27 286 for (i = 0; i < state->nlookaheads; ++i)
08089d5d 287 {
c0263492 288 if (!bitset_disjoint_p (state->lookaheads[i], lookaheadset))
914feea9 289 conflicts[state->number] = 1;
08089d5d 290
c0263492 291 bitset_or (lookaheadset, lookaheadset, state->lookaheads[i]);
c29240e7
AD
292 }
293}
08089d5d 294
8b752b00
AD
295
296/*----------------------------------------------------------------.
297| Solve all the S/R conflicts using the precedence/associativity, |
298| and flag as inconsistent the states that still have conflicts. |
299`----------------------------------------------------------------*/
300
08089d5d 301void
b408954b 302conflicts_solve (void)
08089d5d 303{
d57650a5 304 state_number_t i;
8b752b00
AD
305 /* List of lookaheads on which we explicitly raise a parse error. */
306 symbol_number_t *errs = XMALLOC (symbol_number_t, ntokens + 1);
08089d5d 307
d7913476 308 conflicts = XCALLOC (char, nstates);
b86796bf 309 shiftset = bitset_create (ntokens, BITSET_FIXED);
b86796bf 310 lookaheadset = bitset_create (ntokens, BITSET_FIXED);
b408954b 311 obstack_init (&solved_conflicts_obstack);
08089d5d 312
c29240e7 313 for (i = 0; i < nstates; i++)
8b752b00
AD
314 {
315 set_conflicts (states[i], errs);
316
317 /* For uniformity of the code, make sure all the states have a valid
318 `errs' member. */
319 if (!states[i]->errs)
320 states[i]->errs = errs_new (0, 0);
321 }
322
323 free (errs);
08089d5d
DM
324}
325
326
c29240e7
AD
327/*---------------------------------------------.
328| Count the number of shift/reduce conflicts. |
329`---------------------------------------------*/
330
0df87bb6 331static int
065fbd27 332count_sr_conflicts (state_t *state)
08089d5d 333{
f9abaa2c 334 int i;
0df87bb6 335 int src_count = 0;
8b752b00 336 transitions_t *transitions = state->transitions;
08089d5d 337
ccaf65bc 338 if (!transitions)
0df87bb6 339 return 0;
08089d5d 340
b86796bf
AD
341 bitset_zero (lookaheadset);
342 bitset_zero (shiftset);
08089d5d 343
ccaf65bc
AD
344 for (i = 0; i < transitions->num && TRANSITION_IS_SHIFT (transitions, i); i++)
345 if (!TRANSITION_IS_DISABLED (transitions, i))
346 bitset_set (shiftset, TRANSITION_SYMBOL (transitions, i));
08089d5d 347
065fbd27 348 for (i = 0; i < state->nlookaheads; ++i)
c0263492 349 bitset_or (lookaheadset, lookaheadset, state->lookaheads[i]);
08089d5d 350
b86796bf 351 bitset_and (lookaheadset, lookaheadset, shiftset);
08089d5d 352
914feea9 353 src_count = bitset_count (lookaheadset);
0df87bb6
AD
354
355 return src_count;
08089d5d
DM
356}
357
358
676385e2
PH
359/*----------------------------------------------------------------.
360| Count the number of reduce/reduce conflicts. If ONE_PER_TOKEN, |
361| count one conflict for each token that has any reduce/reduce |
362| conflicts. Otherwise, count one conflict for each pair of |
363| conflicting reductions. |
364+`----------------------------------------------------------------*/
c29240e7 365
0df87bb6 366static int
676385e2 367count_rr_conflicts (state_t *state, int one_per_token)
08089d5d 368{
c29240e7 369 int i;
0df87bb6 370 int rrc_count = 0;
08089d5d 371
065fbd27 372 if (state->nlookaheads < 2)
0df87bb6 373 return 0;
08089d5d 374
08089d5d
DM
375 for (i = 0; i < ntokens; i++)
376 {
0df87bb6
AD
377 int count = 0;
378 int j;
065fbd27 379 for (j = 0; j < state->nlookaheads; ++j)
c0263492 380 if (bitset_test (state->lookaheads[j], i))
52afa962 381 count++;
08089d5d 382
c29240e7 383 if (count >= 2)
676385e2 384 rrc_count += one_per_token ? 1 : count-1;
08089d5d 385 }
0df87bb6
AD
386
387 return rrc_count;
08089d5d
DM
388}
389
ff4423cc
AD
390/*--------------------------------------------------------------.
391| Return a human readable string which reports shift/reduce and |
392| reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
393`--------------------------------------------------------------*/
c29240e7 394
ff4423cc
AD
395static const char *
396conflict_report (int src_num, int rrc_num)
c29240e7 397{
ff4423cc
AD
398 static char res[4096];
399 char *cp = res;
400
7da99ede 401 if (src_num >= 1)
22c821f3 402 {
7da99ede
AD
403 sprintf (cp, ngettext ("%d shift/reduce conflict",
404 "%d shift/reduce conflicts", src_num), src_num);
22c821f3
AD
405 cp += strlen (cp);
406 }
c29240e7 407
0619caf0 408 if (src_num > 0 && rrc_num > 0)
22c821f3 409 {
7da99ede 410 sprintf (cp, " %s ", _("and"));
22c821f3
AD
411 cp += strlen (cp);
412 }
c29240e7 413
7da99ede 414 if (rrc_num >= 1)
22c821f3 415 {
7da99ede
AD
416 sprintf (cp, ngettext ("%d reduce/reduce conflict",
417 "%d reduce/reduce conflicts", rrc_num), rrc_num);
22c821f3
AD
418 cp += strlen (cp);
419 }
ff4423cc
AD
420
421 *cp++ = '.';
422 *cp++ = '\n';
423 *cp++ = '\0';
c29240e7 424
ff4423cc 425 return res;
c29240e7
AD
426}
427
428
0df87bb6
AD
429/*-----------------------------------------------------------.
430| Output the detailed description of states with conflicts. |
431`-----------------------------------------------------------*/
c29240e7
AD
432
433void
0df87bb6 434conflicts_output (FILE *out)
c29240e7 435{
d2d1b42b 436 bool printed_sth = FALSE;
d57650a5 437 state_number_t i;
0df87bb6
AD
438 for (i = 0; i < nstates; i++)
439 if (conflicts[i])
440 {
7da99ede 441 fprintf (out, _("State %d contains "), i);
29e88316 442 fputs (conflict_report (count_sr_conflicts (states[i]),
676385e2 443 count_rr_conflicts (states[i], TRUE)), out);
d2d1b42b 444 printed_sth = TRUE;
0df87bb6 445 }
d2d1b42b
AD
446 if (printed_sth)
447 fputs ("\n\n", out);
0df87bb6 448}
c29240e7 449
676385e2
PH
450/*--------------------------------------------------------.
451| Total the number of S/R and R/R conflicts. Unlike the |
452| code in conflicts_output, however, count EACH pair of |
453| reductions for the same state and lookahead as one |
454| conflict. |
455`--------------------------------------------------------*/
456
457int
458conflicts_total_count (void)
459{
d57650a5 460 state_number_t i;
676385e2
PH
461 int count;
462
463 /* Conflicts by state. */
464 count = 0;
465 for (i = 0; i < nstates; i++)
466 if (conflicts[i])
467 {
468 count += count_sr_conflicts (states[i]);
469 count += count_rr_conflicts (states[i], FALSE);
470 }
471 return count;
472}
e0e5bf84 473
c29240e7 474
0df87bb6
AD
475/*------------------------------------------.
476| Reporting the total number of conflicts. |
477`------------------------------------------*/
0619caf0 478
0df87bb6
AD
479void
480conflicts_print (void)
481{
a034c8b8
AD
482 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
483 not set, and then we want 0 SR, or else it is specified, in which
484 case we want equality. */
485 int src_ok = 0;
486
0df87bb6
AD
487 int src_total = 0;
488 int rrc_total = 0;
489
490 /* Conflicts by state. */
d57650a5
AD
491 {
492 state_number_t i;
493
494 for (i = 0; i < nstates; i++)
495 if (conflicts[i])
496 {
497 src_total += count_sr_conflicts (states[i]);
498 rrc_total += count_rr_conflicts (states[i], TRUE);
499 }
500 }
c29240e7 501
a034c8b8
AD
502 src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
503
504 /* If there are no RR conflicts, and as many SR conflicts as
505 expected, then there is nothing to report. */
506 if (!rrc_total && src_ok)
507 return;
508
0619caf0 509 /* Report the total number of conflicts on STDERR. */
a034c8b8 510 if (yacc_flag)
09b503c8 511 {
a034c8b8
AD
512 /* If invoked with `--yacc', use the output format specified by
513 POSIX. */
514 fprintf (stderr, _("conflicts: "));
515 if (src_total > 0)
516 fprintf (stderr, _(" %d shift/reduce"), src_total);
517 if (src_total > 0 && rrc_total > 0)
518 fprintf (stderr, ",");
519 if (rrc_total > 0)
520 fprintf (stderr, _(" %d reduce/reduce"), rrc_total);
521 putc ('\n', stderr);
522 }
523 else
524 {
525 fprintf (stderr, _("%s contains "), infile);
526 fputs (conflict_report (src_total, rrc_total), stderr);
09b503c8 527 }
7da99ede 528
a034c8b8 529 if (expected_conflicts != -1 && !src_ok)
7da99ede
AD
530 {
531 complain_message_count++;
81e895c0
AD
532 fprintf (stderr, ngettext ("expected %d shift/reduce conflict\n",
533 "expected %d shift/reduce conflicts\n",
7da99ede
AD
534 expected_conflicts),
535 expected_conflicts);
536 }
c29240e7
AD
537}
538
539
08089d5d 540void
b408954b 541conflicts_free (void)
08089d5d 542{
d7913476 543 XFREE (conflicts);
b86796bf
AD
544 bitset_free (shiftset);
545 bitset_free (lookaheadset);
b408954b 546 obstack_free (&solved_conflicts_obstack, NULL);
08089d5d 547}