]> git.saurik.com Git - bison.git/blame - src/conflicts.c
Work around portability problem on Solaris 10: flex-generated
[bison.git] / src / conflicts.c
CommitLineData
08089d5d 1/* Find and resolve or report look-ahead conflicts for bison,
f041e30b 2
035aa4a0 3 Copyright (C) 1984, 1989, 1992, 2000, 2001, 2002, 2003, 2004, 2005
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;
b408954b 43struct obstack solved_conflicts_obstack;
08089d5d 44
8dd162d3
PE
45static bitset shift_set;
46static bitset look_ahead_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
8dd162d3 150 bitset_reset (look_ahead_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 |
160| specified look-ahead. Used when we resolve a shift-reduce conflict |
161| in favor of the shift. |
162`--------------------------------------------------------------------*/
709ae8c6
AD
163
164static void
8dd162d3 165flush_reduce (bitset look_ahead_tokens, int token)
709ae8c6 166{
8dd162d3 167 bitset_reset (look_ahead_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| |
8dd162d3 177| RULENO is the number of the look-ahead 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;
8dd162d3 190 bitset look_ahead_tokens = reds->look_ahead_tokens[ruleno];
8b752b00 191 int nerrs = 0;
08089d5d 192
08089d5d 193 for (i = 0; i < ntokens; i++)
8dd162d3
PE
194 if (bitset_test (look_ahead_tokens, i)
195 && bitset_test (look_ahead_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);
8dd162d3 209 flush_reduce (look_ahead_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
AD
218 {
219 case right_assoc:
9801d40c 220 log_resolution (redrule, i, right_resolution);
8dd162d3 221 flush_reduce (look_ahead_tokens, i);
709ae8c6
AD
222 break;
223
224 case left_assoc:
9801d40c 225 log_resolution (redrule, i, left_resolution);
f041e30b 226 flush_shift (s, i);
709ae8c6
AD
227 break;
228
229 case non_assoc:
9801d40c 230 log_resolution (redrule, i, nonassoc_resolution);
f041e30b 231 flush_shift (s, i);
8dd162d3 232 flush_reduce (look_ahead_tokens, i);
709ae8c6 233 /* Record an explicit error for this token. */
f041e30b 234 errors[nerrs++] = symbols[i];
709ae8c6 235 break;
e9955c83
AD
236
237 case undef_assoc:
b9a01048 238 abort ();
709ae8c6 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 |
8dd162d3 261| look-ahead 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
8dd162d3 274 bitset_zero (look_ahead_set);
08089d5d 275
f041e30b 276 FOR_EACH_SHIFT (trans, i)
8dd162d3 277 bitset_set (look_ahead_set, TRANSITION_SYMBOL (trans, i));
08089d5d 278
8dd162d3 279 /* Loop over all rules which require look-ahead 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
8dd162d3 284 && !bitset_disjoint_p (reds->look_ahead_tokens[i], look_ahead_set))
0de45ae5 285 resolve_sr_conflict (s, i, errors);
08089d5d 286
8dd162d3 287 /* Loop over all rules which require look-ahead in this state. Check
c29240e7 288 for conflicts not resolved above. */
cd08e51e 289 for (i = 0; i < reds->num; ++i)
08089d5d 290 {
8dd162d3 291 if (!bitset_disjoint_p (reds->look_ahead_tokens[i], look_ahead_set))
f041e30b 292 conflicts[s->number] = 1;
08089d5d 293
8dd162d3 294 bitset_or (look_ahead_set, look_ahead_set, reds->look_ahead_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;
8dd162d3 308 /* List of look-ahead 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
PE
312 shift_set = bitset_create (ntokens, BITSET_FIXED);
313 look_ahead_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
8dd162d3
PE
345 bitset_zero (look_ahead_set);
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)
8dd162d3 352 bitset_or (look_ahead_set, look_ahead_set, reds->look_ahead_tokens[i]);
08089d5d 353
8dd162d3 354 bitset_and (look_ahead_set, look_ahead_set, shift_set);
08089d5d 355
8dd162d3 356 src_count = bitset_count (look_ahead_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)
8dd162d3 381 if (bitset_test (reds->look_ahead_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 |
8dd162d3 436| reductions for the same state and look-ahead 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
PE
532 bitset_free (shift_set);
533 bitset_free (look_ahead_set);
b408954b 534 obstack_free (&solved_conflicts_obstack, NULL);
08089d5d 535}