]> git.saurik.com Git - bison.git/blame - src/conflicts.c
(output_graph): G_VIEW -> normal_view in case someone
[bison.git] / src / conflicts.c
CommitLineData
08089d5d 1/* Find and resolve or report look-ahead conflicts for bison,
f041e30b 2
4f16766c 3 Copyright (C) 1984, 1989, 1992, 2000, 2001, 2002, 2003, 2004
03b31c0c 4 Free Software Foundation, Inc.
08089d5d 5
ceed8467 6 This file is part of Bison, the GNU Compiler Compiler.
08089d5d 7
ceed8467
AD
8 Bison is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
08089d5d 12
ceed8467
AD
13 Bison is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
08089d5d 17
ceed8467
AD
18 You should have received a copy of the GNU General Public License
19 along with Bison; see the file COPYING. If not, write to the Free
20 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA. */
08089d5d 22
08089d5d 23#include "system.h"
f041e30b
PE
24
25#include <bitset.h>
26
27#include "LR0.h"
7da99ede 28#include "complain.h"
f041e30b 29#include "conflicts.h"
08089d5d 30#include "files.h"
f041e30b 31#include "getargs.h"
08089d5d 32#include "gram.h"
720d742f 33#include "lalr.h"
b2ca4022 34#include "reader.h"
f041e30b
PE
35#include "state.h"
36#include "symtab.h"
d2729d44 37
7da99ede 38/* -1 stands for not specified. */
d6328241
PH
39int expected_sr_conflicts = -1;
40int expected_rr_conflicts = -1;
da2a7671 41static char *conflicts;
b408954b 42struct obstack solved_conflicts_obstack;
08089d5d 43
8dd162d3
PE
44static bitset shift_set;
45static bitset look_ahead_set;
b408954b 46
c29240e7 47\f
08089d5d 48
f041e30b 49enum conflict_resolution
b408954b
AD
50 {
51 shift_resolution,
52 reduce_resolution,
53 left_resolution,
54 right_resolution,
86eff183 55 nonassoc_resolution
b408954b
AD
56 };
57
58
9801d40c
AD
59/*----------------------------------------------------------------.
60| Explain how an SR conflict between TOKEN and RULE was resolved: |
61| RESOLUTION. |
62`----------------------------------------------------------------*/
63
c29240e7 64static inline void
f041e30b
PE
65log_resolution (rule *r, symbol_number token,
66 enum conflict_resolution resolution)
08089d5d 67{
b408954b
AD
68 if (report_flag & report_solved_conflicts)
69 {
70 /* The description of the resolution. */
71 switch (resolution)
72 {
73 case shift_resolution:
4b3d3a8e 74 case right_resolution:
b408954b
AD
75 obstack_fgrow2 (&solved_conflicts_obstack,
76 _("\
77 Conflict between rule %d and token %s resolved as shift"),
f041e30b 78 r->number,
b408954b
AD
79 symbols[token]->tag);
80 break;
81 case reduce_resolution:
4b3d3a8e 82 case left_resolution:
b408954b
AD
83 obstack_fgrow2 (&solved_conflicts_obstack,
84 _("\
85 Conflict between rule %d and token %s resolved as reduce"),
f041e30b 86 r->number,
b408954b
AD
87 symbols[token]->tag);
88 break;
89 case nonassoc_resolution:
90 obstack_fgrow2 (&solved_conflicts_obstack,
91 _("\
92 Conflict between rule %d and token %s resolved as an error"),
f041e30b 93 r->number,
b408954b
AD
94 symbols[token]->tag);
95 break;
96 }
97
98 /* The reason. */
99 switch (resolution)
100 {
101 case shift_resolution:
102 obstack_fgrow2 (&solved_conflicts_obstack,
103 " (%s < %s)",
f041e30b 104 r->prec->tag,
b408954b
AD
105 symbols[token]->tag);
106 break;
107
108 case reduce_resolution:
109 obstack_fgrow2 (&solved_conflicts_obstack,
110 " (%s < %s)",
111 symbols[token]->tag,
f041e30b 112 r->prec->tag);
b408954b
AD
113 break;
114
115 case left_resolution:
4a713ec2 116 obstack_fgrow1 (&solved_conflicts_obstack,
b408954b
AD
117 " (%%left %s)",
118 symbols[token]->tag);
119 break;
120
121 case right_resolution:
122 obstack_fgrow1 (&solved_conflicts_obstack,
123 " (%%right %s)",
124 symbols[token]->tag);
125 break;
126 case nonassoc_resolution:
127 obstack_fgrow1 (&solved_conflicts_obstack,
128 " (%%nonassoc %s)",
129 symbols[token]->tag);
130 break;
131 }
132 obstack_sgrow (&solved_conflicts_obstack, ".\n");
133 }
08089d5d
DM
134}
135
136
c29240e7
AD
137/*------------------------------------------------------------------.
138| Turn off the shift recorded for the specified token in the |
139| specified state. Used when we resolve a shift-reduce conflict in |
140| favor of the reduction. |
141`------------------------------------------------------------------*/
142
4a120d45 143static void
f041e30b 144flush_shift (state *s, int token)
08089d5d 145{
f041e30b 146 transitions *trans = s->transitions;
9f136c07 147 int i;
c29240e7 148
8dd162d3 149 bitset_reset (look_ahead_set, token);
f041e30b
PE
150 for (i = 0; i < trans->num; i++)
151 if (!TRANSITION_IS_DISABLED (trans, i)
152 && TRANSITION_SYMBOL (trans, i) == token)
153 TRANSITION_DISABLE (trans, i);
08089d5d
DM
154}
155
156
8dd162d3
PE
157/*--------------------------------------------------------------------.
158| Turn off the reduce recorded for the specified token for the |
159| specified look-ahead. Used when we resolve a shift-reduce conflict |
160| in favor of the shift. |
161`--------------------------------------------------------------------*/
709ae8c6
AD
162
163static void
8dd162d3 164flush_reduce (bitset look_ahead_tokens, int token)
709ae8c6 165{
8dd162d3 166 bitset_reset (look_ahead_tokens, token);
709ae8c6
AD
167}
168
169
c29240e7
AD
170/*------------------------------------------------------------------.
171| Attempt to resolve shift-reduce conflict for one rule by means of |
172| precedence declarations. It has already been checked that the |
173| rule has a precedence. A conflict is resolved by modifying the |
174| shift or reduce tables so that there is no longer a conflict. |
9801d40c 175| |
8dd162d3 176| RULENO is the number of the look-ahead bitset to consider. |
8b752b00 177| |
f041e30b 178| ERRORS can be used to store discovered explicit errors. |
c29240e7 179`------------------------------------------------------------------*/
08089d5d 180
4a120d45 181static void
f041e30b 182resolve_sr_conflict (state *s, int ruleno, symbol **errors)
08089d5d 183{
f041e30b
PE
184 symbol_number i;
185 reductions *reds = s->reductions;
9801d40c 186 /* Find the rule to reduce by to get precedence of reduction. */
f041e30b 187 rule *redrule = reds->rules[ruleno];
9801d40c 188 int redprec = redrule->prec->prec;
8dd162d3 189 bitset look_ahead_tokens = reds->look_ahead_tokens[ruleno];
8b752b00 190 int nerrs = 0;
08089d5d 191
08089d5d 192 for (i = 0; i < ntokens; i++)
8dd162d3
PE
193 if (bitset_test (look_ahead_tokens, i)
194 && bitset_test (look_ahead_set, i)
0e78e603 195 && symbols[i]->prec)
92b16366 196 {
709ae8c6
AD
197 /* Shift-reduce conflict occurs for token number i
198 and it has a precedence.
199 The precedence of shifting is that of token i. */
0e78e603 200 if (symbols[i]->prec < redprec)
92b16366 201 {
9801d40c 202 log_resolution (redrule, i, reduce_resolution);
f041e30b 203 flush_shift (s, i);
92b16366 204 }
0e78e603 205 else if (symbols[i]->prec > redprec)
92b16366 206 {
9801d40c 207 log_resolution (redrule, i, shift_resolution);
8dd162d3 208 flush_reduce (look_ahead_tokens, i);
92b16366
AD
209 }
210 else
709ae8c6
AD
211 /* Matching precedence levels.
212 For left association, keep only the reduction.
213 For right association, keep only the shift.
214 For nonassociation, keep neither. */
215
5a670b1e 216 switch (symbols[i]->assoc)
709ae8c6
AD
217 {
218 case right_assoc:
9801d40c 219 log_resolution (redrule, i, right_resolution);
8dd162d3 220 flush_reduce (look_ahead_tokens, i);
709ae8c6
AD
221 break;
222
223 case left_assoc:
9801d40c 224 log_resolution (redrule, i, left_resolution);
f041e30b 225 flush_shift (s, i);
709ae8c6
AD
226 break;
227
228 case non_assoc:
9801d40c 229 log_resolution (redrule, i, nonassoc_resolution);
f041e30b 230 flush_shift (s, i);
8dd162d3 231 flush_reduce (look_ahead_tokens, i);
709ae8c6 232 /* Record an explicit error for this token. */
f041e30b 233 errors[nerrs++] = symbols[i];
709ae8c6 234 break;
e9955c83
AD
235
236 case undef_assoc:
b9a01048 237 abort ();
709ae8c6 238 }
92b16366
AD
239 }
240
0de45ae5
PE
241 if (nerrs)
242 {
243 /* Some tokens have been explicitly made errors. Allocate a
244 permanent errs structure for this state, to record them. */
245 state_errs_set (s, nerrs, errors);
246 }
b408954b
AD
247
248 if (obstack_object_size (&solved_conflicts_obstack))
249 {
250 obstack_1grow (&solved_conflicts_obstack, '\0');
f041e30b 251 s->solved_conflicts = obstack_finish (&solved_conflicts_obstack);
b408954b 252 }
08089d5d
DM
253}
254
255
8b752b00 256/*-------------------------------------------------------------------.
f041e30b 257| Solve the S/R conflicts of state S using the |
8b752b00 258| precedence/associativity, and flag it inconsistent if it still has |
f041e30b 259| conflicts. ERRORS can be used as storage to compute the list of |
8dd162d3 260| look-ahead tokens on which S raises a syntax error (%nonassoc). |
8b752b00
AD
261`-------------------------------------------------------------------*/
262
4a120d45 263static void
f041e30b 264set_conflicts (state *s, symbol **errors)
08089d5d 265{
914feea9 266 int i;
f041e30b
PE
267 transitions *trans = s->transitions;
268 reductions *reds = s->reductions;
c29240e7 269
f041e30b 270 if (s->consistent)
c29240e7 271 return;
08089d5d 272
8dd162d3 273 bitset_zero (look_ahead_set);
08089d5d 274
f041e30b 275 FOR_EACH_SHIFT (trans, i)
8dd162d3 276 bitset_set (look_ahead_set, TRANSITION_SYMBOL (trans, i));
08089d5d 277
8dd162d3 278 /* Loop over all rules which require look-ahead in this state. First
c29240e7 279 check for shift-reduce conflict, and try to resolve using
9801d40c 280 precedence. */
cd08e51e
AD
281 for (i = 0; i < reds->num; ++i)
282 if (reds->rules[i]->prec && reds->rules[i]->prec->prec
8dd162d3 283 && !bitset_disjoint_p (reds->look_ahead_tokens[i], look_ahead_set))
0de45ae5 284 resolve_sr_conflict (s, i, errors);
08089d5d 285
8dd162d3 286 /* Loop over all rules which require look-ahead in this state. Check
c29240e7 287 for conflicts not resolved above. */
cd08e51e 288 for (i = 0; i < reds->num; ++i)
08089d5d 289 {
8dd162d3 290 if (!bitset_disjoint_p (reds->look_ahead_tokens[i], look_ahead_set))
f041e30b 291 conflicts[s->number] = 1;
08089d5d 292
8dd162d3 293 bitset_or (look_ahead_set, look_ahead_set, reds->look_ahead_tokens[i]);
c29240e7
AD
294 }
295}
08089d5d 296
8b752b00
AD
297
298/*----------------------------------------------------------------.
299| Solve all the S/R conflicts using the precedence/associativity, |
300| and flag as inconsistent the states that still have conflicts. |
301`----------------------------------------------------------------*/
302
08089d5d 303void
b408954b 304conflicts_solve (void)
08089d5d 305{
f041e30b 306 state_number i;
8dd162d3 307 /* List of look-ahead tokens on which we explicitly raise a syntax error. */
da2a7671 308 symbol **errors = xnmalloc (ntokens + 1, sizeof *errors);
08089d5d 309
da2a7671 310 conflicts = xcalloc (nstates, sizeof *conflicts);
8dd162d3
PE
311 shift_set = bitset_create (ntokens, BITSET_FIXED);
312 look_ahead_set = bitset_create (ntokens, BITSET_FIXED);
b408954b 313 obstack_init (&solved_conflicts_obstack);
08089d5d 314
c29240e7 315 for (i = 0; i < nstates; i++)
8b752b00 316 {
f041e30b 317 set_conflicts (states[i], errors);
8b752b00
AD
318
319 /* For uniformity of the code, make sure all the states have a valid
320 `errs' member. */
321 if (!states[i]->errs)
322 states[i]->errs = errs_new (0, 0);
323 }
324
f041e30b 325 free (errors);
08089d5d
DM
326}
327
328
c29240e7
AD
329/*---------------------------------------------.
330| Count the number of shift/reduce conflicts. |
331`---------------------------------------------*/
332
0df87bb6 333static int
f041e30b 334count_sr_conflicts (state *s)
08089d5d 335{
f9abaa2c 336 int i;
0df87bb6 337 int src_count = 0;
f041e30b
PE
338 transitions *trans = s->transitions;
339 reductions *reds = s->reductions;
08089d5d 340
f041e30b 341 if (!trans)
0df87bb6 342 return 0;
08089d5d 343
8dd162d3
PE
344 bitset_zero (look_ahead_set);
345 bitset_zero (shift_set);
08089d5d 346
f041e30b 347 FOR_EACH_SHIFT (trans, i)
8dd162d3 348 bitset_set (shift_set, TRANSITION_SYMBOL (trans, i));
08089d5d 349
cd08e51e 350 for (i = 0; i < reds->num; ++i)
8dd162d3 351 bitset_or (look_ahead_set, look_ahead_set, reds->look_ahead_tokens[i]);
08089d5d 352
8dd162d3 353 bitset_and (look_ahead_set, look_ahead_set, shift_set);
08089d5d 354
8dd162d3 355 src_count = bitset_count (look_ahead_set);
0df87bb6
AD
356
357 return src_count;
08089d5d
DM
358}
359
360
676385e2
PH
361/*----------------------------------------------------------------.
362| Count the number of reduce/reduce conflicts. If ONE_PER_TOKEN, |
363| count one conflict for each token that has any reduce/reduce |
364| conflicts. Otherwise, count one conflict for each pair of |
365| conflicting reductions. |
366+`----------------------------------------------------------------*/
c29240e7 367
0df87bb6 368static int
d0829076 369count_rr_conflicts (state *s, bool one_per_token)
08089d5d 370{
c29240e7 371 int i;
f041e30b 372 reductions *reds = s->reductions;
0df87bb6 373 int rrc_count = 0;
08089d5d 374
08089d5d
DM
375 for (i = 0; i < ntokens; i++)
376 {
0df87bb6
AD
377 int count = 0;
378 int j;
cd08e51e 379 for (j = 0; j < reds->num; ++j)
8dd162d3 380 if (bitset_test (reds->look_ahead_tokens[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
52489d44 390
be728048
PE
391/*--------------------------------------------------------.
392| Report the number of conflicts, using the Yacc format. |
393`--------------------------------------------------------*/
52489d44
AD
394
395static void
be728048 396conflict_report (FILE *out, int src_num, int rrc_num)
52489d44 397{
be728048
PE
398 if (src_num && rrc_num)
399 fprintf (out, _("conflicts: %d shift/reduce, %d reduce/reduce\n"),
400 src_num, rrc_num);
401 else if (src_num)
402 fprintf (out, _("conflicts: %d shift/reduce\n"), src_num);
403 else if (rrc_num)
404 fprintf (out, _("conflicts: %d reduce/reduce\n"), rrc_num);
52489d44
AD
405}
406
407
0df87bb6
AD
408/*-----------------------------------------------------------.
409| Output the detailed description of states with conflicts. |
410`-----------------------------------------------------------*/
c29240e7
AD
411
412void
0df87bb6 413conflicts_output (FILE *out)
c29240e7 414{
8307162d 415 bool printed_sth = false;
f041e30b 416 state_number i;
0df87bb6 417 for (i = 0; i < nstates; i++)
640748ee 418 {
f041e30b 419 state *s = states[i];
640748ee
AD
420 if (conflicts[i])
421 {
be728048
PE
422 fprintf (out, _("State %d "), i);
423 conflict_report (out, count_sr_conflicts (s),
424 count_rr_conflicts (s, true));
8307162d 425 printed_sth = true;
640748ee
AD
426 }
427 }
d2d1b42b
AD
428 if (printed_sth)
429 fputs ("\n\n", out);
0df87bb6 430}
c29240e7 431
676385e2
PH
432/*--------------------------------------------------------.
433| Total the number of S/R and R/R conflicts. Unlike the |
434| code in conflicts_output, however, count EACH pair of |
8dd162d3 435| reductions for the same state and look-ahead as one |
676385e2
PH
436| conflict. |
437`--------------------------------------------------------*/
438
439int
440conflicts_total_count (void)
441{
f041e30b 442 state_number i;
676385e2
PH
443 int count;
444
445 /* Conflicts by state. */
446 count = 0;
447 for (i = 0; i < nstates; i++)
448 if (conflicts[i])
449 {
450 count += count_sr_conflicts (states[i]);
8307162d 451 count += count_rr_conflicts (states[i], false);
676385e2
PH
452 }
453 return count;
454}
e0e5bf84 455
c29240e7 456
0df87bb6
AD
457/*------------------------------------------.
458| Reporting the total number of conflicts. |
459`------------------------------------------*/
0619caf0 460
0df87bb6
AD
461void
462conflicts_print (void)
463{
a034c8b8
AD
464 /* Is the number of SR conflicts OK? Either EXPECTED_CONFLICTS is
465 not set, and then we want 0 SR, or else it is specified, in which
466 case we want equality. */
d0829076 467 bool src_ok = false;
d6328241 468 bool rrc_ok = false;
a034c8b8 469
0df87bb6
AD
470 int src_total = 0;
471 int rrc_total = 0;
472
473 /* Conflicts by state. */
d57650a5 474 {
f041e30b 475 state_number i;
d57650a5
AD
476
477 for (i = 0; i < nstates; i++)
478 if (conflicts[i])
479 {
480 src_total += count_sr_conflicts (states[i]);
8307162d 481 rrc_total += count_rr_conflicts (states[i], true);
d57650a5
AD
482 }
483 }
c29240e7 484
d6328241
PH
485 if (! glr_parser && rrc_total > 0 && expected_rr_conflicts != -1)
486 {
4f16766c 487 warn (_("%%expect-rr applies only to GLR parsers"));
d6328241
PH
488 expected_rr_conflicts = -1;
489 }
490
afbb696d 491 src_ok =
d6328241 492 src_total == (expected_sr_conflicts == -1 ? 0 : expected_sr_conflicts);
afbb696d 493 rrc_ok =
d6328241 494 rrc_total == (expected_rr_conflicts == -1 ? 0 : expected_rr_conflicts);
a034c8b8 495
d6328241 496 /* If there are as many RR conflicts and SR conflicts as
a034c8b8 497 expected, then there is nothing to report. */
d6328241 498 if (rrc_ok && src_ok)
a034c8b8
AD
499 return;
500
0619caf0 501 /* Report the total number of conflicts on STDERR. */
be728048
PE
502 if (! yacc_flag)
503 fprintf (stderr, "%s: ", current_file);
504 conflict_report (stderr, src_total, rrc_total);
7da99ede 505
d6328241 506 if (expected_sr_conflicts != -1 || expected_rr_conflicts != -1)
76be9271 507 {
d6328241
PH
508 int sr = expected_sr_conflicts == -1 ? 0 : expected_sr_conflicts;
509 int rr = expected_rr_conflicts == -1 ? 0 : expected_rr_conflicts;
76be9271 510 if (! src_ok)
69363a9e
PE
511 warn (ngettext ("expected %d shift/reduce conflict",
512 "expected %d shift/reduce conflicts",
d6328241
PH
513 sr), sr);
514 if (! rrc_ok)
515 warn (ngettext ("expected %d reduce/reduce conflict",
516 "expected %d reduce/reduce conflicts",
517 rr), rr);
76be9271 518 }
c29240e7
AD
519}
520
521
08089d5d 522void
b408954b 523conflicts_free (void)
08089d5d 524{
afbb696d 525 free (conflicts);
8dd162d3
PE
526 bitset_free (shift_set);
527 bitset_free (look_ahead_set);
b408954b 528 obstack_free (&solved_conflicts_obstack, NULL);
08089d5d 529}