]> git.saurik.com Git - bison.git/blame - src/conflicts.c
(EXTRA_DIST): Avoid +=, a GNU make extension.
[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:
234 assert (symbols[i]->assoc != undef_assoc);
235 break;
709ae8c6 236 }
92b16366
AD
237 }
238
92b16366
AD
239 /* Some tokens have been explicitly made errors. Allocate a
240 permanent errs structure for this state, to record them. */
8b752b00 241 state_errs_set (state, nerrs, errs);
b408954b
AD
242
243 if (obstack_object_size (&solved_conflicts_obstack))
244 {
245 obstack_1grow (&solved_conflicts_obstack, '\0');
246 state->solved_conflicts = obstack_finish (&solved_conflicts_obstack);
247 }
08089d5d
DM
248}
249
250
8b752b00
AD
251/*-------------------------------------------------------------------.
252| Solve the S/R conflicts of STATE using the |
253| precedence/associativity, and flag it inconsistent if it still has |
254| conflicts. ERRS can be used as storage to compute the list of |
255| lookaheads on which this STATE raises a parse error (%nonassoc). |
256`-------------------------------------------------------------------*/
257
4a120d45 258static void
640748ee 259set_conflicts (state_t *state, symbol_t **errs)
08089d5d 260{
914feea9 261 int i;
8b752b00 262 transitions_t *transitions = state->transitions;
cd08e51e 263 reductions_t *reds = state->reductions;
c29240e7 264
065fbd27 265 if (state->consistent)
c29240e7 266 return;
08089d5d 267
b86796bf 268 bitset_zero (lookaheadset);
08089d5d 269
640748ee
AD
270 FOR_EACH_SHIFT (transitions, i)
271 bitset_set (lookaheadset, TRANSITION_SYMBOL (transitions, i));
08089d5d 272
c29240e7
AD
273 /* Loop over all rules which require lookahead in this state. First
274 check for shift-reduce conflict, and try to resolve using
9801d40c 275 precedence. */
cd08e51e
AD
276 for (i = 0; i < reds->num; ++i)
277 if (reds->rules[i]->prec && reds->rules[i]->prec->prec
278 && !bitset_disjoint_p (reds->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. */
cd08e51e 286 for (i = 0; i < reds->num; ++i)
08089d5d 287 {
cd08e51e 288 if (!bitset_disjoint_p (reds->lookaheads[i], lookaheadset))
914feea9 289 conflicts[state->number] = 1;
08089d5d 290
cd08e51e 291 bitset_or (lookaheadset, lookaheadset, reds->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 305 /* List of lookaheads on which we explicitly raise a parse error. */
640748ee 306 symbol_t **errs = XMALLOC (symbol_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;
cd08e51e 337 reductions_t *reds = state->reductions;
08089d5d 338
ccaf65bc 339 if (!transitions)
0df87bb6 340 return 0;
08089d5d 341
b86796bf
AD
342 bitset_zero (lookaheadset);
343 bitset_zero (shiftset);
08089d5d 344
640748ee
AD
345 FOR_EACH_SHIFT (transitions, i)
346 bitset_set (shiftset, TRANSITION_SYMBOL (transitions, i));
08089d5d 347
cd08e51e
AD
348 for (i = 0; i < reds->num; ++i)
349 bitset_or (lookaheadset, lookaheadset, reds->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;
cd08e51e 370 reductions_t *reds = state->reductions;
0df87bb6 371 int rrc_count = 0;
08089d5d 372
08089d5d
DM
373 for (i = 0; i < ntokens; i++)
374 {
0df87bb6
AD
375 int count = 0;
376 int j;
cd08e51e
AD
377 for (j = 0; j < reds->num; ++j)
378 if (bitset_test (reds->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
52489d44 388
ff4423cc
AD
389/*--------------------------------------------------------------.
390| Return a human readable string which reports shift/reduce and |
391| reduce/reduce conflict numbers (SRC_NUM, RRC_NUM). |
392`--------------------------------------------------------------*/
c29240e7 393
ff4423cc
AD
394static const char *
395conflict_report (int src_num, int rrc_num)
c29240e7 396{
ff4423cc
AD
397 static char res[4096];
398 char *cp = res;
399
7da99ede 400 if (src_num >= 1)
22c821f3 401 {
7da99ede
AD
402 sprintf (cp, ngettext ("%d shift/reduce conflict",
403 "%d shift/reduce conflicts", src_num), src_num);
22c821f3
AD
404 cp += strlen (cp);
405 }
c29240e7 406
0619caf0 407 if (src_num > 0 && rrc_num > 0)
22c821f3 408 {
7da99ede 409 sprintf (cp, " %s ", _("and"));
22c821f3
AD
410 cp += strlen (cp);
411 }
c29240e7 412
7da99ede 413 if (rrc_num >= 1)
22c821f3 414 {
7da99ede
AD
415 sprintf (cp, ngettext ("%d reduce/reduce conflict",
416 "%d reduce/reduce conflicts", rrc_num), rrc_num);
22c821f3
AD
417 cp += strlen (cp);
418 }
ff4423cc 419
ff4423cc 420 *cp++ = '\0';
c29240e7 421
ff4423cc 422 return res;
c29240e7
AD
423}
424
425
52489d44
AD
426/*----------------------------------------------------------------.
427| Same as above, but report the number of conflicts a` la POSIX. |
428`----------------------------------------------------------------*/
429
430static void
431conflict_report_yacc (int src_num, int rrc_num)
432{
433 /* If invoked with `--yacc', use the output format specified by
434 POSIX. */
435 fprintf (stderr, _("conflicts: "));
436 if (src_num > 0)
437 fprintf (stderr, _(" %d shift/reduce"), src_num);
438 if (src_num > 0 && rrc_num > 0)
439 fprintf (stderr, ",");
440 if (rrc_num > 0)
441 fprintf (stderr, _(" %d reduce/reduce"), rrc_num);
442 putc ('\n', stderr);
443}
444
445
0df87bb6
AD
446/*-----------------------------------------------------------.
447| Output the detailed description of states with conflicts. |
448`-----------------------------------------------------------*/
c29240e7
AD
449
450void
0df87bb6 451conflicts_output (FILE *out)
c29240e7 452{
d2d1b42b 453 bool printed_sth = FALSE;
d57650a5 454 state_number_t i;
0df87bb6 455 for (i = 0; i < nstates; i++)
640748ee
AD
456 {
457 state_t *s = states[i];
640748ee
AD
458 if (conflicts[i])
459 {
460 fprintf (out, _("State %d contains "), i);
52489d44
AD
461 fprintf (out, "%s.\n",
462 conflict_report (count_sr_conflicts (s),
463 count_rr_conflicts (s, TRUE)));
640748ee
AD
464 printed_sth = TRUE;
465 }
466 }
d2d1b42b
AD
467 if (printed_sth)
468 fputs ("\n\n", out);
0df87bb6 469}
c29240e7 470
676385e2
PH
471/*--------------------------------------------------------.
472| Total the number of S/R and R/R conflicts. Unlike the |
473| code in conflicts_output, however, count EACH pair of |
474| reductions for the same state and lookahead as one |
475| conflict. |
476`--------------------------------------------------------*/
477
478int
479conflicts_total_count (void)
480{
d57650a5 481 state_number_t i;
676385e2
PH
482 int count;
483
484 /* Conflicts by state. */
485 count = 0;
486 for (i = 0; i < nstates; i++)
487 if (conflicts[i])
488 {
489 count += count_sr_conflicts (states[i]);
490 count += count_rr_conflicts (states[i], FALSE);
491 }
492 return count;
493}
e0e5bf84 494
c29240e7 495
0df87bb6
AD
496/*------------------------------------------.
497| Reporting the total number of conflicts. |
498`------------------------------------------*/
0619caf0 499
0df87bb6
AD
500void
501conflicts_print (void)
502{
a034c8b8
AD
503 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
504 not set, and then we want 0 SR, or else it is specified, in which
505 case we want equality. */
506 int src_ok = 0;
507
0df87bb6
AD
508 int src_total = 0;
509 int rrc_total = 0;
510
511 /* Conflicts by state. */
d57650a5
AD
512 {
513 state_number_t i;
514
515 for (i = 0; i < nstates; i++)
516 if (conflicts[i])
517 {
518 src_total += count_sr_conflicts (states[i]);
519 rrc_total += count_rr_conflicts (states[i], TRUE);
520 }
521 }
c29240e7 522
a034c8b8
AD
523 src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
524
525 /* If there are no RR conflicts, and as many SR conflicts as
526 expected, then there is nothing to report. */
527 if (!rrc_total && src_ok)
528 return;
529
0619caf0 530 /* Report the total number of conflicts on STDERR. */
a034c8b8 531 if (yacc_flag)
52489d44 532 conflict_report_yacc (src_total, rrc_total);
a034c8b8 533 else
52489d44 534 warn ("%s", conflict_report (src_total, rrc_total));
7da99ede 535
a034c8b8 536 if (expected_conflicts != -1 && !src_ok)
52489d44
AD
537 complain (ngettext ("expected %d shift/reduce conflict",
538 "expected %d shift/reduce conflicts",
539 expected_conflicts),
540 expected_conflicts);
c29240e7
AD
541}
542
543
08089d5d 544void
b408954b 545conflicts_free (void)
08089d5d 546{
d7913476 547 XFREE (conflicts);
b86796bf
AD
548 bitset_free (shiftset);
549 bitset_free (lookaheadset);
b408954b 550 obstack_free (&solved_conflicts_obstack, NULL);
08089d5d 551}