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